diff --git a/.changeset/beige-eagles-cheat.md b/.changeset/beige-eagles-cheat.md deleted file mode 100644 index 5b5081d2ee..0000000000 --- a/.changeset/beige-eagles-cheat.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli-node': patch ---- - -Updated doc link. diff --git a/.changeset/blue-hairs-marry.md b/.changeset/blue-hairs-marry.md deleted file mode 100644 index 2ca1a3d47e..0000000000 --- a/.changeset/blue-hairs-marry.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli-node': patch ---- - -Added new plugin metadata fields to `BackstagePackageJson` type. diff --git a/.changeset/brave-apples-move.md b/.changeset/brave-apples-move.md deleted file mode 100644 index 7a1fa86a56..0000000000 --- a/.changeset/brave-apples-move.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-app-api': patch ---- - -Fixed a potential crash when passing an object with a `null` prototype as log meta. diff --git a/.changeset/breezy-badgers-train.md b/.changeset/breezy-badgers-train.md deleted file mode 100644 index 8f747b8602..0000000000 --- a/.changeset/breezy-badgers-train.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli-node': patch ---- - -Upgraded @yarnpkg/parsers to stable 3.0 diff --git a/.changeset/breezy-planets-sparkle.md b/.changeset/breezy-planets-sparkle.md deleted file mode 100644 index eea9e5c6bf..0000000000 --- a/.changeset/breezy-planets-sparkle.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-auth-backend-module-onelogin-provider': minor ---- - -Separate out the OneLogin provider into its own module diff --git a/.changeset/bright-panthers-leave.md b/.changeset/bright-panthers-leave.md new file mode 100644 index 0000000000..35d9c0f869 --- /dev/null +++ b/.changeset/bright-panthers-leave.md @@ -0,0 +1,6 @@ +--- +'@backstage/backend-plugin-api': patch +'@backstage/backend-defaults': patch +--- + +Added a new Root Health Service which adds new endpoints for health checks. diff --git a/.changeset/brown-bananas-talk.md b/.changeset/brown-bananas-talk.md deleted file mode 100644 index 71020b787a..0000000000 --- a/.changeset/brown-bananas-talk.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-components': patch ---- - -Having tooltip inherit font size for consistency in catalog table columns diff --git a/.changeset/calm-cars-serve.md b/.changeset/calm-cars-serve.md deleted file mode 100644 index 5df2a18cd4..0000000000 --- a/.changeset/calm-cars-serve.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-tasks': patch ---- - -Marked all exports as deprecated and pointed at `@backstage/backend-plugin-api` and `@backstage/backend-defaults` diff --git a/.changeset/calm-files-sort.md b/.changeset/calm-files-sort.md deleted file mode 100644 index a487c00eb4..0000000000 --- a/.changeset/calm-files-sort.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-plugin-api': patch ---- - -In tests, return `null` rather than throwing an error when trying to get the `ExtensionPoint.T` property, so that tests asserting the property are not easily broken. diff --git a/.changeset/calm-jeans-ring.md b/.changeset/calm-jeans-ring.md new file mode 100644 index 0000000000..3d1efcf7bd --- /dev/null +++ b/.changeset/calm-jeans-ring.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder': minor +--- + +Use virtualization with `EntityPicker` as done earlier with `MultiEntityPicker` to fix performance issues with large data sets. `VirtualizedListbox` extracted into reusable component. diff --git a/.changeset/calm-plums-wink.md b/.changeset/calm-plums-wink.md deleted file mode 100644 index edb991f616..0000000000 --- a/.changeset/calm-plums-wink.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs': patch ---- - -mkdocs-material have updated their CSS variable template, and a few are unset in Backstage. This patch adds the missing variables to ensure coverage. diff --git a/.changeset/chilled-planes-sniff.md b/.changeset/chilled-planes-sniff.md deleted file mode 100644 index e4084ea561..0000000000 --- a/.changeset/chilled-planes-sniff.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-api-docs': patch ---- - -The `registerComponent` external route will now by default bind to the catalog import page if it is available. diff --git a/.changeset/chilly-roses-trade.md b/.changeset/chilly-roses-trade.md new file mode 100644 index 0000000000..73fc3ff766 --- /dev/null +++ b/.changeset/chilly-roses-trade.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-common': patch +--- + +Deprecate legacy status check factory, handler and types. diff --git a/.changeset/clever-kids-return.md b/.changeset/clever-kids-return.md deleted file mode 100644 index a6cab79f2b..0000000000 --- a/.changeset/clever-kids-return.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -'@backstage/plugin-auth-node': patch ---- - -Updated scope management for OAuth providers, where the `createOAuthAuthenticator` now accepts a new collection of `scopes` options: - -- `scopes.persist` - Whether scopes should be persisted, replaces the `shouldPersistScopes` option. -- `scopes.required` - A list of required scopes that will always be requested. -- `scopes.transform` - A function that can be used to transform the scopes before they are requested. - -The `createOAuthProviderFactory` has also received a new `additionalScopes` option, and will also read `additionalScopes` from the auth provider configuration. Both of these can be used to add additional scopes that should always be requested. - -A significant change under the hood that this new scope management brings is that providers that persist scopes will now always merge the already granted scopes with the requested ones. The previous behavior was that the full authorization flow would not include existing scopes, while the refresh flow would only include the existing scopes. diff --git a/.changeset/clever-radios-yawn.md b/.changeset/clever-radios-yawn.md deleted file mode 100644 index e5600183f5..0000000000 --- a/.changeset/clever-radios-yawn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-api-docs': patch ---- - -Make sure that the toggle button state is properly reflected in API cards diff --git a/.changeset/clever-waves-judge.md b/.changeset/clever-waves-judge.md new file mode 100644 index 0000000000..585ad01bbe --- /dev/null +++ b/.changeset/clever-waves-judge.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-techdocs-react': patch +'@backstage/plugin-techdocs': patch +--- + +Fixed a bug with the TechDocsReaderPageProvider not re-rendering when setShadowDom is called, meaning that the useShadowDom hooks were inconsistent. This issue caused the TextSize addon changes not to reapply during navigation. diff --git a/.changeset/cold-seas-end.md b/.changeset/cold-seas-end.md deleted file mode 100644 index 96fa048fbd..0000000000 --- a/.changeset/cold-seas-end.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-common': patch ---- - -Updated configuration schema to include the `useRedisSets` cache config option. diff --git a/.changeset/create-app-1716903719.md b/.changeset/create-app-1716903719.md deleted file mode 100644 index b50d431d4b..0000000000 --- a/.changeset/create-app-1716903719.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Bumped create-app version. diff --git a/.changeset/create-app-1716302437.md b/.changeset/create-app-1719320674.md similarity index 100% rename from .changeset/create-app-1716302437.md rename to .changeset/create-app-1719320674.md diff --git a/.changeset/cuddly-eggs-sin.md b/.changeset/cuddly-eggs-sin.md deleted file mode 100644 index bfe7de9680..0000000000 --- a/.changeset/cuddly-eggs-sin.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-techdocs-backend': patch -'@backstage/plugin-techdocs-node': patch ---- - -Allow defining custom build log transport for techdocs builder diff --git a/.changeset/cuddly-jobs-kick.md b/.changeset/cuddly-jobs-kick.md deleted file mode 100644 index aa62efb88b..0000000000 --- a/.changeset/cuddly-jobs-kick.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-compat-api': patch ---- - -Add support for forwarding default target from legacy external route refs. diff --git a/.changeset/curvy-teachers-smell.md b/.changeset/curvy-teachers-smell.md new file mode 100644 index 0000000000..3f032f2177 --- /dev/null +++ b/.changeset/curvy-teachers-smell.md @@ -0,0 +1,8 @@ +--- +'@backstage/plugin-catalog-backend-module-ldap': patch +'@backstage/backend-plugin-api': patch +'@backstage/backend-defaults': patch +'@backstage/backend-tasks': patch +--- + +Fix bug where ISO durations could no longer be used for schedules diff --git a/.changeset/cyan-jobs-visit.md b/.changeset/cyan-jobs-visit.md deleted file mode 100644 index ccc8c90adf..0000000000 --- a/.changeset/cyan-jobs-visit.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-test-utils': minor ---- - -Added `TestCaches` that functions just like `TestDatabases` diff --git a/.changeset/cyan-paws-beg.md b/.changeset/cyan-paws-beg.md deleted file mode 100644 index 87c2b746a4..0000000000 --- a/.changeset/cyan-paws-beg.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend-module-github': patch ---- - -Added handling for dry run to githubPullRequest and githubWebhook and added tests for this functionality diff --git a/.changeset/cyan-snails-peel.md b/.changeset/cyan-snails-peel.md deleted file mode 100644 index 4da79258fb..0000000000 --- a/.changeset/cyan-snails-peel.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -'@backstage/plugin-user-settings-backend': patch -'@backstage/plugin-devtools-backend': patch -'@backstage/plugin-techdocs-backend': patch -'@backstage/plugin-catalog-backend': patch -'@backstage/plugin-search-backend': patch -'@backstage/plugin-proxy-backend': patch -'@backstage/plugin-auth-backend': patch -'@backstage/plugin-app-backend': patch ---- - -Updated local development setup. diff --git a/.changeset/eighty-games-wink.md b/.changeset/eighty-games-wink.md new file mode 100644 index 0000000000..e87dc56b5f --- /dev/null +++ b/.changeset/eighty-games-wink.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Fixed bug where `` component with empty string as placeholder gave an error +- Updated dependencies + - @backstage/core-plugin-api@1.9.3 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/theme@0.5.6 + - @backstage/version-bridge@1.0.8 + +## @backstage/create-app@0.5.17-next.0 + +### Patch Changes + +- Bumped create-app version. +- Updated dependencies + - @backstage/cli-common@0.1.14 + +## @backstage/dev-utils@1.0.34-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/core-app-api@1.13.0-next.0 + - @backstage/plugin-catalog-react@1.12.2-next.0 + - @backstage/app-defaults@1.5.7-next.0 + - @backstage/integration-react@1.1.29-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/catalog-model@1.5.0 + - @backstage/theme@0.5.6 + +## @backstage/frontend-app-api@0.7.2-next.0 + +### Patch Changes + +- d3c39fc: Allow for the disabling of external routes through config, which was rendered impossible after the introduction of default targets. + + ```yaml + app: + routes: + bindings: + # This has the effect of removing the button for registering new + # catalog entities in the scaffolder template list view + scaffolder.registerComponent: false + ``` + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/core-app-api@1.13.0-next.0 + - @backstage/frontend-plugin-api@0.6.7-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/theme@0.5.6 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.8 + +## @backstage/frontend-plugin-api@0.6.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.8 + +## @backstage/frontend-test-utils@0.1.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-app-api@0.7.2-next.0 + - @backstage/frontend-plugin-api@0.6.7-next.0 + - @backstage/test-utils@1.5.7-next.0 + - @backstage/types@1.1.1 + +## @backstage/integration-react@1.1.29-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.13.0-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/config@1.2.0 + +## @backstage/repo-tools@0.9.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/catalog-model@1.5.0 + - @backstage/cli-common@0.1.14 + - @backstage/cli-node@0.2.6 + - @backstage/config-loader@1.8.1 + - @backstage/errors@1.2.4 + +## @techdocs/cli@1.8.15-next.0 + +### Patch Changes + +- c964a3d: Import discovery from backend-defaults instead of backend-common +- Updated dependencies + - @backstage/backend-defaults@0.3.3-next.0 + - @backstage/plugin-techdocs-node@1.12.7-next.0 + - @backstage/catalog-model@1.5.0 + - @backstage/cli-common@0.1.14 + - @backstage/config@1.2.0 + +## @backstage/test-utils@1.5.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.13.0-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/config@1.2.0 + - @backstage/theme@0.5.6 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.14 + - @backstage/plugin-permission-react@0.4.23 + +## @backstage/plugin-api-docs@0.11.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/plugin-catalog-react@1.12.2-next.0 + - @backstage/plugin-catalog@1.21.1-next.0 + - @backstage/frontend-plugin-api@0.6.7-next.0 + - @backstage/core-compat-api@0.2.7-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/catalog-model@1.5.0 + - @backstage/plugin-catalog-common@1.0.24 + - @backstage/plugin-permission-react@0.4.23 + +## @backstage/plugin-app-backend@0.3.70-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/plugin-app-node@0.1.21-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/config@1.2.0 + - @backstage/config-loader@1.8.1 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + +## @backstage/plugin-app-node@0.1.21-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/config-loader@1.8.1 + +## @backstage/plugin-app-visualizer@0.1.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/frontend-plugin-api@0.6.7-next.0 + - @backstage/core-plugin-api@1.9.3 + +## @backstage/plugin-auth-backend@0.22.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/plugin-auth-backend-module-atlassian-provider@0.2.2-next.0 + - @backstage/plugin-auth-backend-module-aws-alb-provider@0.1.13-next.0 + - @backstage/plugin-auth-backend-module-azure-easyauth-provider@0.1.4-next.0 + - @backstage/plugin-auth-backend-module-bitbucket-provider@0.1.4-next.0 + - @backstage/plugin-auth-backend-module-cloudflare-access-provider@0.1.4-next.0 + - @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.16-next.0 + - @backstage/plugin-auth-backend-module-github-provider@0.1.18-next.0 + - @backstage/plugin-auth-backend-module-gitlab-provider@0.1.18-next.0 + - @backstage/plugin-auth-backend-module-google-provider@0.1.18-next.0 + - @backstage/plugin-auth-backend-module-microsoft-provider@0.1.16-next.0 + - @backstage/plugin-auth-backend-module-oauth2-provider@0.2.2-next.0 + - @backstage/plugin-auth-backend-module-oauth2-proxy-provider@0.1.14-next.0 + - @backstage/plugin-auth-backend-module-oidc-provider@0.2.2-next.0 + - @backstage/plugin-auth-backend-module-okta-provider@0.0.14-next.0 + - @backstage/plugin-auth-backend-module-onelogin-provider@0.1.2-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/plugin-catalog-node@1.12.3-next.0 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + +## @backstage/plugin-auth-backend-module-atlassian-provider@0.2.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + +## @backstage/plugin-auth-backend-module-aws-alb-provider@0.1.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/plugin-auth-backend@0.22.8-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/errors@1.2.4 + +## @backstage/plugin-auth-backend-module-azure-easyauth-provider@0.1.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/catalog-model@1.5.0 + - @backstage/errors@1.2.4 + +## @backstage/plugin-auth-backend-module-bitbucket-provider@0.1.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + +## @backstage/plugin-auth-backend-module-cloudflare-access-provider@0.1.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + +## @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + +## @backstage/plugin-auth-backend-module-github-provider@0.1.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + +## @backstage/plugin-auth-backend-module-gitlab-provider@0.1.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + +## @backstage/plugin-auth-backend-module-google-provider@0.1.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + +## @backstage/plugin-auth-backend-module-guest-provider@0.1.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/catalog-model@1.5.0 + - @backstage/errors@1.2.4 + +## @backstage/plugin-auth-backend-module-microsoft-provider@0.1.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + +## @backstage/plugin-auth-backend-module-oauth2-provider@0.2.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + +## @backstage/plugin-auth-backend-module-oauth2-proxy-provider@0.1.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/errors@1.2.4 + +## @backstage/plugin-auth-backend-module-oidc-provider@0.2.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/plugin-auth-backend@0.22.8-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + +## @backstage/plugin-auth-backend-module-okta-provider@0.0.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + +## @backstage/plugin-auth-backend-module-onelogin-provider@0.1.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + +## @backstage/plugin-auth-backend-module-pinniped-provider@0.1.15-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/config@1.2.0 + +## @backstage/plugin-auth-backend-module-vmware-cloud-provider@0.2.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/catalog-model@1.5.0 + +## @backstage/plugin-auth-node@0.4.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + +## @backstage/plugin-auth-react@0.1.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/errors@1.2.4 + +## @backstage/plugin-bitbucket-cloud-common@0.2.21-next.0 + +### Patch Changes + +- b5deed0: Add support for `autocomplete` handler to provide autocomplete options for `RepoUrlPicker` +- Updated dependencies + - @backstage/integration@1.13.0-next.0 + +## @backstage/plugin-catalog@1.21.1-next.0 + +### Patch Changes + +- d133eaa: Added small notes to AboutCard to discourage customizability PRs +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/plugin-catalog-react@1.12.2-next.0 + - @backstage/frontend-plugin-api@0.6.7-next.0 + - @backstage/integration-react@1.1.29-next.0 + - @backstage/plugin-search-react@1.7.13-next.0 + - @backstage/core-compat-api@0.2.7-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.24 + - @backstage/plugin-permission-react@0.4.23 + - @backstage/plugin-scaffolder-common@1.5.3 + - @backstage/plugin-search-common@1.2.12 + +## @backstage/plugin-catalog-backend@1.23.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/backend-openapi-utils@0.1.14-next.0 + - @backstage/plugin-catalog-node@1.12.3-next.0 + - @backstage/plugin-events-node@0.3.7-next.0 + - @backstage/plugin-permission-node@0.7.32-next.0 + - @backstage/plugin-search-backend-module-catalog@0.1.27-next.0 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.24 + - @backstage/plugin-permission-common@0.7.14 + +## @backstage/plugin-catalog-backend-module-aws@0.3.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/plugin-catalog-node@1.12.3-next.0 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/integration-aws-node@0.1.12 + - @backstage/plugin-catalog-common@1.0.24 + - @backstage/plugin-kubernetes-common@0.8.0 + +## @backstage/plugin-catalog-backend-module-azure@0.1.41-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/plugin-catalog-node@1.12.3-next.0 + - @backstage/config@1.2.0 + - @backstage/plugin-catalog-common@1.0.24 + +## @backstage/plugin-catalog-backend-module-backstage-openapi@0.2.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/backend-openapi-utils@0.1.14-next.0 + - @backstage/plugin-catalog-node@1.12.3-next.0 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.2.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/plugin-bitbucket-cloud-common@0.2.21-next.0 + - @backstage/plugin-catalog-node@1.12.3-next.0 + - @backstage/plugin-events-node@0.3.7-next.0 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/plugin-catalog-common@1.0.24 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.1.35-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/plugin-catalog-node@1.12.3-next.0 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + +## @backstage/plugin-catalog-backend-module-gcp@0.1.22-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/plugin-catalog-node@1.12.3-next.0 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/plugin-kubernetes-common@0.8.0 + +## @backstage/plugin-catalog-backend-module-gerrit@0.1.38-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/plugin-catalog-node@1.12.3-next.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + +## @backstage/plugin-catalog-backend-module-github@0.6.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/plugin-catalog-backend@1.23.2-next.0 + - @backstage/plugin-catalog-node@1.12.3-next.0 + - @backstage/plugin-events-node@0.3.7-next.0 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/plugin-catalog-common@1.0.24 + +## @backstage/plugin-catalog-backend-module-github-org@0.1.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/plugin-catalog-backend-module-github@0.6.4-next.0 + - @backstage/plugin-catalog-node@1.12.3-next.0 + - @backstage/plugin-events-node@0.3.7-next.0 + - @backstage/config@1.2.0 + +## @backstage/plugin-catalog-backend-module-gitlab@0.3.20-next.0 + +### Patch Changes + +- 8db30ad: The Gitlab configuration supports an additional optional boolean key `catalog.providers.gitlab..restrictUsersToGroup`. Setting this to `true` will make Backstage only import users from the group defined in the `group` key, instead of all users in the organisation (self-hosted) or of the root group (SaaS). It will default to false, keeping the original implementation intact, when not explicitly set. +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/plugin-catalog-node@1.12.3-next.0 + - @backstage/plugin-events-node@0.3.7-next.0 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/plugin-catalog-common@1.0.24 + +## @backstage/plugin-catalog-backend-module-gitlab-org@0.0.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/plugin-catalog-backend-module-gitlab@0.3.20-next.0 + - @backstage/plugin-catalog-node@1.12.3-next.0 + - @backstage/plugin-events-node@0.3.7-next.0 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.4.26-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/plugin-catalog-backend@1.23.2-next.0 + - @backstage/plugin-catalog-node@1.12.3-next.0 + - @backstage/plugin-events-node@0.3.7-next.0 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/plugin-permission-common@0.7.14 + +## @backstage/plugin-catalog-backend-module-ldap@0.6.2-next.0 + +### Patch Changes + +- 083eaf9: Fix bug where ISO durations could no longer be used for schedules +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/plugin-catalog-node@1.12.3-next.0 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.24 + +## @backstage/plugin-catalog-backend-module-logs@0.0.1-next.0 + +### Patch Changes + +- 97caf55: Creates a new module to make logging catalog errors simple. This module subscribes to catalog events and logs them. + + See [Backstage documentation](https://backstage.io/docs/features/software-catalog/configuration#subscribing-to-catalog-errors) for details on how to install + and configure the plugin. + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/plugin-catalog-backend@1.23.2-next.0 + - @backstage/plugin-events-node@0.3.7-next.0 + +## @backstage/plugin-catalog-backend-module-msgraph@0.5.29-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/plugin-catalog-node@1.12.3-next.0 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/plugin-catalog-common@1.0.24 + +## @backstage/plugin-catalog-backend-module-openapi@0.1.39-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/plugin-catalog-backend@1.23.2-next.0 + - @backstage/plugin-catalog-node@1.12.3-next.0 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.24 + +## @backstage/plugin-catalog-backend-module-puppetdb@0.1.27-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/plugin-catalog-node@1.12.3-next.0 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + +## @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.19-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/plugin-catalog-node@1.12.3-next.0 + - @backstage/catalog-model@1.5.0 + - @backstage/plugin-catalog-common@1.0.24 + - @backstage/plugin-scaffolder-common@1.5.3 + +## @backstage/plugin-catalog-backend-module-unprocessed@0.4.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/plugin-catalog-node@1.12.3-next.0 + - @backstage/catalog-model@1.5.0 + - @backstage/errors@1.2.4 + - @backstage/plugin-catalog-unprocessed-entities-common@0.0.2 + - @backstage/plugin-permission-common@0.7.14 + +## @backstage/plugin-catalog-graph@0.4.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/plugin-catalog-react@1.12.2-next.0 + - @backstage/frontend-plugin-api@0.6.7-next.0 + - @backstage/core-compat-api@0.2.7-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-catalog-import@0.12.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/plugin-catalog-react@1.12.2-next.0 + - @backstage/frontend-plugin-api@0.6.7-next.0 + - @backstage/integration-react@1.1.29-next.0 + - @backstage/core-compat-api@0.2.7-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/plugin-catalog-common@1.0.24 + +## @backstage/plugin-catalog-node@1.12.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/plugin-permission-node@0.7.32-next.0 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.24 + - @backstage/plugin-permission-common@0.7.14 + +## @backstage/plugin-catalog-react@1.12.2-next.0 + +### Patch Changes + +- 2030962: Make EntityOwnerPicker display metadata.title or spec.profile.displayName for mode=only-owners instead of metadata.name +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/frontend-plugin-api@0.6.7-next.0 + - @backstage/integration-react@1.1.29-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.8 + - @backstage/plugin-catalog-common@1.0.24 + - @backstage/plugin-permission-common@0.7.14 + - @backstage/plugin-permission-react@0.4.23 + +## @backstage/plugin-catalog-unprocessed-entities@0.2.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/catalog-model@1.5.0 + - @backstage/errors@1.2.4 + +## @backstage/plugin-config-schema@0.1.57-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + +## @backstage/plugin-devtools@0.1.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/frontend-plugin-api@0.6.7-next.0 + - @backstage/core-compat-api@0.2.7-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/errors@1.2.4 + - @backstage/plugin-devtools-common@0.1.10 + - @backstage/plugin-permission-react@0.4.23 + +## @backstage/plugin-devtools-backend@0.3.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/plugin-permission-node@0.7.32-next.0 + - @backstage/cli-common@0.1.14 + - @backstage/config@1.2.0 + - @backstage/config-loader@1.8.1 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + - @backstage/plugin-devtools-common@0.1.10 + - @backstage/plugin-permission-common@0.7.14 + +## @backstage/plugin-events-backend@0.3.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/plugin-events-node@0.3.7-next.0 + - @backstage/config@1.2.0 + +## @backstage/plugin-events-backend-module-aws-sqs@0.3.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/plugin-events-node@0.3.7-next.0 + - @backstage/config@1.2.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-events-backend-module-azure@0.2.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/plugin-events-node@0.3.7-next.0 + +## @backstage/plugin-events-backend-module-bitbucket-cloud@0.2.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/plugin-events-node@0.3.7-next.0 + +## @backstage/plugin-events-backend-module-gerrit@0.2.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/plugin-events-node@0.3.7-next.0 + +## @backstage/plugin-events-backend-module-github@0.2.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/plugin-events-node@0.3.7-next.0 + - @backstage/config@1.2.0 + +## @backstage/plugin-events-backend-module-gitlab@0.2.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/plugin-events-node@0.3.7-next.0 + - @backstage/config@1.2.0 + +## @backstage/plugin-events-backend-test-utils@0.1.31-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.3.7-next.0 + +## @backstage/plugin-events-node@0.3.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + +## @backstage/plugin-home@0.7.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/core-app-api@1.13.0-next.0 + - @backstage/plugin-catalog-react@1.12.2-next.0 + - @backstage/frontend-plugin-api@0.6.7-next.0 + - @backstage/plugin-home-react@0.1.15-next.0 + - @backstage/core-compat-api@0.2.7-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/theme@0.5.6 + +## @backstage/plugin-home-react@0.1.15-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/core-plugin-api@1.9.3 + +## @backstage/plugin-kubernetes@0.11.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/plugin-catalog-react@1.12.2-next.0 + - @backstage/plugin-kubernetes-react@0.4.1-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/catalog-model@1.5.0 + - @backstage/plugin-kubernetes-common@0.8.0 + +## @backstage/plugin-kubernetes-backend@0.18.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/plugin-catalog-node@1.12.3-next.0 + - @backstage/plugin-kubernetes-node@0.1.15-next.0 + - @backstage/plugin-permission-node@0.7.32-next.0 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/integration-aws-node@0.1.12 + - @backstage/types@1.1.1 + - @backstage/plugin-kubernetes-common@0.8.0 + - @backstage/plugin-permission-common@0.7.14 + +## @backstage/plugin-kubernetes-cluster@0.0.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/plugin-catalog-react@1.12.2-next.0 + - @backstage/plugin-kubernetes-react@0.4.1-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/catalog-model@1.5.0 + - @backstage/plugin-kubernetes-common@0.8.0 + +## @backstage/plugin-kubernetes-node@0.1.15-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/catalog-model@1.5.0 + - @backstage/types@1.1.1 + - @backstage/plugin-kubernetes-common@0.8.0 + +## @backstage/plugin-kubernetes-react@0.4.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/catalog-model@1.5.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + - @backstage/plugin-kubernetes-common@0.8.0 + +## @backstage/plugin-notifications@0.2.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/errors@1.2.4 + - @backstage/theme@0.5.6 + - @backstage/types@1.1.1 + - @backstage/plugin-notifications-common@0.0.4 + - @backstage/plugin-signals-react@0.0.4 + +## @backstage/plugin-notifications-backend@0.3.2-next.0 + +### Patch Changes + +- d7b8ca5: Added an option to filter notifications by topic +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/plugin-events-node@0.3.7-next.0 + - @backstage/plugin-notifications-node@0.2.2-next.0 + - @backstage/plugin-signals-node@0.1.7-next.0 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/plugin-notifications-common@0.0.4 + +## @backstage/plugin-notifications-backend-module-email@0.1.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/plugin-notifications-node@0.2.2-next.0 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/integration-aws-node@0.1.12 + - @backstage/types@1.1.1 + - @backstage/plugin-notifications-common@0.0.4 + +## @backstage/plugin-notifications-node@0.2.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/plugin-signals-node@0.1.7-next.0 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/plugin-notifications-common@0.0.4 + +## @backstage/plugin-org@0.6.27-next.0 + +### Patch Changes + +- c307ef4: Added `relationType` property to EntityMembersListCard component that allows for display users related to a group via some other relationship aside from `memberOf`. + + Also, as a side effect, the `relationsType` property has been deprecated in favor of a more accurately named `relationAggregation` property. + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/plugin-catalog-react@1.12.2-next.0 + - @backstage/frontend-plugin-api@0.6.7-next.0 + - @backstage/core-compat-api@0.2.7-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/catalog-model@1.5.0 + - @backstage/plugin-catalog-common@1.0.24 + +## @backstage/plugin-org-react@0.1.26-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/plugin-catalog-react@1.12.2-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + +## @backstage/plugin-permission-backend@0.5.45-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/plugin-permission-node@0.7.32-next.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/plugin-permission-common@0.7.14 + +## @backstage/plugin-permission-backend-module-allow-all-policy@0.1.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/plugin-permission-node@0.7.32-next.0 + - @backstage/plugin-permission-common@0.7.14 + +## @backstage/plugin-permission-node@0.7.32-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/plugin-permission-common@0.7.14 + +## @backstage/plugin-proxy-backend@0.5.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/config@1.2.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-scaffolder-backend-module-azure@0.1.13-next.0 + +### Patch Changes + +- 661b354: Fixed a bug where the `RepoUrlPicker` would still require the `owner` field for `azure` +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/plugin-scaffolder-node@0.4.7-next.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + +## @backstage/plugin-scaffolder-backend-module-bitbucket@0.2.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.11-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/plugin-scaffolder-node@0.4.7-next.0 + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.11-next.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + +## @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.11-next.0 + +### Patch Changes + +- b5deed0: Add support for `autocomplete` handler to provide autocomplete options for `RepoUrlPicker` +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/plugin-scaffolder-node@0.4.7-next.0 + - @backstage/plugin-bitbucket-cloud-common@0.2.21-next.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + +## @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.11-next.0 + +### Patch Changes + +- 6a4ad4e: Instead of using hardcoded `targetBranch` now fetch the default branch from Bitbucket repository. + This prevents from errors when no `targetBranch` is provided and the default repository branch is different from `master`, for example: `main`. +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/plugin-scaffolder-node@0.4.7-next.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + +## @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.22-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/plugin-scaffolder-node@0.4.7-next.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.45-next.0 + +### Patch Changes + +- 0ac124b: Updated configuration instructions +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/plugin-scaffolder-node@0.4.7-next.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + +## @backstage/plugin-scaffolder-backend-module-gerrit@0.1.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/plugin-scaffolder-node@0.4.7-next.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + +## @backstage/plugin-scaffolder-backend-module-gitea@0.1.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/plugin-scaffolder-node@0.4.7-next.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + +## @backstage/plugin-scaffolder-backend-module-gitlab@0.4.3-next.0 + +### Patch Changes + +- 0ac124b: Updated configuration instructions +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/plugin-scaffolder-node@0.4.7-next.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + +## @backstage/plugin-scaffolder-backend-module-notifications@0.0.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/plugin-scaffolder-node@0.4.7-next.0 + - @backstage/plugin-notifications-node@0.2.2-next.0 + - @backstage/plugin-notifications-common@0.0.4 + +## @backstage/plugin-scaffolder-backend-module-rails@0.4.38-next.0 + +### Patch Changes + +- 0ac124b: Updated configuration instructions +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/plugin-scaffolder-node@0.4.7-next.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.1.29-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/plugin-scaffolder-node@0.4.7-next.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.3.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/plugin-scaffolder-node@0.4.7-next.0 + - @backstage/plugin-scaffolder-node-test-utils@0.1.8-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-scaffolder-node@0.4.7-next.0 + +### Patch Changes + +- 661b354: Fixed a bug where the `RepoUrlPicker` would still require the `owner` field for `azure` +- b5deed0: Add support for `autocomplete` extension point to provide additional `autocomplete` handlers +- 0b52438: Serialization of the scaffolder workspace into GCP bucket +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/catalog-model@1.5.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-common@1.5.3 + +## @backstage/plugin-scaffolder-node-test-utils@0.1.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.23.2-next.0 + - @backstage/plugin-scaffolder-node@0.4.7-next.0 + - @backstage/backend-test-utils@0.4.3-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-search@1.4.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/plugin-catalog-react@1.12.2-next.0 + - @backstage/frontend-plugin-api@0.6.7-next.0 + - @backstage/plugin-search-react@1.7.13-next.0 + - @backstage/core-compat-api@0.2.7-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.8 + - @backstage/plugin-search-common@1.2.12 + +## @backstage/plugin-search-backend@1.5.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-defaults@0.3.3-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-openapi-utils@0.1.14-next.0 + - @backstage/plugin-permission-node@0.7.32-next.0 + - @backstage/plugin-search-backend-node@1.2.26-next.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.14 + - @backstage/plugin-search-common@1.2.12 + +## @backstage/plugin-search-backend-module-catalog@0.1.27-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/plugin-catalog-node@1.12.3-next.0 + - @backstage/plugin-search-backend-node@1.2.26-next.0 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/plugin-catalog-common@1.0.24 + - @backstage/plugin-permission-common@0.7.14 + - @backstage/plugin-search-common@1.2.12 + +## @backstage/plugin-search-backend-module-elasticsearch@1.5.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/plugin-search-backend-node@1.2.26-next.0 + - @backstage/config@1.2.0 + - @backstage/integration-aws-node@0.1.12 + - @backstage/plugin-search-common@1.2.12 + +## @backstage/plugin-search-backend-module-explore@0.1.27-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/plugin-search-backend-node@1.2.26-next.0 + - @backstage/config@1.2.0 + - @backstage/plugin-search-common@1.2.12 + +## @backstage/plugin-search-backend-module-pg@0.5.31-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-app-api@0.7.9-next.0 + - @backstage/plugin-search-backend-node@1.2.26-next.0 + - @backstage/config@1.2.0 + - @backstage/plugin-search-common@1.2.12 + +## @backstage/plugin-search-backend-module-stack-overflow-collator@0.1.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/plugin-search-backend-node@1.2.26-next.0 + - @backstage/config@1.2.0 + - @backstage/plugin-search-common@1.2.12 + +## @backstage/plugin-search-backend-module-techdocs@0.1.26-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/plugin-catalog-node@1.12.3-next.0 + - @backstage/plugin-search-backend-node@1.2.26-next.0 + - @backstage/plugin-techdocs-node@1.12.7-next.0 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/plugin-catalog-common@1.0.24 + - @backstage/plugin-permission-common@0.7.14 + - @backstage/plugin-search-common@1.2.12 + +## @backstage/plugin-search-backend-node@1.2.26-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/plugin-permission-common@0.7.14 + - @backstage/plugin-search-common@1.2.12 + +## @backstage/plugin-search-react@1.7.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/frontend-plugin-api@0.6.7-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/theme@0.5.6 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.8 + - @backstage/plugin-search-common@1.2.12 + +## @backstage/plugin-signals@0.0.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/theme@0.5.6 + - @backstage/types@1.1.1 + - @backstage/plugin-signals-react@0.0.4 + +## @backstage/plugin-signals-backend@0.1.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/plugin-events-node@0.3.7-next.0 + - @backstage/plugin-signals-node@0.1.7-next.0 + - @backstage/config@1.2.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-signals-node@0.1.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/plugin-events-node@0.3.7-next.0 + - @backstage/config@1.2.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-techdocs@1.10.7-next.0 + +### Patch Changes + +- 8ac9ce5: Fixed a bug with the TechDocsReaderPageProvider not re-rendering when setShadowDom is called, meaning that the useShadowDom hooks were inconsistent. This issue caused the TextSize addon changes not to reapply during navigation. +- Updated dependencies + - @backstage/plugin-techdocs-react@1.2.6-next.0 + - @backstage/core-components@0.14.9-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/plugin-catalog-react@1.12.2-next.0 + - @backstage/frontend-plugin-api@0.6.7-next.0 + - @backstage/integration-react@1.1.29-next.0 + - @backstage/plugin-auth-react@0.1.4-next.0 + - @backstage/plugin-search-react@1.7.13-next.0 + - @backstage/core-compat-api@0.2.7-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/theme@0.5.6 + - @backstage/plugin-search-common@1.2.12 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.34-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-techdocs-react@1.2.6-next.0 + - @backstage/plugin-techdocs@1.10.7-next.0 + - @backstage/core-app-api@1.13.0-next.0 + - @backstage/plugin-catalog-react@1.12.2-next.0 + - @backstage/plugin-catalog@1.21.1-next.0 + - @backstage/integration-react@1.1.29-next.0 + - @backstage/plugin-search-react@1.7.13-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/test-utils@1.5.7-next.0 + +## @backstage/plugin-techdocs-backend@1.10.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.1.26-next.0 + - @backstage/plugin-techdocs-node@1.12.7-next.0 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/plugin-catalog-common@1.0.24 + - @backstage/plugin-permission-common@0.7.14 + +## @backstage/plugin-techdocs-module-addons-contrib@1.1.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-techdocs-react@1.2.6-next.0 + - @backstage/core-components@0.14.9-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/integration-react@1.1.29-next.0 + - @backstage/core-plugin-api@1.9.3 + +## @backstage/plugin-techdocs-node@1.12.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/integration-aws-node@0.1.12 + - @backstage/plugin-search-common@1.2.12 + +## @backstage/plugin-techdocs-react@1.2.6-next.0 + +### Patch Changes + +- 8ac9ce5: Fixed a bug with the TechDocsReaderPageProvider not re-rendering when setShadowDom is called, meaning that the useShadowDom hooks were inconsistent. This issue caused the TextSize addon changes not to reapply during navigation. +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/version-bridge@1.0.8 + +## @backstage/plugin-user-settings@0.8.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/core-app-api@1.13.0-next.0 + - @backstage/plugin-catalog-react@1.12.2-next.0 + - @backstage/frontend-plugin-api@0.6.7-next.0 + - @backstage/core-compat-api@0.2.7-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/errors@1.2.4 + - @backstage/theme@0.5.6 + - @backstage/types@1.1.1 + - @backstage/plugin-signals-react@0.0.4 + - @backstage/plugin-user-settings-common@0.0.1 + +## @backstage/plugin-user-settings-backend@0.2.20-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/plugin-signals-node@0.1.7-next.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + - @backstage/plugin-user-settings-common@0.0.1 + +## example-app@0.2.99-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder@1.22.0-next.0 + - @backstage/plugin-techdocs-react@1.2.6-next.0 + - @backstage/plugin-techdocs@1.10.7-next.0 + - @backstage/core-components@0.14.9-next.0 + - @backstage/core-app-api@1.13.0-next.0 + - @backstage/frontend-app-api@0.7.2-next.0 + - @backstage/cli@0.26.10-next.0 + - @backstage/plugin-org@0.6.27-next.0 + - @backstage/plugin-catalog-react@1.12.2-next.0 + - @backstage/plugin-catalog@1.21.1-next.0 + - @backstage/plugin-scaffolder-react@1.10.0-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.12-next.0 + - @backstage/app-defaults@1.5.7-next.0 + - @backstage/integration-react@1.1.29-next.0 + - @backstage/plugin-api-docs@0.11.7-next.0 + - @backstage/plugin-auth-react@0.1.4-next.0 + - @backstage/plugin-catalog-graph@0.4.7-next.0 + - @backstage/plugin-catalog-import@0.12.1-next.0 + - @backstage/plugin-catalog-unprocessed-entities@0.2.6-next.0 + - @backstage/plugin-devtools@0.1.16-next.0 + - @backstage/plugin-home@0.7.6-next.0 + - @backstage/plugin-kubernetes@0.11.12-next.0 + - @backstage/plugin-kubernetes-cluster@0.0.13-next.0 + - @backstage/plugin-notifications@0.2.3-next.0 + - @backstage/plugin-search@1.4.13-next.0 + - @backstage/plugin-search-react@1.7.13-next.0 + - @backstage/plugin-signals@0.0.8-next.0 + - @backstage/plugin-user-settings@0.8.8-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/theme@0.5.6 + - @backstage/plugin-catalog-common@1.0.24 + - @backstage/plugin-permission-react@0.4.23 + - @backstage/plugin-search-common@1.2.12 + +## example-app-next@0.0.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder@1.22.0-next.0 + - @backstage/plugin-techdocs-react@1.2.6-next.0 + - @backstage/plugin-techdocs@1.10.7-next.0 + - @backstage/core-components@0.14.9-next.0 + - @backstage/core-app-api@1.13.0-next.0 + - @backstage/frontend-app-api@0.7.2-next.0 + - @backstage/cli@0.26.10-next.0 + - @backstage/plugin-org@0.6.27-next.0 + - @backstage/plugin-catalog-react@1.12.2-next.0 + - @backstage/plugin-catalog@1.21.1-next.0 + - @backstage/plugin-scaffolder-react@1.10.0-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.12-next.0 + - @backstage/app-defaults@1.5.7-next.0 + - @backstage/frontend-plugin-api@0.6.7-next.0 + - @backstage/integration-react@1.1.29-next.0 + - @backstage/plugin-api-docs@0.11.7-next.0 + - @backstage/plugin-app-visualizer@0.1.8-next.0 + - @backstage/plugin-auth-react@0.1.4-next.0 + - @backstage/plugin-catalog-graph@0.4.7-next.0 + - @backstage/plugin-catalog-import@0.12.1-next.0 + - @backstage/plugin-catalog-unprocessed-entities@0.2.6-next.0 + - @backstage/plugin-home@0.7.6-next.0 + - @backstage/plugin-kubernetes@0.11.12-next.0 + - @backstage/plugin-kubernetes-cluster@0.0.13-next.0 + - @backstage/plugin-notifications@0.2.3-next.0 + - @backstage/plugin-search@1.4.13-next.0 + - @backstage/plugin-search-react@1.7.13-next.0 + - @backstage/plugin-signals@0.0.8-next.0 + - @backstage/plugin-user-settings@0.8.8-next.0 + - @backstage/core-compat-api@0.2.7-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/theme@0.5.6 + - @backstage/plugin-catalog-common@1.0.24 + - @backstage/plugin-permission-react@0.4.23 + - @backstage/plugin-search-common@1.2.12 + +## app-next-example-plugin@0.0.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/frontend-plugin-api@0.6.7-next.0 + +## example-backend@0.0.28-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-defaults@0.3.3-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/plugin-scaffolder-backend@1.23.0-next.0 + - @backstage/plugin-scaffolder-backend-module-github@0.4.0-next.0 + - @backstage/plugin-notifications-backend@0.3.2-next.0 + - @backstage/plugin-app-backend@0.3.70-next.0 + - @backstage/plugin-auth-backend@0.22.8-next.0 + - @backstage/plugin-auth-backend-module-github-provider@0.1.18-next.0 + - @backstage/plugin-auth-backend-module-guest-provider@0.1.7-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/plugin-catalog-backend@1.23.2-next.0 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.2.4-next.0 + - @backstage/plugin-catalog-backend-module-openapi@0.1.39-next.0 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.19-next.0 + - @backstage/plugin-catalog-backend-module-unprocessed@0.4.8-next.0 + - @backstage/plugin-devtools-backend@0.3.7-next.0 + - @backstage/plugin-kubernetes-backend@0.18.2-next.0 + - @backstage/plugin-permission-backend@0.5.45-next.0 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.1.18-next.0 + - @backstage/plugin-permission-node@0.7.32-next.0 + - @backstage/plugin-proxy-backend@0.5.2-next.0 + - @backstage/plugin-search-backend@1.5.13-next.0 + - @backstage/plugin-search-backend-module-catalog@0.1.27-next.0 + - @backstage/plugin-search-backend-module-explore@0.1.27-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.1.26-next.0 + - @backstage/plugin-search-backend-node@1.2.26-next.0 + - @backstage/plugin-signals-backend@0.1.7-next.0 + - @backstage/plugin-techdocs-backend@1.10.8-next.0 + - @backstage/catalog-model@1.5.0 + - @backstage/plugin-permission-common@0.7.14 + +## example-backend-legacy@0.2.100-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/plugin-scaffolder-backend-module-gitlab@0.4.3-next.0 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.38-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/plugin-scaffolder-backend@1.23.0-next.0 + - @backstage/plugin-app-backend@0.3.70-next.0 + - @backstage/plugin-auth-backend@0.22.8-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/plugin-catalog-backend@1.23.2-next.0 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.19-next.0 + - @backstage/plugin-catalog-backend-module-unprocessed@0.4.8-next.0 + - @backstage/plugin-catalog-node@1.12.3-next.0 + - @backstage/plugin-devtools-backend@0.3.7-next.0 + - @backstage/plugin-events-backend@0.3.8-next.0 + - @backstage/plugin-events-node@0.3.7-next.0 + - @backstage/plugin-kubernetes-backend@0.18.2-next.0 + - @backstage/plugin-permission-backend@0.5.45-next.0 + - @backstage/plugin-permission-node@0.7.32-next.0 + - @backstage/plugin-proxy-backend@0.5.2-next.0 + - @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.22-next.0 + - @backstage/plugin-search-backend@1.5.13-next.0 + - @backstage/plugin-search-backend-module-catalog@0.1.27-next.0 + - @backstage/plugin-search-backend-module-elasticsearch@1.5.2-next.0 + - @backstage/plugin-search-backend-module-explore@0.1.27-next.0 + - @backstage/plugin-search-backend-module-pg@0.5.31-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.1.26-next.0 + - @backstage/plugin-search-backend-node@1.2.26-next.0 + - @backstage/plugin-signals-backend@0.1.7-next.0 + - @backstage/plugin-signals-node@0.1.7-next.0 + - @backstage/plugin-techdocs-backend@1.10.8-next.0 + - example-app@0.2.99-next.0 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/plugin-permission-common@0.7.14 + +## e2e-test@0.2.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.17-next.0 + - @backstage/cli-common@0.1.14 + - @backstage/errors@1.2.4 + +## techdocs-cli-embedded-app@0.2.98-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-techdocs-react@1.2.6-next.0 + - @backstage/plugin-techdocs@1.10.7-next.0 + - @backstage/core-components@0.14.9-next.0 + - @backstage/core-app-api@1.13.0-next.0 + - @backstage/cli@0.26.10-next.0 + - @backstage/plugin-catalog@1.21.1-next.0 + - @backstage/app-defaults@1.5.7-next.0 + - @backstage/integration-react@1.1.29-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/test-utils@1.5.7-next.0 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/theme@0.5.6 + +## @internal/plugin-todo-list@1.0.29-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/core-plugin-api@1.9.3 + +## @internal/plugin-todo-list-backend@1.0.29-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/errors@1.2.4 diff --git a/docs/tooling/cli/02-build-system.md b/docs/tooling/cli/02-build-system.md index bfdb21f45f..1bcf7ad30c 100644 --- a/docs/tooling/cli/02-build-system.md +++ b/docs/tooling/cli/02-build-system.md @@ -617,7 +617,10 @@ A complete launch configuration for VS Code debugging may look like this: Package publishing is an optional part of the Backstage build system and not something you will need to worry about unless you are publishing packages to a -registry. In order to publish a package, you first need to build it, which will +registry. In addition to the documentation in the section, be sure to also read +the section on [metadata for published packages](../package-metadata.md#metadata-for-published-packages). + +In order to publish a package, you first need to build it, which will populate the `dist` folder. Because the Backstage build system is optimized for local development along with our particular TypeScript and bundling setup, it is not possible to publish the package immediately at this point. This is because diff --git a/docs/tooling/package-metadata.md b/docs/tooling/package-metadata.md new file mode 100644 index 0000000000..63ce6d1085 --- /dev/null +++ b/docs/tooling/package-metadata.md @@ -0,0 +1,192 @@ +--- +id: package-metadata +title: Package Metadata +description: An inventory of well known package metadata fields in the Backstage ecosystem. +--- + +The `package.json` file is a JSON file that contains metadata about a JavaScript package. It is a [Node.js standard](https://nodejs.org/api/packages.html) that is expanded upon in the [NPM ecosystem](https://docs.npmjs.com/cli/v10/configuring-npm/package-json), and is required for all packages published to NPM or a similar package registry. + +## Known Metadata Fields + +This section documents the known `package.json` metadata fields that play a significant role in the Backstage ecosystem. + +All [fields defined by NPM](https://docs.npmjs.com/cli/v10/configuring-npm/package-json) are inherited by the Backstage ecosystem. The list below only includes those standard fields for which additional information is available. + +### `name` + +The name of the package, as defined by [NPM](https://docs.npmjs.com/cli/v10/configuring-npm/package-json#name). In addition, the following naming scheme is strongly encouraged for packages published in the Backstage ecosystem: + +First pick a package name prefix that is unique to your organization or collection of packages, but also places it within the Backstage ecosystem, for example: `@example/backstage`, `@example-backstage/`, or `example-backstage`. This prefix should be used by all packages that you publish, regardless of whether they're part of a plugin or not. + +Any package that is not part of a plugin should use the prefix along with a descriptive name, for example: `@example/backstage-components` or `@example/backstage-foo-client`. + +For plugin packages you should also pick a plugin ID and add `plugin-` to the prefix, along with a suffix based on the package role: + +- `-plugin-`: The main frontend code of the plugin. +- `-plugin--module-`: Optional modules related to the frontend plugin package. +- `-plugin--backend`: The main backend code of the plugin. +- `-plugin--backend-module-`: Optional modules related to the backend plugin package. +- `-plugin--react`: Shared widgets, hooks and similar that both the plugin itself and third-party frontend plugins or modules can depend on. +- `-plugin--node`: Utilities for backends that both the plugin backend itself and third-party backend plugins or modules can depend on. +- `-plugin--common`: An isomorphic package with platform agnostic models, clients, and utilities that all packages above or any third-party plugin or module can depend on. + +For example, a frontend package for the `poetry` plugin might be called `@example/backstage-plugin-poetry`, and a backend package for the same plugin might be called `@example/backstage-plugin-poetry-backend`. + +If you are creating a module for an existing package that is not part of your project, you should use the same prefix along with the plugin ID of the package that the module is for. For example, if you are creating a poetry provider module for `@backstage/plugin-catalog-backend`, you might call it `@example/backstage-plugin-catalog-backend-module-poetry-provider`. + +### `repository` + +The location of the source code for the package, as defined by [NPM](https://docs.npmjs.com/cli/v10/configuring-npm/package-json#repository). + +This field can be generated by the `backstage-cli repo fix --publish` command. The only requirement is that the `package.json` in your workspace root has the `repository` field documented. + +### `main` + +The main entry point of the package, as defined by [NPM](https://docs.npmjs.com/cli/v10/configuring-npm/package-json#main). In a standard Backstage setup this should point to the entry point for local development, typically `src/index.ts`. This field along with other entry point fields such as `module` and `types` are rewritten when packaging the package for distribution. You can read more about this process in the [publishing](./cli/02-build-system.md#publishing) section, and it is also used for [backend production builds](./cli/02-build-system.md#backend-production). + +### `exports` + +The exports of the package, as defined by [Node.js](https://nodejs.org/api/packages.html#exports). This field is used to define the entry points of the package. As with other entry point fields, the exports should point to entry points for local development. They will the be rewritten when packaging the package for distribution. You can read more about this in the [sub-path exports](./cli/02-build-system.md#subpath-exports) section. + +### `typeVersions` + +This field is used to specify versioned type entry points for the package, as defined by [TypeScript](https://www.typescriptlang.org/docs/handbook/declaration-files/publishing.html#version-selection-with-typesversions), and is used as the equivalent of the `exports` field. TypeScript does support type declarations in the `exports` field, but that requires that the `moduleResolution` option in `tsconfig.json` is set to `node16` or `bundler`, which the Backstage ecosystem currently does not support. + +This field can be generated by the `backstage-cli repo fix` command. First fill out the `exports` field to point to source fields, which will then be used to generate `typeVersions`. + +### `sideEffects` + +This field declares whether it is safe to remove unused code through tree shaking when bundling this package into a frontend build, and is defined for example by [WebPack](https://github.com/backstage/backstage/blob/8d5cdb5d536cc8eb444da4b57dca4e36716f4535/plugins/auth-backend-module-google-provider/config.d.ts#L22). + +This field can be generated by the `backstage-cli repo fix` command. It will set to `false` by default for all frontend packages, since Backstage frontend packages should generally never have any side effects. If your package does have side effects, you can set explicitly set this field to `true`. + +### `scripts` + +The package scripts as defined by [NPM](https://docs.npmjs.com/cli/v10/configuring-npm/package-json#scripts). The Backstage CLI provides a set of standard scripts, which you can read more about in the [build system](./cli/02-build-system.md) section. The full list of scripts is as follows: + +```js +"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" +} +``` + +### `configSchema` + +The Backstage configuration schema for the package, as described in the [defining configuration](../conf/defining.md) section. + +### `backstage` + +This field is a collection of Backstage specific metadata fields. It is required for all Backstage packages, and any package that defines this field is considered to be part of the Backstage ecosystem. All sub-fields of this collection are defined below. + +### `backstage.role` + +This field defines the role of the package in the Backstage ecosystem. It can affect both the build process and runtime behavior, and signals the intended usage of the package to consumers. You can read more about this field in the [package roles](./cli/02-build-system.md#package-roles) section. + +### `backstage.pluginId` + +For any package that is part of a plugin, this field should be set to the plugin ID. This is the same ID as you would pass to the `createPlugin`, `createBackendPlugin`, or `createBackendModule` functions in the implementation of the package. It is also the same ID as the one described in the [name](#name) section. + +This field can be generated by the `backstage-cli repo fix --publish` command. The plugin ID will be inferred from the package [name](#name) and [role](#backstagerole). If the package name is not actually part of a plugin but still has `plugin-*` in its name, you can set this field to be explicitly `null`. + +The presence of this field is checked by the `backstage-cli package prepack` command, which is used to prepare a package for publishing. You can read more about this requirement in the section on [metadata for published packages](#metadata-for-published-packages). + +### `backstage.pluginPackages` + +For any package that is part of a plugin, this field should be set to a list of all packages that are directly part of the same plugin. This includes frontend and backend plugin packages as well as related libraries, but not modules. + +This field can be generated by the `backstage-cli repo fix --publish` command. It will list all packages with the same [plugin ID](#backstagepluginid) in the workspace. + +The presence of this field is checked by the `backstage-cli package prepack` command, which is used to prepare a package for publishing. You can read more about this requirement in the section on [metadata for published packages](#metadata-for-published-packages). + +```js title="Example usage of the backstage.pluginPackages field" +{ + "name": "@backstage/plugin-catalog", + "backstage": { + "role": "frontend-plugin", + "pluginId": "catalog", + "pluginPackages": [ + "@backstage/plugin-catalog", + "@backstage/plugin-catalog-backend", + "@backstage/plugin-catalog-common", + "@backstage/plugin-catalog-node", + "@backstage/plugin-catalog-react" + ] + } + ... +} +``` + +### `backstage.pluginPackage` + +For any module package of a plugin, this field should be set to the [name](#name) of the plugin package that this is a module for. + +This field can be generated by the `backstage-cli repo fix --publish` command. It checks for packages with a matching [plugin ID](#backstagepluginid) in the same workspace, but also knows the package names of the core feature plugin IDs such as `catalog`, `auth`, `scaffolder`, etc. If the package name can not be inferred, it has to be provided manually. + +The presence of this field is checked by the `backstage-cli package prepack` command, which is used to prepare a package for publishing. You can read more about this requirement in the section on [metadata for published packages](#metadata-for-published-packages). + +```js title="Example usage of the backstage.pluginPackage field" +{ + "name": "@backstage/plugin-catalog-backend-module-github", + "backstage": { + "role": "backend-plugin-module", + "pluginId": "catalog", + "pluginPackage": "@backstage/plugin-catalog-backend" + } + ... +} +``` + +### `backstage.moved` + +This field indicates that a package has been renamed and moved to a new location. This field is recognized by the Backstage CLI, where the version bump command will automatically switch to using the new package instead. The value of this field should be the new package name. + +```js title="Example usage of the backstage.moved field" +{ + "name": "@backstage/plugin-azure-devops", + "backstage": { + "moved": "@backstage-community/plugin-azure-devops" + } + ... +} +``` + +## Metadata for Published Packages + +When publishing a package with the help of the Backstage CLI, there are a number of metadata checks that are performed to ensure that the package is correctly set up for the Backstage ecosystem. These checks are performed by the `backstage-cli package prepack` command, which is used to prepare a package for publishing. These checks can all also be verified separately using the `backstage-cli repo fix --publish` command, and in many cases the required metadata can be generated automatically. It is therefore important to make running the `fix` command part of your workflow in any project that is publishing Backstage packages. + +To set this up, we recommend that you add the following script to the root `package.json` of your workspace: + +```js +{ + "scripts": { + "fix": "backstage-cli repo fix --publish" + } +} +``` + +This allows anyone working in the repo to run `yarn fix` to check and update all packages in the workspace. + +In addition, you should also add a check to your CI pipeline that ensures that there are no pending fixes. This is done by calling the command with the `--check` flag, which in GitHub actions would look something like this: + +```yaml +- name: check for missing repo fixes + run: yarn fix --check +``` + +Finally, if you are using Husky or any other pre-commit hook, you can also set up a hook to run the fix command before committing: + +```js +{ + "lint-staged": { + "package.json": [ + "yarn fix" + ] + } +} +``` diff --git a/docs/tutorials/setup-opentelemetry.md b/docs/tutorials/setup-opentelemetry.md index 30dde79db8..faaeab49f4 100644 --- a/docs/tutorials/setup-opentelemetry.md +++ b/docs/tutorials/setup-opentelemetry.md @@ -33,6 +33,7 @@ const { } = require('@opentelemetry/auto-instrumentations-node'); const { PrometheusExporter } = require('@opentelemetry/exporter-prometheus'); +// By default exports the metrics on localhost:9464/metrics const prometheus = new PrometheusExporter(); const sdk = new NodeSDK({ // You can add a traceExporter field here too diff --git a/microsite/data/plugins/digital.ai-release.yaml b/microsite/data/plugins/digital.ai-release.yaml new file mode 100644 index 0000000000..288a95a123 --- /dev/null +++ b/microsite/data/plugins/digital.ai-release.yaml @@ -0,0 +1,18 @@ +--- +title: Digital.ai Release +author: digital.ai +authorUrl: https://digital.ai/ +category: CI/CD +description: The plugin offers integration with Digital.ai Release and backstage. It provide access to active releases, templates and manage workflow executions. +documentation: https://docs.digital.ai/bundle/devops-release-version-v.24.1/page/release/concept/release-backstage-overview.html +iconUrl: /img/digital.ai-release.svg +npmPackageName: '@digital-ai/plugin-dai-release' +tags: + - ci + - cd + - release + - orchestration + - devops + - pipeline + - automation +addedDate: '2024-05-28' diff --git a/microsite/data/plugins/harness-chaos.yaml b/microsite/data/plugins/harness-chaos.yaml new file mode 100644 index 0000000000..ade6f9e566 --- /dev/null +++ b/microsite/data/plugins/harness-chaos.yaml @@ -0,0 +1,11 @@ +title: Harness Service Reliability Management +author: harness.io +authorUrl: https://github.com/harness/backstage-plugins +category: Chaos Engineering +description: This plugin lets you view the status of Harness Chaos Engineering Resources and launch Chaos Experiments directly inside Backstage. +documentation: https://github.com/harness/backstage-plugins/tree/main/plugins/harness-chaos +iconUrl: https://static.harness.io/ng-static/images/favicon.png +npmPackageName: '@harnessio/backstage-plugin-harness-chaos' +tags: + - resiliency +addedDate: '2024-06-25' diff --git a/microsite/docusaurus.config.ts b/microsite/docusaurus.config.ts index 9e2a70e74e..b1a6533ab9 100644 --- a/microsite/docusaurus.config.ts +++ b/microsite/docusaurus.config.ts @@ -241,7 +241,7 @@ const config: Config = { position: 'left', }, { - to: 'docs/releases/v1.27.0', + to: 'docs/releases/v1.28.0', label: 'Releases', position: 'left', }, diff --git a/microsite/sidebars.json b/microsite/sidebars.json index 5ddd2f97f1..075025afbb 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -1,6 +1,7 @@ { "releases": { "Release Notes": [ + "releases/v1.28.0", "releases/v1.27.0", "releases/v1.26.0", "releases/v1.25.0", @@ -302,6 +303,7 @@ "items": [ "auth/auth0/provider", "auth/atlassian/provider", + "auth/aws-alb/provider", "auth/microsoft/provider", "auth/microsoft/easy-auth", "auth/bitbucket/provider", @@ -362,7 +364,8 @@ "tooling/local-dev/linking-local-packages", "tooling/local-dev/debugging" ] - } + }, + "tooling/package-metadata" ], "Deployment": [ "deployment/index", diff --git a/microsite/static/img/digital.ai-release.svg b/microsite/static/img/digital.ai-release.svg new file mode 100644 index 0000000000..ba510e2a79 --- /dev/null +++ b/microsite/static/img/digital.ai-release.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/microsite/yarn.lock b/microsite/yarn.lock index ebaeb33c2f..00732d79f2 100644 --- a/microsite/yarn.lock +++ b/microsite/yarn.lock @@ -2696,94 +2696,94 @@ __metadata: languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.5.0": - version: 1.5.0 - resolution: "@swc/core-darwin-arm64@npm:1.5.0" +"@swc/core-darwin-arm64@npm:1.5.29": + version: 1.5.29 + resolution: "@swc/core-darwin-arm64@npm:1.5.29" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.5.0": - version: 1.5.0 - resolution: "@swc/core-darwin-x64@npm:1.5.0" +"@swc/core-darwin-x64@npm:1.5.29": + version: 1.5.29 + resolution: "@swc/core-darwin-x64@npm:1.5.29" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.5.0": - version: 1.5.0 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.5.0" +"@swc/core-linux-arm-gnueabihf@npm:1.5.29": + version: 1.5.29 + resolution: "@swc/core-linux-arm-gnueabihf@npm:1.5.29" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@swc/core-linux-arm64-gnu@npm:1.5.0": - version: 1.5.0 - resolution: "@swc/core-linux-arm64-gnu@npm:1.5.0" +"@swc/core-linux-arm64-gnu@npm:1.5.29": + version: 1.5.29 + resolution: "@swc/core-linux-arm64-gnu@npm:1.5.29" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.5.0": - version: 1.5.0 - resolution: "@swc/core-linux-arm64-musl@npm:1.5.0" +"@swc/core-linux-arm64-musl@npm:1.5.29": + version: 1.5.29 + resolution: "@swc/core-linux-arm64-musl@npm:1.5.29" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.5.0": - version: 1.5.0 - resolution: "@swc/core-linux-x64-gnu@npm:1.5.0" +"@swc/core-linux-x64-gnu@npm:1.5.29": + version: 1.5.29 + resolution: "@swc/core-linux-x64-gnu@npm:1.5.29" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.5.0": - version: 1.5.0 - resolution: "@swc/core-linux-x64-musl@npm:1.5.0" +"@swc/core-linux-x64-musl@npm:1.5.29": + version: 1.5.29 + resolution: "@swc/core-linux-x64-musl@npm:1.5.29" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.5.0": - version: 1.5.0 - resolution: "@swc/core-win32-arm64-msvc@npm:1.5.0" +"@swc/core-win32-arm64-msvc@npm:1.5.29": + version: 1.5.29 + resolution: "@swc/core-win32-arm64-msvc@npm:1.5.29" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.5.0": - version: 1.5.0 - resolution: "@swc/core-win32-ia32-msvc@npm:1.5.0" +"@swc/core-win32-ia32-msvc@npm:1.5.29": + version: 1.5.29 + resolution: "@swc/core-win32-ia32-msvc@npm:1.5.29" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.5.0": - version: 1.5.0 - resolution: "@swc/core-win32-x64-msvc@npm:1.5.0" +"@swc/core-win32-x64-msvc@npm:1.5.29": + version: 1.5.29 + resolution: "@swc/core-win32-x64-msvc@npm:1.5.29" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "@swc/core@npm:^1.3.46": - version: 1.5.0 - resolution: "@swc/core@npm:1.5.0" + version: 1.5.29 + resolution: "@swc/core@npm:1.5.29" dependencies: - "@swc/core-darwin-arm64": 1.5.0 - "@swc/core-darwin-x64": 1.5.0 - "@swc/core-linux-arm-gnueabihf": 1.5.0 - "@swc/core-linux-arm64-gnu": 1.5.0 - "@swc/core-linux-arm64-musl": 1.5.0 - "@swc/core-linux-x64-gnu": 1.5.0 - "@swc/core-linux-x64-musl": 1.5.0 - "@swc/core-win32-arm64-msvc": 1.5.0 - "@swc/core-win32-ia32-msvc": 1.5.0 - "@swc/core-win32-x64-msvc": 1.5.0 - "@swc/counter": ^0.1.2 - "@swc/types": ^0.1.5 + "@swc/core-darwin-arm64": 1.5.29 + "@swc/core-darwin-x64": 1.5.29 + "@swc/core-linux-arm-gnueabihf": 1.5.29 + "@swc/core-linux-arm64-gnu": 1.5.29 + "@swc/core-linux-arm64-musl": 1.5.29 + "@swc/core-linux-x64-gnu": 1.5.29 + "@swc/core-linux-x64-musl": 1.5.29 + "@swc/core-win32-arm64-msvc": 1.5.29 + "@swc/core-win32-ia32-msvc": 1.5.29 + "@swc/core-win32-x64-msvc": 1.5.29 + "@swc/counter": ^0.1.3 + "@swc/types": ^0.1.8 peerDependencies: - "@swc/helpers": ^0.5.0 + "@swc/helpers": "*" dependenciesMeta: "@swc/core-darwin-arm64": optional: true @@ -2808,21 +2808,23 @@ __metadata: peerDependenciesMeta: "@swc/helpers": optional: true - checksum: 1abab0b57755020b60ebf2557629c23c65c3546e4cd80f9d02fbdf208d4169c9300a0229c088081b43a01e630c9d86d02f8c240c9fc2842eaed2a517770fcd1d + checksum: 19e3f8525ce4f4d9f6f3f62825b1f13e1e76146390930b6d5e663c0bb2c5e95ef3bf30268110d1444ea92b99dd95bfe5a3c6e2a3c0dd79291505dc7da1ed3dab languageName: node linkType: hard -"@swc/counter@npm:^0.1.2, @swc/counter@npm:^0.1.3": +"@swc/counter@npm:^0.1.3": version: 0.1.3 resolution: "@swc/counter@npm:0.1.3" checksum: df8f9cfba9904d3d60f511664c70d23bb323b3a0803ec9890f60133954173047ba9bdeabce28cd70ba89ccd3fd6c71c7b0bd58be85f611e1ffbe5d5c18616598 languageName: node linkType: hard -"@swc/types@npm:^0.1.5": - version: 0.1.5 - resolution: "@swc/types@npm:0.1.5" - checksum: 6aee11f62d3d805a64848e0bd5f0e0e615f958e327a9e1260056c368d7d28764d89e38bd8005a536c9bf18afbcd303edd84099d60df34a2975d62540f61df13b +"@swc/types@npm:^0.1.8": + version: 0.1.8 + resolution: "@swc/types@npm:0.1.8" + dependencies: + "@swc/counter": ^0.1.3 + checksum: e564d0e37b0e28546973c6d50c7a179395912a97168d695cfe9cf1051199c8b828680cdafcb8d43948f76d3703873bafb88dfb5bc2dfe0596b4ad18fcaf90c80 languageName: node linkType: hard @@ -3996,11 +3998,11 @@ __metadata: linkType: hard "braces@npm:^3.0.2, braces@npm:~3.0.2": - version: 3.0.2 - resolution: "braces@npm:3.0.2" + version: 3.0.3 + resolution: "braces@npm:3.0.3" dependencies: - fill-range: ^7.0.1 - checksum: e2a8e769a863f3d4ee887b5fe21f63193a891c68b612ddb4b68d82d1b5f3ff9073af066c343e9867a393fe4c2555dcb33e89b937195feb9c1613d259edfcd459 + fill-range: ^7.1.1 + checksum: b95aa0b3bd909f6cd1720ffcf031aeaf46154dd88b4da01f9a1d3f7ea866a79eba76a6d01cbc3c422b2ee5cdc39a4f02491058d5df0d7bf6e6a162a832df1f69 languageName: node linkType: hard @@ -5111,11 +5113,11 @@ __metadata: linkType: hard "docusaurus-pushfeedback@npm:^1.0.0": - version: 1.0.0 - resolution: "docusaurus-pushfeedback@npm:1.0.0" + version: 1.0.1 + resolution: "docusaurus-pushfeedback@npm:1.0.1" peerDependencies: "@docusaurus/core": 3.x - checksum: 5f119fac4b18198ecab7ca3892b8d19ea21c1f4147b7500de0f2a341651630ff090e38ac4984e33d87729f1b00d621ae8945efe2a2ea37b9a74b76c7f468f21e + checksum: 45319080911438f828d9b550481511065de225b03511347324f9ecba133ce2693fa19fd394cd0a0e43b1723e15c2c988a11838a5cab1e3702295123be4b875a8 languageName: node linkType: hard @@ -5710,12 +5712,12 @@ __metadata: languageName: node linkType: hard -"fill-range@npm:^7.0.1": - version: 7.0.1 - resolution: "fill-range@npm:7.0.1" +"fill-range@npm:^7.1.1": + version: 7.1.1 + resolution: "fill-range@npm:7.1.1" dependencies: to-regex-range: ^5.0.1 - checksum: cc283f4e65b504259e64fd969bcf4def4eb08d85565e906b7d36516e87819db52029a76b6363d0f02d0d532f0033c9603b9e2d943d56ee3b0d4f7ad3328ff917 + checksum: b4abfbca3839a3d55e4ae5ec62e131e2e356bf4859ce8480c64c4876100f4df292a63e5bb1618e1d7460282ca2b305653064f01654474aa35c68000980f17798 languageName: node linkType: hard @@ -11870,8 +11872,8 @@ __metadata: linkType: hard "ws@npm:^7.3.1": - version: 7.5.9 - resolution: "ws@npm:7.5.9" + version: 7.5.10 + resolution: "ws@npm:7.5.10" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ^5.0.2 @@ -11880,7 +11882,7 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: c3c100a181b731f40b7f2fddf004aa023f79d64f489706a28bc23ff88e87f6a64b3c6651fbec3a84a53960b75159574d7a7385709847a62ddb7ad6af76f49138 + checksum: f9bb062abf54cc8f02d94ca86dcd349c3945d63851f5d07a3a61c2fcb755b15a88e943a63cf580cbdb5b74436d67ef6b67f745b8f7c0814e411379138e1863cb languageName: node linkType: hard diff --git a/mkdocs.yml b/mkdocs.yml index 026e76d531..b9f6d41d46 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -153,6 +153,7 @@ nav: - Included providers: - Atlassian: 'auth/atlassian/provider.md' - Auth0: 'auth/auth0/provider.md' + - AWS ALB: 'auth/aws-alb/provider.md' - Azure: 'auth/microsoft/provider.md' - Azure EasyAuth: 'auth/microsoft/azure-easyauth.md' - Bitbucket: 'auth/bitbucket/provider.md' @@ -180,6 +181,7 @@ nav: - Local Development: - Linking in Local Packages: 'tooling/local-dev/linking-local-packages.md' - Debugging Backstage: 'tooling/local-dev/debugging.md' + - Package Metadata: 'tooling/package-metadata.md' - Deployment: - Deploying Backstage: 'deployment/index.md' - Scaling: 'deployment/scaling.md' diff --git a/package.json b/package.json index 4868e93942..0946671f12 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "root", - "version": "1.28.0-next.2", + "version": "1.29.0-next.0", "private": true, "repository": { "type": "git", @@ -17,7 +17,7 @@ "build:all": "backstage-cli repo build --all", "build:api-docs": "LANG=en_EN yarn build:api-reports --docs --exclude 'plugins/@(adr|adr-backend|adr-common|airbrake|airbrake-backend|allure|analytics-module-ga|analytics-module-ga4|analytics-module-newrelic-browser|apache-airflow|api-docs|api-docs-module-protoc-gen-doc|apollo-explorer|app-visualizer|azure-devops|azure-devops-backend|azure-devops-common|azure-sites|azure-sites-backend|azure-sites-common|badges|badges-backend|bazaar|bazaar-backend|bitbucket-cloud-common|bitrise|catalog-graph|catalog-graphql|catalog-import|catalog-unprocessed-entities|cicd-statistics|cicd-statistics-module-gitlab|circleci|cloudbuild|code-climate|code-coverage|code-coverage-backend|codescene|config-schema|cost-insights|cost-insights-common|dynatrace|entity-feedback|entity-feedback-backend|entity-feedback-common|entity-validation|example-todo-list|example-todo-list-backend|example-todo-list-common|firehydrant|fossa|gcalendar|gcp-projects|git-release-manager|github-actions|github-deployments|github-issues|github-pull-requests-board|gitops-profiles|gocd|graphiql|graphql-backend|graphql-voyager|ilert|jenkins|jenkins-backend|jenkins-common|kafka|kafka-backend|lighthouse|lighthouse-backend|lighthouse-common|linguist|linguist-backend|linguist-common|microsoft-calendar|newrelic|newrelic-dashboard|nomad|nomad-backend|octopus-deploy|opencost|pagerduty|periskop|periskop-backend|playlist|playlist-backend|playlist-common|proxy-backend|puppetdb|rollbar|rollbar-backend|sentry|shortcuts|splunk-on-call|stack-overflow|stack-overflow-backend|stackstorm|tech-radar|tech-radar-2|todo|todo-backend|xcmetrics)'", "build:api-reports": "yarn build:api-reports:only --tsc", - "build:api-reports:only": "NODE_OPTIONS=--max-old-space-size=8192 backstage-repo-tools api-reports --allow-warnings 'packages/backend-common,packages/core-components,plugins/+(catalog|catalog-import|git-release-manager|jenkins|kubernetes)' -o ae-wrong-input-file-type --validate-release-tags", + "build:api-reports:only": "NODE_OPTIONS=--max-old-space-size=8192 backstage-repo-tools api-reports --allow-warnings 'packages/backend-app-api,packages/backend-common,packages/core-components,plugins/+(catalog|catalog-import|git-release-manager|jenkins|kubernetes)' -o ae-wrong-input-file-type --validate-release-tags", "build:backend": "yarn workspace example-backend build", "build:knip-reports": "backstage-repo-tools knip-reports", "build:plugins-report": "node ./scripts/build-plugins-report", @@ -94,6 +94,7 @@ "dependencies": { "@backstage/errors": "workspace:^", "@manypkg/get-packages": "^1.1.3", + "@types/global-agent": "^2.1.3", "@useoptic/optic": "^0.50.10" }, "devDependencies": { diff --git a/packages/app-defaults/CHANGELOG.md b/packages/app-defaults/CHANGELOG.md index 74ed9e5945..40ee32565f 100644 --- a/packages/app-defaults/CHANGELOG.md +++ b/packages/app-defaults/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/app-defaults +## 1.5.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/core-app-api@1.13.0-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/theme@0.5.6 + - @backstage/plugin-permission-react@0.4.23 + +## 1.5.6 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.8 + - @backstage/core-plugin-api@1.9.3 + - @backstage/theme@0.5.6 + - @backstage/plugin-permission-react@0.4.23 + - @backstage/core-app-api@1.12.6 + +## 1.5.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.8-next.2 + - @backstage/plugin-permission-react@0.4.23-next.1 + - @backstage/core-app-api@1.12.6-next.0 + - @backstage/core-plugin-api@1.9.3-next.0 + - @backstage/theme@0.5.6-next.0 + ## 1.5.6-next.1 ### Patch Changes diff --git a/packages/app-defaults/package.json b/packages/app-defaults/package.json index de173ffecc..5dc9e3d617 100644 --- a/packages/app-defaults/package.json +++ b/packages/app-defaults/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/app-defaults", - "version": "1.5.6-next.1", + "version": "1.5.7-next.0", "description": "Provides the default wiring of a Backstage App", "backstage": { "role": "web-library" diff --git a/packages/app-next-example-plugin/CHANGELOG.md b/packages/app-next-example-plugin/CHANGELOG.md index 70b5b29965..e6788c8566 100644 --- a/packages/app-next-example-plugin/CHANGELOG.md +++ b/packages/app-next-example-plugin/CHANGELOG.md @@ -1,5 +1,29 @@ # app-next-example-plugin +## 0.0.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/frontend-plugin-api@0.6.7-next.0 + +## 0.0.12 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.8 + - @backstage/frontend-plugin-api@0.6.6 + +## 0.0.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.8-next.2 + - @backstage/frontend-plugin-api@0.6.6-next.2 + ## 0.0.12-next.1 ### Patch Changes diff --git a/packages/app-next-example-plugin/package.json b/packages/app-next-example-plugin/package.json index f42c07952c..9d2e76c418 100644 --- a/packages/app-next-example-plugin/package.json +++ b/packages/app-next-example-plugin/package.json @@ -1,6 +1,6 @@ { "name": "app-next-example-plugin", - "version": "0.0.12-next.1", + "version": "0.0.13-next.0", "description": "Backstage internal example plugin", "backstage": { "role": "frontend-plugin", diff --git a/packages/app-next/CHANGELOG.md b/packages/app-next/CHANGELOG.md index 35842adb21..979284c459 100644 --- a/packages/app-next/CHANGELOG.md +++ b/packages/app-next/CHANGELOG.md @@ -1,5 +1,134 @@ # example-app-next +## 0.0.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder@1.22.0-next.0 + - @backstage/plugin-techdocs-react@1.2.6-next.0 + - @backstage/plugin-techdocs@1.10.7-next.0 + - @backstage/core-components@0.14.9-next.0 + - @backstage/core-app-api@1.13.0-next.0 + - @backstage/frontend-app-api@0.7.2-next.0 + - @backstage/cli@0.26.10-next.0 + - @backstage/plugin-org@0.6.27-next.0 + - @backstage/plugin-catalog-react@1.12.2-next.0 + - @backstage/plugin-catalog@1.21.1-next.0 + - @backstage/plugin-scaffolder-react@1.10.0-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.12-next.0 + - @backstage/app-defaults@1.5.7-next.0 + - @backstage/frontend-plugin-api@0.6.7-next.0 + - @backstage/integration-react@1.1.29-next.0 + - @backstage/plugin-api-docs@0.11.7-next.0 + - @backstage/plugin-app-visualizer@0.1.8-next.0 + - @backstage/plugin-auth-react@0.1.4-next.0 + - @backstage/plugin-catalog-graph@0.4.7-next.0 + - @backstage/plugin-catalog-import@0.12.1-next.0 + - @backstage/plugin-catalog-unprocessed-entities@0.2.6-next.0 + - @backstage/plugin-home@0.7.6-next.0 + - @backstage/plugin-kubernetes@0.11.12-next.0 + - @backstage/plugin-kubernetes-cluster@0.0.13-next.0 + - @backstage/plugin-notifications@0.2.3-next.0 + - @backstage/plugin-search@1.4.13-next.0 + - @backstage/plugin-search-react@1.7.13-next.0 + - @backstage/plugin-signals@0.0.8-next.0 + - @backstage/plugin-user-settings@0.8.8-next.0 + - @backstage/core-compat-api@0.2.7-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/theme@0.5.6 + - @backstage/plugin-catalog-common@1.0.24 + - @backstage/plugin-permission-react@0.4.23 + - @backstage/plugin-search-common@1.2.12 + +## 0.0.12 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.8 + - @backstage/plugin-techdocs@1.10.6 + - @backstage/plugin-api-docs@0.11.6 + - @backstage/core-compat-api@0.2.6 + - @backstage/cli@0.26.7 + - @backstage/plugin-scaffolder@1.21.0 + - @backstage/plugin-catalog-import@0.12.0 + - @backstage/plugin-kubernetes@0.11.11 + - @backstage/plugin-search@1.4.12 + - @backstage/plugin-catalog-graph@0.4.6 + - @backstage/plugin-notifications@0.2.2 + - @backstage/plugin-org@0.6.26 + - @backstage/core-plugin-api@1.9.3 + - @backstage/plugin-scaffolder-react@1.9.0 + - @backstage/theme@0.5.6 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.11 + - @backstage/plugin-catalog-unprocessed-entities@0.2.5 + - @backstage/plugin-kubernetes-cluster@0.0.12 + - @backstage/plugin-permission-react@0.4.23 + - @backstage/plugin-app-visualizer@0.1.7 + - @backstage/plugin-catalog-common@1.0.24 + - @backstage/plugin-techdocs-react@1.2.5 + - @backstage/plugin-catalog-react@1.12.1 + - @backstage/plugin-search-common@1.2.12 + - @backstage/plugin-user-settings@0.8.7 + - @backstage/plugin-search-react@1.7.12 + - @backstage/plugin-auth-react@0.1.3 + - @backstage/plugin-catalog@1.21.0 + - @backstage/plugin-signals@0.0.7 + - @backstage/plugin-home@0.7.5 + - @backstage/core-app-api@1.12.6 + - @backstage/integration-react@1.1.28 + - @backstage/app-defaults@1.5.6 + - @backstage/frontend-app-api@0.7.1 + - @backstage/frontend-plugin-api@0.6.6 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + +## 0.0.12-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-graph@0.4.6-next.2 + - @backstage/core-components@0.14.8-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.11-next.2 + - @backstage/plugin-catalog-unprocessed-entities@0.2.5-next.2 + - @backstage/plugin-kubernetes-cluster@0.0.12-next.3 + - @backstage/plugin-permission-react@0.4.23-next.1 + - @backstage/plugin-scaffolder-react@1.8.7-next.3 + - @backstage/plugin-app-visualizer@0.1.7-next.2 + - @backstage/plugin-catalog-common@1.0.24-next.0 + - @backstage/plugin-catalog-import@0.12.0-next.3 + - @backstage/plugin-techdocs-react@1.2.5-next.2 + - @backstage/plugin-catalog-react@1.12.1-next.2 + - @backstage/plugin-notifications@0.2.2-next.3 + - @backstage/plugin-search-common@1.2.12-next.0 + - @backstage/plugin-user-settings@0.8.7-next.2 + - @backstage/plugin-search-react@1.7.12-next.2 + - @backstage/plugin-auth-react@0.1.3-next.2 + - @backstage/plugin-kubernetes@0.11.11-next.3 + - @backstage/plugin-scaffolder@1.21.0-next.3 + - @backstage/plugin-api-docs@0.11.6-next.2 + - @backstage/plugin-techdocs@1.10.6-next.2 + - @backstage/plugin-catalog@1.21.0-next.3 + - @backstage/plugin-signals@0.0.7-next.2 + - @backstage/plugin-search@1.4.12-next.3 + - @backstage/plugin-home@0.7.5-next.2 + - @backstage/plugin-org@0.6.26-next.2 + - @backstage/integration-react@1.1.28-next.1 + - @backstage/cli@0.26.7-next.3 + - @backstage/app-defaults@1.5.6-next.2 + - @backstage/frontend-app-api@0.7.1-next.2 + - @backstage/frontend-plugin-api@0.6.6-next.2 + - @backstage/core-compat-api@0.2.6-next.2 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/core-app-api@1.12.6-next.0 + - @backstage/core-plugin-api@1.9.3-next.0 + - @backstage/theme@0.5.6-next.0 + ## 0.0.12-next.2 ### Patch Changes diff --git a/packages/app-next/package.json b/packages/app-next/package.json index c3496f5d3b..73141946ea 100644 --- a/packages/app-next/package.json +++ b/packages/app-next/package.json @@ -1,6 +1,6 @@ { "name": "example-app-next", - "version": "0.0.12-next.2", + "version": "0.0.13-next.0", "private": true, "repository": { "type": "git", @@ -62,7 +62,7 @@ "react-use": "^17.2.4", "vite": "^4.4.9", "vite-plugin-html": "^3.2.0", - "vite-plugin-node-polyfills": "^0.21.0", + "vite-plugin-node-polyfills": "^0.22.0", "zen-observable": "^0.10.0" }, "devDependencies": { diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index fc9f12b26f..ca64c31049 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,128 @@ # example-app +## 0.2.99-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder@1.22.0-next.0 + - @backstage/plugin-techdocs-react@1.2.6-next.0 + - @backstage/plugin-techdocs@1.10.7-next.0 + - @backstage/core-components@0.14.9-next.0 + - @backstage/core-app-api@1.13.0-next.0 + - @backstage/frontend-app-api@0.7.2-next.0 + - @backstage/cli@0.26.10-next.0 + - @backstage/plugin-org@0.6.27-next.0 + - @backstage/plugin-catalog-react@1.12.2-next.0 + - @backstage/plugin-catalog@1.21.1-next.0 + - @backstage/plugin-scaffolder-react@1.10.0-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.12-next.0 + - @backstage/app-defaults@1.5.7-next.0 + - @backstage/integration-react@1.1.29-next.0 + - @backstage/plugin-api-docs@0.11.7-next.0 + - @backstage/plugin-auth-react@0.1.4-next.0 + - @backstage/plugin-catalog-graph@0.4.7-next.0 + - @backstage/plugin-catalog-import@0.12.1-next.0 + - @backstage/plugin-catalog-unprocessed-entities@0.2.6-next.0 + - @backstage/plugin-devtools@0.1.16-next.0 + - @backstage/plugin-home@0.7.6-next.0 + - @backstage/plugin-kubernetes@0.11.12-next.0 + - @backstage/plugin-kubernetes-cluster@0.0.13-next.0 + - @backstage/plugin-notifications@0.2.3-next.0 + - @backstage/plugin-search@1.4.13-next.0 + - @backstage/plugin-search-react@1.7.13-next.0 + - @backstage/plugin-signals@0.0.8-next.0 + - @backstage/plugin-user-settings@0.8.8-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/theme@0.5.6 + - @backstage/plugin-catalog-common@1.0.24 + - @backstage/plugin-permission-react@0.4.23 + - @backstage/plugin-search-common@1.2.12 + +## 0.2.98 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.8 + - @backstage/plugin-techdocs@1.10.6 + - @backstage/plugin-api-docs@0.11.6 + - @backstage/cli@0.26.7 + - @backstage/plugin-scaffolder@1.21.0 + - @backstage/plugin-catalog-import@0.12.0 + - @backstage/plugin-kubernetes@0.11.11 + - @backstage/plugin-search@1.4.12 + - @backstage/plugin-catalog-graph@0.4.6 + - @backstage/plugin-notifications@0.2.2 + - @backstage/plugin-org@0.6.26 + - @backstage/core-plugin-api@1.9.3 + - @backstage/plugin-scaffolder-react@1.9.0 + - @backstage/theme@0.5.6 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.11 + - @backstage/plugin-catalog-unprocessed-entities@0.2.5 + - @backstage/plugin-kubernetes-cluster@0.0.12 + - @backstage/plugin-permission-react@0.4.23 + - @backstage/plugin-catalog-common@1.0.24 + - @backstage/plugin-techdocs-react@1.2.5 + - @backstage/plugin-catalog-react@1.12.1 + - @backstage/plugin-search-common@1.2.12 + - @backstage/plugin-user-settings@0.8.7 + - @backstage/plugin-search-react@1.7.12 + - @backstage/plugin-auth-react@0.1.3 + - @backstage/plugin-devtools@0.1.15 + - @backstage/plugin-catalog@1.21.0 + - @backstage/plugin-signals@0.0.7 + - @backstage/plugin-home@0.7.5 + - @backstage/core-app-api@1.12.6 + - @backstage/integration-react@1.1.28 + - @backstage/app-defaults@1.5.6 + - @backstage/frontend-app-api@0.7.1 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + +## 0.2.98-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-graph@0.4.6-next.2 + - @backstage/core-components@0.14.8-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.11-next.2 + - @backstage/plugin-catalog-unprocessed-entities@0.2.5-next.2 + - @backstage/plugin-kubernetes-cluster@0.0.12-next.3 + - @backstage/plugin-permission-react@0.4.23-next.1 + - @backstage/plugin-scaffolder-react@1.8.7-next.3 + - @backstage/plugin-catalog-common@1.0.24-next.0 + - @backstage/plugin-catalog-import@0.12.0-next.3 + - @backstage/plugin-techdocs-react@1.2.5-next.2 + - @backstage/plugin-catalog-react@1.12.1-next.2 + - @backstage/plugin-notifications@0.2.2-next.3 + - @backstage/plugin-search-common@1.2.12-next.0 + - @backstage/plugin-user-settings@0.8.7-next.2 + - @backstage/plugin-search-react@1.7.12-next.2 + - @backstage/plugin-auth-react@0.1.3-next.2 + - @backstage/plugin-kubernetes@0.11.11-next.3 + - @backstage/plugin-scaffolder@1.21.0-next.3 + - @backstage/plugin-api-docs@0.11.6-next.2 + - @backstage/plugin-devtools@0.1.15-next.2 + - @backstage/plugin-techdocs@1.10.6-next.2 + - @backstage/plugin-catalog@1.21.0-next.3 + - @backstage/plugin-signals@0.0.7-next.2 + - @backstage/plugin-search@1.4.12-next.3 + - @backstage/plugin-home@0.7.5-next.2 + - @backstage/plugin-org@0.6.26-next.2 + - @backstage/integration-react@1.1.28-next.1 + - @backstage/cli@0.26.7-next.3 + - @backstage/app-defaults@1.5.6-next.2 + - @backstage/frontend-app-api@0.7.1-next.2 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/core-app-api@1.12.6-next.0 + - @backstage/core-plugin-api@1.9.3-next.0 + - @backstage/theme@0.5.6-next.0 + ## 0.2.98-next.2 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index b08b838f7b..067b2d84eb 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "example-app", - "version": "0.2.98-next.2", + "version": "0.2.99-next.0", "backstage": { "role": "frontend" }, @@ -83,7 +83,7 @@ "react-use": "^17.2.4", "vite": "^4.4.9", "vite-plugin-html": "^3.2.0", - "vite-plugin-node-polyfills": "^0.21.0", + "vite-plugin-node-polyfills": "^0.22.0", "zen-observable": "^0.10.0" }, "devDependencies": { diff --git a/packages/backend-app-api/CHANGELOG.md b/packages/backend-app-api/CHANGELOG.md index 7d3bb8dabf..c9fe21c89e 100644 --- a/packages/backend-app-api/CHANGELOG.md +++ b/packages/backend-app-api/CHANGELOG.md @@ -1,5 +1,110 @@ # @backstage/backend-app-api +## 0.7.9-next.0 + +### Patch Changes + +- b60db08: Fixing exporting of classes properly from new packages +- a63c4b6: Fixing issue with `MiddlewareFactory` deprecation wrapping +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/plugin-permission-node@0.7.32-next.0 + - @backstage/cli-common@0.1.14 + - @backstage/cli-node@0.2.6 + - @backstage/config@1.2.0 + - @backstage/config-loader@1.8.1 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + +## 0.7.6 + +### Patch Changes + +- b7de623: Fixed a potential crash when passing an object with a `null` prototype as log meta. +- 9539a0b: Deprecated `authServiceFactory`, `httpAuthServiceFactory`, and `userInfoServiceFactory`. Please import them from `@backstage/backend-defaults/auth`, `@backstage/backend-defaults/httpAuth`, and `@backstage/backend-defaults/userInfo` respectively instead. +- 3e823d3: Limited user tokens will no longer include the `ent` field in its payload. Ownership claims will now be fetched from the user info service. + + NOTE: Limited tokens issued prior to this change will no longer be valid. Users may have to clear their browser cookies in order to refresh their auth tokens. + +- 78a0b08: Internal refactor to handle `BackendFeature` contract change. +- 398b82a: Add support for JWKS tokens in ExternalTokenHandler. +- 9e63318: Added an optional `accessRestrictions` to external access service tokens and service principals in general, such that you can limit their access to certain plugins or permissions. +- e25e467: Added a new static key based method for plugin-to-plugin auth. This is useful for example if you are running readonly service nodes that cannot use a database for the default public-key signature scheme outlined in [BEP-0003](https://github.com/backstage/backstage/tree/master/beps/0003-auth-architecture-evolution). Most users should want to stay on the more secure zero-config database signature scheme. + + You can generate a public and private key pair using `openssl`. + + - First generate a private key using the ES256 algorithm + + ```sh + openssl ecparam -name prime256v1 -genkey -out private.ec.key + ``` + + - Convert it to PKCS#8 format + + ```sh + openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in private.ec.key -out private.key + ``` + + - Extract the public key + + ```sh + openssl ec -inform PEM -outform PEM -pubout -in private.key -out public.key + ``` + + After this you have the files `private.key` and `public.key`. Put them in a place where you know their absolute paths, and then set up your app-config accordingly: + + ```yaml + backend: + auth: + keyStore: + type: static + static: + keys: + - publicKeyFile: /absolute/path/to/public.key + privateKeyFile: /absolute/path/to/private.key + keyId: some-custom-id + ``` + +- 7d30d95: Fixing issue with log meta fields possibly being circular refs +- 6a576dc: Stop using `getVoidLogger` in tests to reduce the dependency on the soon-to-deprecate `backstage-common` package. +- 6551b3d: Deprecated core service factories and implementations and moved them over to + subpath exports on `@backstage/backend-defaults` instead. E.g. + `@backstage/backend-defaults/scheduler` is where the service factory and default + implementation of `coreServices.scheduler` now lives. +- d617103: Updating the logger redaction message to something less dramatic +- Updated dependencies + - @backstage/cli-node@0.2.6 + - @backstage/backend-common@0.23.0 + - @backstage/backend-plugin-api@0.6.19 + - @backstage/backend-tasks@0.5.24 + - @backstage/plugin-auth-node@0.4.14 + - @backstage/plugin-permission-node@0.7.30 + - @backstage/cli-common@0.1.14 + - @backstage/config-loader@1.8.1 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + +## 0.7.6-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/cli-node@0.2.6-next.2 + - @backstage/backend-plugin-api@0.6.19-next.3 + - @backstage/plugin-auth-node@0.4.14-next.3 + - @backstage/plugin-permission-node@0.7.30-next.3 + - @backstage/cli-common@0.1.14-next.0 + - @backstage/backend-tasks@0.5.24-next.3 + - @backstage/backend-common@0.23.0-next.3 + - @backstage/config-loader@1.8.1-next.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + ## 0.7.6-next.2 ### Patch Changes diff --git a/packages/backend-app-api/api-report.md b/packages/backend-app-api/api-report.md index 3d7357cb87..7518f8e2cc 100644 --- a/packages/backend-app-api/api-report.md +++ b/packages/backend-app-api/api-report.md @@ -12,6 +12,7 @@ import { CacheService } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import { ConfigSchema } from '@backstage/config-loader'; import { CorsOptions } from 'cors'; +import { DatabaseService } from '@backstage/backend-plugin-api'; import { DiscoveryService } from '@backstage/backend-plugin-api'; import { ErrorRequestHandler } from 'express'; import { Express as Express_2 } from 'express'; @@ -28,7 +29,6 @@ import { LifecycleService } from '@backstage/backend-plugin-api'; import { LoadConfigOptionsRemote } from '@backstage/config-loader'; import { LoggerService } from '@backstage/backend-plugin-api'; import { PermissionsService } from '@backstage/backend-plugin-api'; -import { PluginDatabaseManager } from '@backstage/backend-common'; import { RemoteConfigSourceOptions } from '@backstage/config-loader'; import { RequestHandler } from 'express'; import { RequestListener } from 'http'; @@ -45,7 +45,7 @@ import { transport } from 'winston'; import { UrlReaderService } from '@backstage/backend-plugin-api'; import { UserInfoService } from '@backstage/backend-plugin-api'; -// @public (undocumented) +// @public @deprecated (undocumented) export const authServiceFactory: () => ServiceFactory; // @public (undocumented) @@ -68,26 +68,20 @@ export interface Backend { // @public @deprecated (undocumented) export const cacheServiceFactory: () => ServiceFactory; -// @public (undocumented) -export function createConfigSecretEnumerator(options: { - logger: LoggerService; - dir?: string; - schema?: ConfigSchema; -}): Promise<(config: Config) => Iterable>; +// Warning: (ae-forgotten-export) The symbol "createConfigSecretEnumerator_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export const createConfigSecretEnumerator: typeof createConfigSecretEnumerator_2; -// @public -export function createHttpServer( - listener: RequestListener, - options: HttpServerOptions, - deps: { - logger: LoggerService; - }, -): Promise; +// Warning: (ae-forgotten-export) The symbol "createHttpServer_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export const createHttpServer: typeof createHttpServer_2; -// @public -export function createLifecycleMiddleware( - options: LifecycleMiddlewareOptions, -): RequestHandler; +// Warning: (ae-forgotten-export) The symbol "createLifecycleMiddleware_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated +export const createLifecycleMiddleware: typeof createLifecycleMiddleware_2; // @public (undocumented) export function createSpecializedBackend( @@ -102,11 +96,11 @@ export interface CreateSpecializedBackendOptions { // @public @deprecated (undocumented) export const databaseServiceFactory: () => ServiceFactory< - PluginDatabaseManager, + DatabaseService, 'plugin' >; -// @public +// @public @deprecated export class DefaultRootHttpRouter implements RootHttpRouterService { // (undocumented) static create(options?: DefaultRootHttpRouterOptions): DefaultRootHttpRouter; @@ -116,10 +110,10 @@ export class DefaultRootHttpRouter implements RootHttpRouterService { use(path: string, handler: Handler): void; } -// @public -export interface DefaultRootHttpRouterOptions { - indexPath?: string | false; -} +// Warning: (ae-forgotten-export) The symbol "DefaultRootHttpRouterOptions_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated +export type DefaultRootHttpRouterOptions = DefaultRootHttpRouterOptions_2; // @public @deprecated (undocumented) export const discoveryServiceFactory: () => ServiceFactory< @@ -127,15 +121,10 @@ export const discoveryServiceFactory: () => ServiceFactory< 'plugin' >; -// @public -export interface ExtendedHttpServer extends http.Server { - // (undocumented) - port(): number; - // (undocumented) - start(): Promise; - // (undocumented) - stop(): Promise; -} +// Warning: (ae-forgotten-export) The symbol "ExtendedHttpServer_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export type ExtendedHttpServer = ExtendedHttpServer_2; // @public @deprecated export class HostDiscovery implements DiscoveryService { @@ -151,44 +140,31 @@ export class HostDiscovery implements DiscoveryService { getExternalBaseUrl(pluginId: string): Promise; } -// @public (undocumented) +// @public @deprecated (undocumented) export const httpAuthServiceFactory: () => ServiceFactory< HttpAuthService, 'plugin' >; -// @public (undocumented) -export interface HttpRouterFactoryOptions { - getPath?(pluginId: string): string; -} +// Warning: (ae-forgotten-export) The symbol "HttpRouterFactoryOptions_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export type HttpRouterFactoryOptions = HttpRouterFactoryOptions_2; -// @public (undocumented) +// @public @deprecated export const httpRouterServiceFactory: ( - options?: HttpRouterFactoryOptions | undefined, + options?: HttpRouterFactoryOptions_2 | undefined, ) => ServiceFactory; -// @public -export type HttpServerCertificateOptions = - | { - type: 'pem'; - key: string; - cert: string; - } - | { - type: 'generated'; - hostname: string; - }; +// Warning: (ae-forgotten-export) The symbol "HttpServerCertificateOptions_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export type HttpServerCertificateOptions = HttpServerCertificateOptions_2; -// @public -export type HttpServerOptions = { - listen: { - port: number; - host: string; - }; - https?: { - certificate: HttpServerCertificateOptions; - }; -}; +// Warning: (ae-forgotten-export) The symbol "HttpServerOptions_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export type HttpServerOptions = HttpServerOptions_2; // @public @deprecated export type IdentityFactoryOptions = { @@ -201,12 +177,10 @@ export const identityServiceFactory: ( options?: IdentityFactoryOptions | undefined, ) => ServiceFactory; -// @public -export interface LifecycleMiddlewareOptions { - // (undocumented) - lifecycle: LifecycleService; - startupRequestPauseTimeout?: HumanDuration; -} +// Warning: (ae-forgotten-export) The symbol "LifecycleMiddlewareOptions_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated +export type LifecycleMiddlewareOptions = LifecycleMiddlewareOptions_2; // @public @deprecated export const lifecycleServiceFactory: () => ServiceFactory< @@ -214,7 +188,7 @@ export const lifecycleServiceFactory: () => ServiceFactory< 'plugin' >; -// @public +// @public @deprecated export function loadBackendConfig(options: { remote?: LoadConfigOptionsRemote; argv: string[]; @@ -224,13 +198,13 @@ export function loadBackendConfig(options: { config: Config; }>; -// @public (undocumented) +// @public @deprecated export const loggerServiceFactory: () => ServiceFactory< LoggerService, 'plugin' >; -// @public +// @public @deprecated (undocumented) export class MiddlewareFactory { compression(): RequestHandler; cors(): RequestHandler; @@ -241,19 +215,15 @@ export class MiddlewareFactory { notFound(): RequestHandler; } -// @public -export interface MiddlewareFactoryErrorOptions { - logAllErrors?: boolean; - showStackTraces?: boolean; -} +// Warning: (ae-forgotten-export) The symbol "MiddlewareFactoryErrorOptions_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export type MiddlewareFactoryErrorOptions = MiddlewareFactoryErrorOptions_2; -// @public -export interface MiddlewareFactoryOptions { - // (undocumented) - config: RootConfigService; - // (undocumented) - logger: LoggerService; -} +// Warning: (ae-forgotten-export) The symbol "MiddlewareFactoryOptions_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export type MiddlewareFactoryOptions = MiddlewareFactoryOptions_2; // @public @deprecated (undocumented) export const permissionsServiceFactory: () => ServiceFactory< @@ -261,14 +231,20 @@ export const permissionsServiceFactory: () => ServiceFactory< 'plugin' >; -// @public -export function readCorsOptions(config?: Config): CorsOptions; +// Warning: (ae-forgotten-export) The symbol "readCorsOptions_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export const readCorsOptions: typeof readCorsOptions_2; -// @public -export function readHelmetOptions(config?: Config): HelmetOptions; +// Warning: (ae-forgotten-export) The symbol "readHelmetOptions_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export const readHelmetOptions: typeof readHelmetOptions_2; -// @public -export function readHttpServerOptions(config?: Config): HttpServerOptions; +// Warning: (ae-forgotten-export) The symbol "readHttpServerOptions_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export const readHttpServerOptions: typeof readHttpServerOptions_2; // @public @deprecated (undocumented) export interface RootConfigFactoryOptions { @@ -283,35 +259,19 @@ export const rootConfigServiceFactory: ( options?: RootConfigFactoryOptions | undefined, ) => ServiceFactory; -// @public (undocumented) -export interface RootHttpRouterConfigureContext { - // (undocumented) - app: Express_2; - // (undocumented) - applyDefaults: () => void; - // (undocumented) - config: RootConfigService; - // (undocumented) - lifecycle: LifecycleService; - // (undocumented) - logger: LoggerService; - // (undocumented) - middleware: MiddlewareFactory; - // (undocumented) - routes: RequestHandler; - // (undocumented) - server: Server; -} +// Warning: (ae-forgotten-export) The symbol "RootHttpRouterConfigureContext_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export type RootHttpRouterConfigureContext = RootHttpRouterConfigureContext_2; -// @public (undocumented) -export type RootHttpRouterFactoryOptions = { - indexPath?: string | false; - configure?(context: RootHttpRouterConfigureContext): void; -}; +// Warning: (ae-forgotten-export) The symbol "RootHttpRouterFactoryOptions_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated +export type RootHttpRouterFactoryOptions = RootHttpRouterFactoryOptions_2; -// @public (undocumented) +// @public @deprecated (undocumented) export const rootHttpRouterServiceFactory: ( - options?: RootHttpRouterFactoryOptions | undefined, + options?: RootHttpRouterFactoryOptions_2 | undefined, ) => ServiceFactory; // @public @deprecated @@ -320,7 +280,7 @@ export const rootLifecycleServiceFactory: () => ServiceFactory< 'root' >; -// @public (undocumented) +// @public @deprecated export const rootLoggerServiceFactory: () => ServiceFactory< RootLoggerService, 'root' @@ -344,13 +304,13 @@ export const urlReaderServiceFactory: () => ServiceFactory< 'plugin' >; -// @public (undocumented) +// @public @deprecated (undocumented) export const userInfoServiceFactory: () => ServiceFactory< UserInfoService, 'plugin' >; -// @public +// @public @deprecated export class WinstonLogger implements RootLoggerService { // (undocumented) addRedactions(redactions: Iterable): void; @@ -372,15 +332,8 @@ export class WinstonLogger implements RootLoggerService { warn(message: string, meta?: JsonObject): void; } -// @public (undocumented) -export interface WinstonLoggerOptions { - // (undocumented) - format?: Format; - // (undocumented) - level?: string; - // (undocumented) - meta?: JsonObject; - // (undocumented) - transports?: transport[]; -} +// Warning: (ae-forgotten-export) The symbol "WinstonLoggerOptions_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export type WinstonLoggerOptions = WinstonLoggerOptions_2; ``` diff --git a/packages/backend-app-api/config.d.ts b/packages/backend-app-api/config.d.ts index 80f97cb4b5..a23bca447b 100644 --- a/packages/backend-app-api/config.d.ts +++ b/packages/backend-app-api/config.d.ts @@ -33,6 +33,39 @@ export interface Config { */ dangerouslyDisableDefaultAuthPolicy?: boolean; + /** Controls how to store keys for plugin-to-plugin auth */ + pluginKeyStore?: + | { type: 'database' } + | { + type: 'static'; + static: { + /** + * Must be declared at least once and the first one will be used for signing. + */ + keys: Array<{ + /** + * Path to the public key file in the SPKI format. Should be an absolute path. + */ + publicKeyFile: string; + /** + * Path to the matching private key file in the PKCS#8 format. Should be an absolute path. + * + * The first array entry must specify a private key file, the rest must not. + */ + privateKeyFile?: string; + /** + * ID to uniquely identify this key within the JWK set. + */ + keyId: string; + /** + * JWS "alg" (Algorithm) Header Parameter value. Defaults to ES256. + * Must match the algorithm used to generate the keys in the provided files + */ + algorithm?: string; + }>; + }; + }; + /** * Configures methods of external access, ie ways for callers outside of * the Backstage ecosystem to get authorized for access to APIs that do diff --git a/packages/backend-app-api/package.json b/packages/backend-app-api/package.json index efeff8a96d..51bbca14bc 100644 --- a/packages/backend-app-api/package.json +++ b/packages/backend-app-api/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/backend-app-api", - "version": "0.7.6-next.2", + "version": "0.7.9-next.0", "description": "Core API used by Backstage backend apps", "backstage": { "role": "node-library" @@ -79,6 +79,7 @@ "minimatch": "^9.0.0", "minimist": "^1.2.5", "morgan": "^1.10.0", + "node-fetch": "^2.6.7", "node-forge": "^1.3.1", "path-to-regexp": "^6.2.1", "selfsigned": "^2.0.0", @@ -89,6 +90,7 @@ "winston-transport": "^4.5.0" }, "devDependencies": { + "@backstage/backend-defaults": "workspace:^", "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/compression": "^1.7.0", diff --git a/packages/backend-app-api/src/alpha/featureDiscoveryServiceFactory.ts b/packages/backend-app-api/src/alpha/featureDiscoveryServiceFactory.ts index 5943261b0b..c16a3f6534 100644 --- a/packages/backend-app-api/src/alpha/featureDiscoveryServiceFactory.ts +++ b/packages/backend-app-api/src/alpha/featureDiscoveryServiceFactory.ts @@ -168,7 +168,7 @@ export const featureDiscoveryServiceFactory = createServiceFactory({ function isBackendFeature(value: unknown): value is BackendFeature { return ( !!value && - typeof value === 'object' && + ['object', 'function'].includes(typeof value) && (value as BackendFeature).$$type === '@backstage/BackendFeature' ); } diff --git a/packages/backend-app-api/src/config/config.ts b/packages/backend-app-api/src/config/config.ts index 60d1e46e90..957997849e 100644 --- a/packages/backend-app-api/src/config/config.ts +++ b/packages/backend-app-api/src/config/config.ts @@ -14,56 +14,27 @@ * limitations under the License. */ +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { createConfigSecretEnumerator as _createConfigSecretEnumerator } from '../../../backend-defaults/src/entrypoints/rootConfig/createConfigSecretEnumerator'; + import { resolve as resolvePath } from 'path'; import parseArgs from 'minimist'; -import { LoggerService } from '@backstage/backend-plugin-api'; import { findPaths } from '@backstage/cli-common'; import { - loadConfigSchema, loadConfig, ConfigTarget, LoadConfigOptionsRemote, - ConfigSchema, } from '@backstage/config-loader'; import { ConfigReader } from '@backstage/config'; import type { Config, AppConfig } from '@backstage/config'; -import { getPackages } from '@manypkg/get-packages'; import { ObservableConfigProxy } from './ObservableConfigProxy'; import { isValidUrl } from '../lib/urls'; -/** @public */ -export async function createConfigSecretEnumerator(options: { - logger: LoggerService; - dir?: string; - schema?: ConfigSchema; -}): Promise<(config: Config) => Iterable> { - const { logger, dir = process.cwd() } = options; - const { packages } = await getPackages(dir); - const schema = - options.schema ?? - (await loadConfigSchema({ - dependencies: packages.map(p => p.packageJson.name), - })); - - return (config: Config) => { - const [secretsData] = schema.process( - [{ data: config.getOptional() ?? {}, context: 'schema-enumerator' }], - { - visibility: ['secret'], - ignoreSchemaErrors: true, - }, - ); - const secrets = new Set(); - JSON.parse( - JSON.stringify(secretsData.data), - (_, v) => typeof v === 'string' && secrets.add(v), - ); - logger.info( - `Found ${secrets.size} new secrets in config that will be redacted`, - ); - return secrets; - }; -} +/** + * @public + * @deprecated Please import from `@backstage/backend-defaults/rootConfig` instead. + */ +export const createConfigSecretEnumerator = _createConfigSecretEnumerator; /** * Load configuration for a Backend. @@ -71,6 +42,7 @@ export async function createConfigSecretEnumerator(options: { * This function should only be called once, during the initialization of the backend. * * @public + * @deprecated Please migrate to the new backend system and use `coreServices.rootConfig` instead, or the {@link @backstage/config-loader#ConfigSources} facilities if required. */ export async function loadBackendConfig(options: { remote?: LoadConfigOptionsRemote; diff --git a/packages/backend-app-api/src/http/index.ts b/packages/backend-app-api/src/http/index.ts index 4a9ec14cf8..a056ed2d61 100644 --- a/packages/backend-app-api/src/http/index.ts +++ b/packages/backend-app-api/src/http/index.ts @@ -14,17 +14,174 @@ * limitations under the License. */ -export { readHttpServerOptions } from './config'; -export { createHttpServer } from './createHttpServer'; -export { MiddlewareFactory } from './MiddlewareFactory'; -export type { - MiddlewareFactoryErrorOptions, - MiddlewareFactoryOptions, -} from './MiddlewareFactory'; -export { readCorsOptions } from './readCorsOptions'; -export { readHelmetOptions } from './readHelmetOptions'; -export type { - ExtendedHttpServer, - HttpServerCertificateOptions, - HttpServerOptions, -} from './types'; +import { ErrorRequestHandler, RequestHandler } from 'express'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { + readHttpServerOptions as _readHttpServerOptions, + createHttpServer as _createHttpServer, + MiddlewareFactory as _MiddlewareFactory, + readCorsOptions as _readCorsOptions, + readHelmetOptions as _readHelmetOptions, + type MiddlewareFactoryErrorOptions as _MiddlewareFactoryErrorOptions, + type MiddlewareFactoryOptions as _MiddlewareFactoryOptions, + type ExtendedHttpServer as _ExtendedHttpServer, + type HttpServerCertificateOptions as _HttpServerCertificateOptions, + type HttpServerOptions as _HttpServerOptions, +} from '../../../backend-defaults/src/entrypoints/rootHttpRouter/http'; + +/** + * @public + * @deprecated Please import from `@backstage/backend-defaults/rootHttpRouter` instead. + */ +export const readHttpServerOptions = _readHttpServerOptions; +/** + * @public + * @deprecated Please import from `@backstage/backend-defaults/rootHttpRouter` instead. + */ +export const createHttpServer = _createHttpServer; +/** + * @public + * @deprecated Please import from `@backstage/backend-defaults/rootHttpRouter` instead. + */ +export const readCorsOptions = _readCorsOptions; +/** + * @public + * @deprecated Please import from `@backstage/backend-defaults/rootHttpRouter` instead. + */ +export const readHelmetOptions = _readHelmetOptions; +/** + * @public + * @deprecated Please import from `@backstage/backend-defaults/rootHttpRouter` instead. + */ +export class MiddlewareFactory { + /** + * Creates a new {@link MiddlewareFactory}. + */ + static create(options: MiddlewareFactoryOptions) { + return new MiddlewareFactory(_MiddlewareFactory.create(options)); + } + + private constructor(private readonly impl: _MiddlewareFactory) {} + + /** + * Returns a middleware that unconditionally produces a 404 error response. + * + * @remarks + * + * Typically you want to place this middleware at the end of the chain, such + * that it's the last one attempted after no other routes matched. + * + * @returns An Express request handler + */ + notFound(): RequestHandler { + return this.impl.notFound(); + } + + /** + * Returns the compression middleware. + * + * @remarks + * + * The middleware will attempt to compress response bodies for all requests + * that traverse through the middleware. + */ + compression(): RequestHandler { + return this.impl.compression(); + } + + /** + * Returns a request logging middleware. + * + * @remarks + * + * Typically you want to place this middleware at the start of the chain, such + * that it always logs requests whether they are "caught" by handlers farther + * down or not. + * + * @returns An Express request handler + */ + logging(): RequestHandler { + return this.impl.logging(); + } + + /** + * Returns a middleware that implements the helmet library. + * + * @remarks + * + * This middleware applies security policies to incoming requests and outgoing + * responses. It is configured using config keys such as `backend.csp`. + * + * @see {@link https://helmetjs.github.io/} + * + * @returns An Express request handler + */ + helmet(): RequestHandler { + return this.impl.helmet(); + } + + /** + * Returns a middleware that implements the cors library. + * + * @remarks + * + * This middleware handles CORS. It is configured using the config key + * `backend.cors`. + * + * @see {@link https://github.com/expressjs/cors} + * + * @returns An Express request handler + */ + cors(): RequestHandler { + return this.impl.cors(); + } + + /** + * Express middleware to handle errors during request processing. + * + * @remarks + * + * This is commonly the very last middleware in the chain. + * + * Its primary purpose is not to do translation of business logic exceptions, + * but rather to be a global catch-all for uncaught "fatal" errors that are + * expected to result in a 500 error. However, it also does handle some common + * error types (such as http-error exceptions, and the well-known error types + * in the `@backstage/errors` package) and returns the enclosed status code + * accordingly. + * + * It will also produce a response body with a serialized form of the error, + * unless a previous handler already did send a body. See + * {@link @backstage/errors#ErrorResponseBody} for the response shape used. + * + * @returns An Express error request handler + */ + error(options: MiddlewareFactoryErrorOptions = {}): ErrorRequestHandler { + return this.impl.error(options); + } +} +/** + * @public + * @deprecated Please import from `@backstage/backend-defaults/rootHttpRouter` instead. + */ +export type MiddlewareFactoryErrorOptions = _MiddlewareFactoryErrorOptions; +/** + * @public + * @deprecated Please import from `@backstage/backend-defaults/rootHttpRouter` instead. + */ +export type MiddlewareFactoryOptions = _MiddlewareFactoryOptions; +/** + * @public + * @deprecated Please import from `@backstage/backend-defaults/rootHttpRouter` instead. + */ +export type ExtendedHttpServer = _ExtendedHttpServer; +/** + * @public + * @deprecated Please import from `@backstage/backend-defaults/rootHttpRouter` instead. + */ +export type HttpServerCertificateOptions = _HttpServerCertificateOptions; +/** + * @public + * @deprecated Please import from `@backstage/backend-defaults/rootHttpRouter` instead. + */ +export type HttpServerOptions = _HttpServerOptions; diff --git a/packages/backend-app-api/src/logging/WinstonLogger.ts b/packages/backend-app-api/src/logging/WinstonLogger.ts index 64e97b230c..e5403906ce 100644 --- a/packages/backend-app-api/src/logging/WinstonLogger.ts +++ b/packages/backend-app-api/src/logging/WinstonLogger.ts @@ -14,65 +14,37 @@ * limitations under the License. */ +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { + WinstonLogger as _WinstonLogger, + type WinstonLoggerOptions as _WinstonLoggerOptions, +} from '../../../backend-defaults/src/entrypoints/rootLogger'; + import { LoggerService, RootLoggerService, } from '@backstage/backend-plugin-api'; import { JsonObject } from '@backstage/types'; -import { Format, TransformableInfo } from 'logform'; -import { - Logger, - format, - createLogger, - transports, - transport as Transport, -} from 'winston'; -import { MESSAGE } from 'triple-beam'; -import { escapeRegExp } from '../lib/escapeRegExp'; +import { Format } from 'logform'; /** * @public + * @deprecated Please import from `@backstage/backend-defaults/rootLogger` instead. */ -export interface WinstonLoggerOptions { - meta?: JsonObject; - level?: string; - format?: Format; - transports?: Transport[]; -} +export type WinstonLoggerOptions = _WinstonLoggerOptions; /** * A {@link @backstage/backend-plugin-api#LoggerService} implementation based on winston. * * @public + * @deprecated Please import from `@backstage/backend-defaults/rootLogger` instead. */ export class WinstonLogger implements RootLoggerService { - #winston: Logger; - #addRedactions?: (redactions: Iterable) => void; - /** * Creates a {@link WinstonLogger} instance. */ static create(options: WinstonLoggerOptions): WinstonLogger { - const redacter = WinstonLogger.redacter(); - const defaultFormatter = - process.env.NODE_ENV === 'production' - ? format.json() - : WinstonLogger.colorFormat(); - - let logger = createLogger({ - level: process.env.LOG_LEVEL || options.level || 'info', - format: format.combine( - options.format ?? defaultFormatter, - redacter.format, - ), - transports: options.transports ?? new transports.Console(), - }); - - if (options.meta) { - logger = logger.child(options.meta); - } - - return new WinstonLogger(logger, redacter.add); + return new WinstonLogger(_WinstonLogger.create(options)); } /** @@ -82,111 +54,39 @@ export class WinstonLogger implements RootLoggerService { format: Format; add: (redactions: Iterable) => void; } { - const redactionSet = new Set(); - - let redactionPattern: RegExp | undefined = undefined; - - return { - format: format((obj: TransformableInfo) => { - if (!redactionPattern || !obj) { - return obj; - } - - obj[MESSAGE] = obj[MESSAGE]?.replace?.(redactionPattern, '***'); - - return obj; - })(), - add(newRedactions) { - let added = 0; - for (const redactionToTrim of newRedactions) { - // Trimming the string ensures that we don't accdentally get extra - // newlines or other whitespace interfering with the redaction; this - // can happen for example when using string literals in yaml - const redaction = redactionToTrim.trim(); - // Exclude secrets that are empty or just one character in length. These - // typically mean that you are running local dev or tests, or using the - // --lax flag which sets things to just 'x'. - if (redaction.length <= 1) { - continue; - } - if (!redactionSet.has(redaction)) { - redactionSet.add(redaction); - added += 1; - } - } - if (added > 0) { - const redactions = Array.from(redactionSet) - .map(r => escapeRegExp(r)) - .join('|'); - redactionPattern = new RegExp(`(${redactions})`, 'g'); - } - }, - }; + return _WinstonLogger.redacter(); } /** * Creates a pretty printed winston log formatter. */ static colorFormat(): Format { - const colorizer = format.colorize(); - - return format.combine( - format.timestamp(), - format.colorize({ - colors: { - timestamp: 'dim', - prefix: 'blue', - field: 'cyan', - debug: 'grey', - }, - }), - format.printf((info: TransformableInfo) => { - const { timestamp, level, message, plugin, service, ...fields } = info; - const prefix = plugin || service; - const timestampColor = colorizer.colorize('timestamp', timestamp); - const prefixColor = colorizer.colorize('prefix', prefix); - - const extraFields = Object.entries(fields) - .map( - ([key, value]) => - `${colorizer.colorize('field', `${key}`)}=${value}`, - ) - .join(' '); - - return `${timestampColor} ${prefixColor} ${level} ${message} ${extraFields}`; - }), - ); + return _WinstonLogger.colorFormat(); } - private constructor( - winston: Logger, - addRedactions?: (redactions: Iterable) => void, - ) { - this.#winston = winston; - this.#addRedactions = addRedactions; - } + private constructor(private readonly impl: _WinstonLogger) {} error(message: string, meta?: JsonObject): void { - this.#winston.error(message, meta); + this.impl.error(message, meta); } warn(message: string, meta?: JsonObject): void { - this.#winston.warn(message, meta); + this.impl.warn(message, meta); } info(message: string, meta?: JsonObject): void { - this.#winston.info(message, meta); + this.impl.info(message, meta); } debug(message: string, meta?: JsonObject): void { - this.#winston.debug(message, meta); + this.impl.debug(message, meta); } child(meta: JsonObject): LoggerService { - return new WinstonLogger(this.#winston.child(meta)); + return this.impl.child(meta); } addRedactions(redactions: Iterable) { - this.#addRedactions?.(redactions); + this.impl.addRedactions(redactions); } } diff --git a/packages/backend-app-api/src/services/implementations/auth/authServiceFactory.ts b/packages/backend-app-api/src/services/implementations/auth/authServiceFactory.ts index ad4fb17d88..988b907b4c 100644 --- a/packages/backend-app-api/src/services/implementations/auth/authServiceFactory.ts +++ b/packages/backend-app-api/src/services/implementations/auth/authServiceFactory.ts @@ -14,67 +14,11 @@ * limitations under the License. */ -import { - coreServices, - createServiceFactory, -} from '@backstage/backend-plugin-api'; -import { DatabaseKeyStore } from './DatabaseKeyStore'; -import { DefaultAuthService } from './DefaultAuthService'; -import { PluginTokenHandler } from './plugin/PluginTokenHandler'; -import { UserTokenHandler } from './user/UserTokenHandler'; -import { ExternalTokenHandler } from './external/ExternalTokenHandler'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { authServiceFactory as _authServiceFactory } from '../../../../../backend-defaults/src/entrypoints/auth'; -/** @public */ -export const authServiceFactory = createServiceFactory({ - service: coreServices.auth, - deps: { - config: coreServices.rootConfig, - logger: coreServices.rootLogger, - discovery: coreServices.discovery, - plugin: coreServices.pluginMetadata, - database: coreServices.database, - // Re-using the token manager makes sure that we use the same generated keys for - // development as plugins that have not yet been migrated. It's important that this - // keeps working as long as there are plugins that have not been migrated to the - // new auth services in the new backend system. - tokenManager: coreServices.tokenManager, - }, - async factory({ config, discovery, plugin, tokenManager, logger, database }) { - const disableDefaultAuthPolicy = Boolean( - config.getOptionalBoolean( - 'backend.auth.dangerouslyDisableDefaultAuthPolicy', - ), - ); - - const publicKeyStore = await DatabaseKeyStore.create({ - database, - logger, - }); - - const userTokens = UserTokenHandler.create({ - discovery, - }); - const pluginTokens = PluginTokenHandler.create({ - ownPluginId: plugin.getId(), - keyDuration: { hours: 1 }, - logger, - publicKeyStore, - discovery, - }); - const externalTokens = ExternalTokenHandler.create({ - ownPluginId: plugin.getId(), - config, - logger, - }); - - return new DefaultAuthService( - userTokens, - pluginTokens, - externalTokens, - tokenManager, - plugin.getId(), - disableDefaultAuthPolicy, - publicKeyStore, - ); - }, -}); +/** + * @public + * @deprecated Please import from `@backstage/backend-defaults/auth` instead. + */ +export const authServiceFactory = _authServiceFactory; diff --git a/packages/backend-app-api/src/services/implementations/deprecated.ts b/packages/backend-app-api/src/services/implementations/deprecated.ts index 6f4f76e679..347a968bce 100644 --- a/packages/backend-app-api/src/services/implementations/deprecated.ts +++ b/packages/backend-app-api/src/services/implementations/deprecated.ts @@ -14,4 +14,11 @@ * limitations under the License. */ +export * from './auth'; +export * from './httpAuth'; +export * from './httpRouter'; +export * from './logger'; +export * from './rootHttpRouter'; +export * from './rootLogger'; export * from './scheduler'; +export * from './userInfo'; diff --git a/packages/backend-app-api/src/services/implementations/discovery/HostDiscovery.ts b/packages/backend-app-api/src/services/implementations/discovery/HostDiscovery.ts index d337da997a..5909dd1ae6 100644 --- a/packages/backend-app-api/src/services/implementations/discovery/HostDiscovery.ts +++ b/packages/backend-app-api/src/services/implementations/discovery/HostDiscovery.ts @@ -15,10 +15,9 @@ */ import { Config } from '@backstage/config'; -import { readHttpServerOptions } from '@backstage/backend-app-api'; import { DiscoveryService } from '@backstage/backend-plugin-api'; - -type Target = string | { internal: string; external: string }; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { HostDiscovery as _HostDiscovery } from '../../../../../backend-defaults/src/entrypoints/discovery'; /** * HostDiscovery is a basic PluginEndpointDiscovery implementation @@ -57,77 +56,16 @@ export class HostDiscovery implements DiscoveryService { * path for the `catalog` plugin will be `http://localhost:7007/api/catalog`. */ static fromConfig(config: Config, options?: { basePath?: string }) { - const basePath = options?.basePath ?? '/api'; - const externalBaseUrl = config - .getString('backend.baseUrl') - .replace(/\/+$/, ''); - - const { - listen: { host: listenHost = '::', port: listenPort }, - } = readHttpServerOptions(config.getConfig('backend')); - const protocol = config.has('backend.https') ? 'https' : 'http'; - - // Translate bind-all to localhost, and support IPv6 - let host = listenHost; - if (host === '::' || host === '') { - // We use localhost instead of ::1, since IPv6-compatible systems should default - // to using IPv6 when they see localhost, but if the system doesn't support IPv6 - // things will still work. - host = 'localhost'; - } else if (host === '0.0.0.0') { - host = '127.0.0.1'; - } - if (host.includes(':')) { - host = `[${host}]`; - } - - const internalBaseUrl = `${protocol}://${host}:${listenPort}`; - - return new HostDiscovery( - internalBaseUrl + basePath, - externalBaseUrl + basePath, - config.getOptionalConfig('discovery'), - ); + return new HostDiscovery(_HostDiscovery.fromConfig(config, options)); } - private constructor( - private readonly internalBaseUrl: string, - private readonly externalBaseUrl: string, - private readonly discoveryConfig: Config | undefined, - ) {} - - private getTargetFromConfig(pluginId: string, type: 'internal' | 'external') { - const endpoints = this.discoveryConfig?.getOptionalConfigArray('endpoints'); - - const target = endpoints - ?.find(endpoint => endpoint.getStringArray('plugins').includes(pluginId)) - ?.get('target'); - - if (!target) { - const baseUrl = - type === 'external' ? this.externalBaseUrl : this.internalBaseUrl; - - return `${baseUrl}/${encodeURIComponent(pluginId)}`; - } - - if (typeof target === 'string') { - return target.replace( - /\{\{\s*pluginId\s*\}\}/g, - encodeURIComponent(pluginId), - ); - } - - return target[type].replace( - /\{\{\s*pluginId\s*\}\}/g, - encodeURIComponent(pluginId), - ); - } + private constructor(private readonly impl: _HostDiscovery) {} async getBaseUrl(pluginId: string): Promise { - return this.getTargetFromConfig(pluginId, 'internal'); + return this.impl.getBaseUrl(pluginId); } async getExternalBaseUrl(pluginId: string): Promise { - return this.getTargetFromConfig(pluginId, 'external'); + return this.impl.getExternalBaseUrl(pluginId); } } diff --git a/packages/backend-app-api/src/services/implementations/httpAuth/httpAuthServiceFactory.ts b/packages/backend-app-api/src/services/implementations/httpAuth/httpAuthServiceFactory.ts index c85ba6e4b3..373dd10ead 100644 --- a/packages/backend-app-api/src/services/implementations/httpAuth/httpAuthServiceFactory.ts +++ b/packages/backend-app-api/src/services/implementations/httpAuth/httpAuthServiceFactory.ts @@ -14,273 +14,11 @@ * limitations under the License. */ -import { - AuthService, - BackstageCredentials, - BackstagePrincipalTypes, - BackstageUserPrincipal, - DiscoveryService, - HttpAuthService, - coreServices, - createServiceFactory, -} from '@backstage/backend-plugin-api'; -import { AuthenticationError, NotAllowedError } from '@backstage/errors'; -import { parse as parseCookie } from 'cookie'; -import { Request, Response } from 'express'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { httpAuthServiceFactory as _httpAuthServiceFactory } from '../../../../../backend-defaults/src/entrypoints/httpAuth'; -const FIVE_MINUTES_MS = 5 * 60 * 1000; - -const BACKSTAGE_AUTH_COOKIE = 'backstage-auth'; - -function getTokenFromRequest(req: Request) { - // TODO: support multiple auth headers (iterate rawHeaders) - const authHeader = req.headers.authorization; - if (typeof authHeader === 'string') { - const matches = authHeader.match(/^Bearer[ ]+(\S+)$/i); - const token = matches?.[1]; - if (token) { - return token; - } - } - - return undefined; -} - -function getCookieFromRequest(req: Request) { - const cookieHeader = req.headers.cookie; - if (cookieHeader) { - const cookies = parseCookie(cookieHeader); - const token = cookies[BACKSTAGE_AUTH_COOKIE]; - if (token) { - return token; - } - } - - return undefined; -} - -function willExpireSoon(expiresAt: Date) { - return Date.now() + FIVE_MINUTES_MS > expiresAt.getTime(); -} - -const credentialsSymbol = Symbol('backstage-credentials'); -const limitedCredentialsSymbol = Symbol('backstage-limited-credentials'); - -type RequestWithCredentials = Request & { - [credentialsSymbol]?: Promise; - [limitedCredentialsSymbol]?: Promise; -}; - -class DefaultHttpAuthService implements HttpAuthService { - readonly #auth: AuthService; - readonly #discovery: DiscoveryService; - readonly #pluginId: string; - - constructor( - auth: AuthService, - discovery: DiscoveryService, - pluginId: string, - ) { - this.#auth = auth; - this.#discovery = discovery; - this.#pluginId = pluginId; - } - - async #extractCredentialsFromRequest(req: Request) { - const token = getTokenFromRequest(req); - if (!token) { - return await this.#auth.getNoneCredentials(); - } - - return await this.#auth.authenticate(token); - } - - async #extractLimitedCredentialsFromRequest(req: Request) { - const token = getTokenFromRequest(req); - if (token) { - return await this.#auth.authenticate(token, { - allowLimitedAccess: true, - }); - } - - const cookie = getCookieFromRequest(req); - if (cookie) { - return await this.#auth.authenticate(cookie, { - allowLimitedAccess: true, - }); - } - - return await this.#auth.getNoneCredentials(); - } - - async #getCredentials(req: RequestWithCredentials) { - return (req[credentialsSymbol] ??= - this.#extractCredentialsFromRequest(req)); - } - - async #getLimitedCredentials(req: RequestWithCredentials) { - return (req[limitedCredentialsSymbol] ??= - this.#extractLimitedCredentialsFromRequest(req)); - } - - async credentials( - req: Request, - options?: { - allow?: Array; - allowLimitedAccess?: boolean; - }, - ): Promise> { - // Limited and full credentials are treated as two separate cases, this lets - // us avoid internal dependencies between the AuthService and - // HttpAuthService implementations - const credentials = options?.allowLimitedAccess - ? await this.#getLimitedCredentials(req) - : await this.#getCredentials(req); - - const allowed = options?.allow; - if (!allowed) { - return credentials as any; - } - - if (this.#auth.isPrincipal(credentials, 'none')) { - if (allowed.includes('none' as TAllowed)) { - return credentials as any; - } - - throw new AuthenticationError('Missing credentials'); - } else if (this.#auth.isPrincipal(credentials, 'user')) { - if (allowed.includes('user' as TAllowed)) { - return credentials as any; - } - - throw new NotAllowedError( - `This endpoint does not allow 'user' credentials`, - ); - } else if (this.#auth.isPrincipal(credentials, 'service')) { - if (allowed.includes('service' as TAllowed)) { - return credentials as any; - } - - throw new NotAllowedError( - `This endpoint does not allow 'service' credentials`, - ); - } - - throw new NotAllowedError( - 'Unknown principal type, this should never happen', - ); - } - - async issueUserCookie( - res: Response, - options?: { credentials?: BackstageCredentials }, - ): Promise<{ expiresAt: Date }> { - if (res.headersSent) { - throw new Error('Failed to issue user cookie, headers were already sent'); - } - - let credentials: BackstageCredentials; - if (options?.credentials) { - if (this.#auth.isPrincipal(options.credentials, 'none')) { - res.clearCookie( - BACKSTAGE_AUTH_COOKIE, - await this.#getCookieOptions(res.req), - ); - return { expiresAt: new Date() }; - } - if (!this.#auth.isPrincipal(options.credentials, 'user')) { - throw new AuthenticationError( - 'Refused to issue cookie for non-user principal', - ); - } - credentials = options.credentials; - } else { - credentials = await this.credentials(res.req, { allow: ['user'] }); - } - - const existingExpiresAt = await this.#existingCookieExpiration(res.req); - if (existingExpiresAt && !willExpireSoon(existingExpiresAt)) { - return { expiresAt: existingExpiresAt }; - } - - const { token, expiresAt } = await this.#auth.getLimitedUserToken( - credentials, - ); - if (!token) { - throw new Error('User credentials is unexpectedly missing token'); - } - - res.cookie(BACKSTAGE_AUTH_COOKIE, token, { - ...(await this.#getCookieOptions(res.req)), - expires: expiresAt, - }); - - return { expiresAt }; - } - - async #getCookieOptions(_req: Request): Promise<{ - domain: string; - httpOnly: true; - secure: boolean; - priority: 'high'; - sameSite: 'none' | 'lax'; - }> { - // TODO: eventually we should read from `${req.protocol}://${req.hostname}` - // once https://github.com/backstage/backstage/issues/24169 has landed - const externalBaseUrlStr = await this.#discovery.getExternalBaseUrl( - this.#pluginId, - ); - const externalBaseUrl = new URL(externalBaseUrlStr); - - const secure = - externalBaseUrl.protocol === 'https:' || - externalBaseUrl.hostname === 'localhost'; - - return { - domain: externalBaseUrl.hostname, - httpOnly: true, - secure, - priority: 'high', - sameSite: secure ? 'none' : 'lax', - }; - } - - async #existingCookieExpiration(req: Request): Promise { - const existingCookie = getCookieFromRequest(req); - if (!existingCookie) { - return undefined; - } - - try { - const existingCredentials = await this.#auth.authenticate( - existingCookie, - { - allowLimitedAccess: true, - }, - ); - if (!this.#auth.isPrincipal(existingCredentials, 'user')) { - return undefined; - } - - return existingCredentials.expiresAt; - } catch (error) { - if (error.name === 'AuthenticationError') { - return undefined; - } - throw error; - } - } -} - -/** @public */ -export const httpAuthServiceFactory = createServiceFactory({ - service: coreServices.httpAuth, - deps: { - auth: coreServices.auth, - discovery: coreServices.discovery, - plugin: coreServices.pluginMetadata, - }, - async factory({ auth, discovery, plugin }) { - return new DefaultHttpAuthService(auth, discovery, plugin.getId()); - }, -}); +/** + * @public + * @deprecated Please import from `@backstage/backend-defaults/httpAuth` instead. + */ +export const httpAuthServiceFactory = _httpAuthServiceFactory; diff --git a/packages/backend-app-api/src/services/implementations/httpRouter/createLifecycleMiddleware.ts b/packages/backend-app-api/src/services/implementations/httpRouter/createLifecycleMiddleware.ts index 3f8ee3ea69..d4864a23a6 100644 --- a/packages/backend-app-api/src/services/implementations/httpRouter/createLifecycleMiddleware.ts +++ b/packages/backend-app-api/src/services/implementations/httpRouter/createLifecycleMiddleware.ts @@ -14,26 +14,18 @@ * limitations under the License. */ -import { LifecycleService } from '@backstage/backend-plugin-api'; -import { ServiceUnavailableError } from '@backstage/errors'; -import { HumanDuration, durationToMilliseconds } from '@backstage/types'; -import { RequestHandler } from 'express'; - -export const DEFAULT_TIMEOUT = { seconds: 5 }; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { + createLifecycleMiddleware as _createLifecycleMiddleware, + type LifecycleMiddlewareOptions as _LifecycleMiddlewareOptions, +} from '../../../../../backend-defaults/src/entrypoints/httpRouter/createLifecycleMiddleware'; /** * Options for {@link createLifecycleMiddleware}. * @public + * @deprecated Please import from `@backstage/backend-defaults/httpRouter` instead. */ -export interface LifecycleMiddlewareOptions { - lifecycle: LifecycleService; - /** - * The maximum time that paused requests will wait for the service to start, before returning an error. - * - * Defaults to 5 seconds. - */ - startupRequestPauseTimeout?: HumanDuration; -} +export type LifecycleMiddlewareOptions = _LifecycleMiddlewareOptions; /** * Creates a middleware that pauses requests until the service has started. @@ -48,59 +40,6 @@ export interface LifecycleMiddlewareOptions { * {@link @backstage/errors#ServiceUnavailableError}. * * @public + * @deprecated Please import from `@backstage/backend-defaults/httpRouter` instead. */ -export function createLifecycleMiddleware( - options: LifecycleMiddlewareOptions, -): RequestHandler { - const { lifecycle, startupRequestPauseTimeout = DEFAULT_TIMEOUT } = options; - - let state: 'init' | 'up' | 'down' = 'init'; - const waiting = new Set<{ - next: (err?: Error) => void; - timeout: NodeJS.Timeout; - }>(); - - lifecycle.addStartupHook(async () => { - if (state === 'init') { - state = 'up'; - for (const item of waiting) { - clearTimeout(item.timeout); - item.next(); - } - waiting.clear(); - } - }); - - lifecycle.addShutdownHook(async () => { - state = 'down'; - - for (const item of waiting) { - clearTimeout(item.timeout); - item.next(new ServiceUnavailableError('Service is shutting down')); - } - waiting.clear(); - }); - - const timeoutMs = durationToMilliseconds(startupRequestPauseTimeout); - - return (_req, _res, next) => { - if (state === 'up') { - next(); - return; - } else if (state === 'down') { - next(new ServiceUnavailableError('Service is shutting down')); - return; - } - - const item = { - next, - timeout: setTimeout(() => { - if (waiting.delete(item)) { - next(new ServiceUnavailableError('Service has not started up yet')); - } - }, timeoutMs), - }; - - waiting.add(item); - }; -} +export const createLifecycleMiddleware = _createLifecycleMiddleware; diff --git a/packages/backend-app-api/src/services/implementations/httpRouter/httpRouterServiceFactory.ts b/packages/backend-app-api/src/services/implementations/httpRouter/httpRouterServiceFactory.ts index 5e3a26252f..9d2b74fb43 100644 --- a/packages/backend-app-api/src/services/implementations/httpRouter/httpRouterServiceFactory.ts +++ b/packages/backend-app-api/src/services/implementations/httpRouter/httpRouterServiceFactory.ts @@ -14,80 +14,26 @@ * limitations under the License. */ -import { Handler } from 'express'; -import PromiseRouter from 'express-promise-router'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports import { - coreServices, - createServiceFactory, - HttpRouterServiceAuthPolicy, -} from '@backstage/backend-plugin-api'; -import { createLifecycleMiddleware } from './createLifecycleMiddleware'; -import { createCredentialsBarrier } from './createCredentialsBarrier'; -import { createAuthIntegrationRouter } from './createAuthIntegrationRouter'; -import { createCookieAuthRefreshMiddleware } from './createCookieAuthRefreshMiddleware'; + httpRouterServiceFactory as _httpRouterServiceFactory, + type HttpRouterFactoryOptions as _HttpRouterFactoryOptions, +} from '../../../../../backend-defaults/src/entrypoints/httpRouter/httpRouterServiceFactory'; /** * @public + * @deprecated Please import from `@backstage/backend-defaults/httpRouter` instead. */ -export interface HttpRouterFactoryOptions { - /** - * A callback used to generate the path for each plugin, defaults to `/api/{pluginId}`. - */ - getPath?(pluginId: string): string; -} +export type HttpRouterFactoryOptions = _HttpRouterFactoryOptions; -/** @public */ -export const httpRouterServiceFactory = createServiceFactory( - (options?: HttpRouterFactoryOptions) => ({ - service: coreServices.httpRouter, - initialization: 'always', - deps: { - plugin: coreServices.pluginMetadata, - config: coreServices.rootConfig, - logger: coreServices.logger, - lifecycle: coreServices.lifecycle, - rootHttpRouter: coreServices.rootHttpRouter, - auth: coreServices.auth, - httpAuth: coreServices.httpAuth, - }, - async factory({ - auth, - httpAuth, - config, - logger, - plugin, - rootHttpRouter, - lifecycle, - }) { - if (options?.getPath) { - logger.warn( - `DEPRECATION WARNING: The 'getPath' option for HttpRouterService is deprecated. The ability to reconfigure the '/api/' path prefix for plugins will be removed in the future.`, - ); - } - const getPath = options?.getPath ?? (id => `/api/${id}`); - const path = getPath(plugin.getId()); - - const router = PromiseRouter(); - rootHttpRouter.use(path, router); - - const credentialsBarrier = createCredentialsBarrier({ - httpAuth, - config, - }); - - router.use(createAuthIntegrationRouter({ auth })); - router.use(createLifecycleMiddleware({ lifecycle })); - router.use(credentialsBarrier.middleware); - router.use(createCookieAuthRefreshMiddleware({ auth, httpAuth })); - - return { - use(handler: Handler): void { - router.use(handler); - }, - addAuthPolicy(policy: HttpRouterServiceAuthPolicy): void { - credentialsBarrier.addAuthPolicy(policy); - }, - }; - }, - }), -); +/** + * HTTP route registration for plugins. + * + * See {@link @backstage/code-plugin-api#HttpRouterService} + * and {@link https://backstage.io/docs/backend-system/core-services/http-router | the service docs} + * for more information. + * + * @public + * @deprecated Please import from `@backstage/backend-defaults/httpRouter` instead. + */ +export const httpRouterServiceFactory = _httpRouterServiceFactory; diff --git a/packages/backend-app-api/src/services/implementations/index.ts b/packages/backend-app-api/src/services/implementations/index.ts index e6656801a9..3a2fe819ed 100644 --- a/packages/backend-app-api/src/services/implementations/index.ts +++ b/packages/backend-app-api/src/services/implementations/index.ts @@ -14,22 +14,15 @@ * limitations under the License. */ -export * from './auth'; export * from './cache'; export * from './config'; export * from './database'; export * from './discovery'; -export * from './httpAuth'; -export * from './httpRouter'; export * from './identity'; export * from './lifecycle'; -export * from './logger'; export * from './permissions'; -export * from './rootHttpRouter'; export * from './rootLifecycle'; -export * from './rootLogger'; export * from './tokenManager'; export * from './urlReader'; -export * from './userInfo'; export * from './deprecated'; diff --git a/packages/backend-app-api/src/services/implementations/logger/loggerServiceFactory.ts b/packages/backend-app-api/src/services/implementations/logger/loggerServiceFactory.ts index d9158529ca..7e7b4b98b0 100644 --- a/packages/backend-app-api/src/services/implementations/logger/loggerServiceFactory.ts +++ b/packages/backend-app-api/src/services/implementations/logger/loggerServiceFactory.ts @@ -14,19 +14,17 @@ * limitations under the License. */ -import { - createServiceFactory, - coreServices, -} from '@backstage/backend-plugin-api'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { loggerServiceFactory as _loggerServiceFactory } from '../../../../../backend-defaults/src/entrypoints/logger/loggerServiceFactory'; -/** @public */ -export const loggerServiceFactory = createServiceFactory({ - service: coreServices.logger, - deps: { - rootLogger: coreServices.rootLogger, - plugin: coreServices.pluginMetadata, - }, - factory({ rootLogger, plugin }) { - return rootLogger.child({ plugin: plugin.getId() }); - }, -}); +/** + * Plugin-level logging. + * + * See {@link @backstage/code-plugin-api#LoggerService} + * and {@link https://backstage.io/docs/backend-system/core-services/logger | the service docs} + * for more information. + * + * @public + * @deprecated Please import from `@backstage/backend-defaults/logger` instead. + */ +export const loggerServiceFactory = _loggerServiceFactory; diff --git a/packages/backend-app-api/src/services/implementations/rootHttpRouter/DefaultRootHttpRouter.ts b/packages/backend-app-api/src/services/implementations/rootHttpRouter/DefaultRootHttpRouter.ts index 9d7d1de120..617d5055db 100644 --- a/packages/backend-app-api/src/services/implementations/rootHttpRouter/DefaultRootHttpRouter.ts +++ b/packages/backend-app-api/src/services/implementations/rootHttpRouter/DefaultRootHttpRouter.ts @@ -15,101 +15,40 @@ */ import { RootHttpRouterService } from '@backstage/backend-plugin-api'; -import { Handler, Router } from 'express'; -import trimEnd from 'lodash/trimEnd'; - -function normalizePath(path: string): string { - return `${trimEnd(path, '/')}/`; -} +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { + DefaultRootHttpRouter as _DefaultRootHttpRouter, + DefaultRootHttpRouterOptions as _DefaultRootHttpRouterOptions, +} from '../../../../../backend-defaults/src/entrypoints/rootHttpRouter/DefaultRootHttpRouter'; +import { Handler } from 'express'; /** * Options for the {@link DefaultRootHttpRouter} class. * * @public + * @deprecated Please import from `@backstage/backend-defaults/rootHttpRouter` instead. */ -export interface DefaultRootHttpRouterOptions { - /** - * The path to forward all unmatched requests to. Defaults to '/api/app' if - * not given. Disables index path behavior if false is given. - */ - indexPath?: string | false; -} +export type DefaultRootHttpRouterOptions = _DefaultRootHttpRouterOptions; /** * The default implementation of the {@link @backstage/backend-plugin-api#RootHttpRouterService} interface for * {@link @backstage/backend-plugin-api#coreServices.rootHttpRouter}. * * @public + * @deprecated Please import from `@backstage/backend-defaults/rootHttpRouter` instead. */ export class DefaultRootHttpRouter implements RootHttpRouterService { - #indexPath?: string; - - #router = Router(); - #namedRoutes = Router(); - #indexRouter = Router(); - #existingPaths = new Array(); - static create(options?: DefaultRootHttpRouterOptions) { - let indexPath; - if (options?.indexPath === false) { - indexPath = undefined; - } else if (options?.indexPath === undefined) { - indexPath = '/api/app'; - } else if (options?.indexPath === '') { - throw new Error('indexPath option may not be an empty string'); - } else { - indexPath = options.indexPath; - } - return new DefaultRootHttpRouter(indexPath); + return new DefaultRootHttpRouter(_DefaultRootHttpRouter.create(options)); } - private constructor(indexPath?: string) { - this.#indexPath = indexPath; - this.#router.use(this.#namedRoutes); - - // Any request with a /api/ prefix will skip the index router, even if no named router matches - this.#router.use('/api/', (_req, _res, next) => { - next('router'); - }); - - if (this.#indexPath) { - this.#router.use(this.#indexRouter); - } - } + private constructor(private readonly impl: RootHttpRouterService) {} use(path: string, handler: Handler) { - if (path.match(/^[/\s]*$/)) { - throw new Error(`Root router path may not be empty`); - } - const conflictingPath = this.#findConflictingPath(path); - if (conflictingPath) { - throw new Error( - `Path ${path} conflicts with the existing path ${conflictingPath}`, - ); - } - this.#existingPaths.push(path); - this.#namedRoutes.use(path, handler); - - if (this.#indexPath === path) { - this.#indexRouter.use(handler); - } + this.impl.use(path, handler); } handler(): Handler { - return this.#router; - } - - #findConflictingPath(newPath: string): string | undefined { - const normalizedNewPath = normalizePath(newPath); - for (const path of this.#existingPaths) { - const normalizedPath = normalizePath(path); - if (normalizedPath.startsWith(normalizedNewPath)) { - return path; - } - if (normalizedNewPath.startsWith(normalizedPath)) { - return path; - } - } - return undefined; + return (this.impl as any).handler(); } } diff --git a/packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterServiceFactory.ts b/packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterServiceFactory.ts index a469a2f303..bef1913645 100644 --- a/packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterServiceFactory.ts +++ b/packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterServiceFactory.ts @@ -14,100 +14,33 @@ * limitations under the License. */ +// eslint-disable-next-line @backstage/no-relative-monorepo-imports import { - RootConfigService, - coreServices, - createServiceFactory, - LifecycleService, - LoggerService, -} from '@backstage/backend-plugin-api'; -import express, { RequestHandler, Express } from 'express'; -import type { Server } from 'node:http'; -import { - createHttpServer, - MiddlewareFactory, - readHttpServerOptions, -} from '../../../http'; -import { DefaultRootHttpRouter } from './DefaultRootHttpRouter'; + rootHttpRouterServiceFactory as _rootHttpRouterServiceFactory, + RootHttpRouterFactoryOptions as _RootHttpRouterFactoryOptions, + RootHttpRouterConfigureContext as _RootHttpRouterConfigureContext, +} from '../../../../../backend-defaults/src/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory'; /** * @public + * @deprecated Please import from `@backstage/backend-defaults/rootHttpRouter` instead. */ -export interface RootHttpRouterConfigureContext { - app: Express; - server: Server; - middleware: MiddlewareFactory; - routes: RequestHandler; - config: RootConfigService; - logger: LoggerService; - lifecycle: LifecycleService; - applyDefaults: () => void; -} +export type RootHttpRouterConfigureContext = _RootHttpRouterConfigureContext; + +/** + * HTTP route registration for root services. + * + * See {@link @backstage/code-plugin-api#RootHttpRouterService} + * and {@link https://backstage.io/docs/backend-system/core-services/root-http-router | the service docs} + * for more information. + * + * @public + * @deprecated Please import from `@backstage/backend-defaults/rootHttpRouter` instead. + */ +export type RootHttpRouterFactoryOptions = _RootHttpRouterFactoryOptions; /** * @public + * @deprecated Please import from `@backstage/backend-defaults/rootHttpRouter` instead. */ -export type RootHttpRouterFactoryOptions = { - /** - * The path to forward all unmatched requests to. Defaults to '/api/app' if - * not given. Disables index path behavior if false is given. - */ - indexPath?: string | false; - - configure?(context: RootHttpRouterConfigureContext): void; -}; - -function defaultConfigure({ applyDefaults }: RootHttpRouterConfigureContext) { - applyDefaults(); -} - -/** @public */ -export const rootHttpRouterServiceFactory = createServiceFactory( - (options?: RootHttpRouterFactoryOptions) => ({ - service: coreServices.rootHttpRouter, - deps: { - config: coreServices.rootConfig, - rootLogger: coreServices.rootLogger, - lifecycle: coreServices.rootLifecycle, - }, - async factory({ config, rootLogger, lifecycle }) { - const { indexPath, configure = defaultConfigure } = options ?? {}; - const logger = rootLogger.child({ service: 'rootHttpRouter' }); - const app = express(); - - const router = DefaultRootHttpRouter.create({ indexPath }); - const middleware = MiddlewareFactory.create({ config, logger }); - const routes = router.handler(); - const server = await createHttpServer( - app, - readHttpServerOptions(config.getOptionalConfig('backend')), - { logger }, - ); - - configure({ - app, - server, - routes, - middleware, - config, - logger, - lifecycle, - applyDefaults() { - app.use(middleware.helmet()); - app.use(middleware.cors()); - app.use(middleware.compression()); - app.use(middleware.logging()); - app.use(routes); - app.use(middleware.notFound()); - app.use(middleware.error()); - }, - }); - - lifecycle.addShutdownHook(() => server.stop()); - - await server.start(); - - return router; - }, - }), -); +export const rootHttpRouterServiceFactory = _rootHttpRouterServiceFactory; diff --git a/packages/backend-app-api/src/services/implementations/rootLogger/rootLoggerServiceFactory.ts b/packages/backend-app-api/src/services/implementations/rootLogger/rootLoggerServiceFactory.ts index bd45df383f..af1931c438 100644 --- a/packages/backend-app-api/src/services/implementations/rootLogger/rootLoggerServiceFactory.ts +++ b/packages/backend-app-api/src/services/implementations/rootLogger/rootLoggerServiceFactory.ts @@ -14,37 +14,17 @@ * limitations under the License. */ -import { - createServiceFactory, - coreServices, -} from '@backstage/backend-plugin-api'; -import { WinstonLogger } from '../../../logging'; -import { transports, format } from 'winston'; -import { createConfigSecretEnumerator } from '../../../config'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { rootLoggerServiceFactory as _rootLoggerServiceFactory } from '../../../../../backend-defaults/src/entrypoints/rootLogger/rootLoggerServiceFactory'; -/** @public */ -export const rootLoggerServiceFactory = createServiceFactory({ - service: coreServices.rootLogger, - deps: { - config: coreServices.rootConfig, - }, - async factory({ config }) { - const logger = WinstonLogger.create({ - meta: { - service: 'backstage', - }, - level: process.env.LOG_LEVEL || 'info', - format: - process.env.NODE_ENV === 'production' - ? format.json() - : WinstonLogger.colorFormat(), - transports: [new transports.Console()], - }); - - const secretEnumerator = await createConfigSecretEnumerator({ logger }); - logger.addRedactions(secretEnumerator(config)); - config.subscribe?.(() => logger.addRedactions(secretEnumerator(config))); - - return logger; - }, -}); +/** + * Root-level logging. + * + * See {@link @backstage/code-plugin-api#RootLoggerService} + * and {@link https://backstage.io/docs/backend-system/core-services/root-logger | the service docs} + * for more information. + * + * @public + * @deprecated Please import from `@backstage/backend-defaults/rootLogger` instead. + */ +export const rootLoggerServiceFactory = _rootLoggerServiceFactory; diff --git a/packages/backend-app-api/src/services/implementations/userInfo/userInfoServiceFactory.ts b/packages/backend-app-api/src/services/implementations/userInfo/userInfoServiceFactory.ts index e88acaf4c2..746f480c41 100644 --- a/packages/backend-app-api/src/services/implementations/userInfo/userInfoServiceFactory.ts +++ b/packages/backend-app-api/src/services/implementations/userInfo/userInfoServiceFactory.ts @@ -14,51 +14,11 @@ * limitations under the License. */ -import { - UserInfoService, - BackstageUserInfo, - coreServices, - createServiceFactory, - BackstageCredentials, -} from '@backstage/backend-plugin-api'; -import { decodeJwt } from 'jose'; -import { toInternalBackstageCredentials } from '../auth/helpers'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { userInfoServiceFactory as _userInfoServiceFactory } from '../../../../../backend-defaults/src/entrypoints/userInfo'; -// TODO: The intention is for this to eventually be replaced by a call to the auth-backend -export class DefaultUserInfoService implements UserInfoService { - async getUserInfo( - credentials: BackstageCredentials, - ): Promise { - const internalCredentials = toInternalBackstageCredentials(credentials); - if (internalCredentials.principal.type !== 'user') { - throw new Error('Only user credentials are supported'); - } - if (!internalCredentials.token) { - throw new Error('User credentials is unexpectedly missing token'); - } - const { sub: userEntityRef, ent: ownershipEntityRefs = [] } = decodeJwt( - internalCredentials.token, - ); - - if (typeof userEntityRef !== 'string') { - throw new Error('User entity ref must be a string'); - } - if ( - !Array.isArray(ownershipEntityRefs) || - ownershipEntityRefs.some(ref => typeof ref !== 'string') - ) { - throw new Error('Ownership entity refs must be an array of strings'); - } - - return { userEntityRef, ownershipEntityRefs }; - } -} - -/** @public */ -export const userInfoServiceFactory = createServiceFactory({ - service: coreServices.userInfo, - deps: {}, - async factory() { - return new DefaultUserInfoService(); - }, -}); +/** + * @public + * @deprecated Please import from `@backstage/backend-defaults/userInfo` instead. + */ +export const userInfoServiceFactory = _userInfoServiceFactory; diff --git a/packages/backend-app-api/src/wiring/BackendInitializer.test.ts b/packages/backend-app-api/src/wiring/BackendInitializer.test.ts index b60eede277..3bbef5a4c0 100644 --- a/packages/backend-app-api/src/wiring/BackendInitializer.test.ts +++ b/packages/backend-app-api/src/wiring/BackendInitializer.test.ts @@ -14,6 +14,9 @@ * limitations under the License. */ +import { rootLifecycleServiceFactory } from '@backstage/backend-defaults/rootLifecycle'; +import { lifecycleServiceFactory } from '@backstage/backend-defaults/lifecycle'; +import { loggerServiceFactory } from '@backstage/backend-defaults/logger'; import { createServiceRef, createServiceFactory, @@ -24,12 +27,6 @@ import { } from '@backstage/backend-plugin-api'; import { BackendInitializer } from './BackendInitializer'; -import { - lifecycleServiceFactory, - loggerServiceFactory, - rootLifecycleServiceFactory, -} from '../services/implementations'; - class MockLogger { debug() {} info() {} @@ -153,7 +150,7 @@ describe('BackendInitializer', () => { async init() {}, }); }, - })(), + }), ); await init.start(); @@ -184,7 +181,7 @@ describe('BackendInitializer', () => { }, }); }, - })(), + }), ); init.add( @@ -201,7 +198,7 @@ describe('BackendInitializer', () => { }, }); }, - })(), + }), ); init.add( @@ -217,7 +214,7 @@ describe('BackendInitializer', () => { }, }); }, - })(), + }), ); await init.start(); }); @@ -235,7 +232,7 @@ describe('BackendInitializer', () => { }, }); }, - })(), + }), ); await expect(init.start()).rejects.toThrow( "Plugin 'test' startup failed; caused by Error: NOPE", @@ -257,7 +254,7 @@ describe('BackendInitializer', () => { }, }); }, - })(), + }), ); await expect(init.start()).rejects.toThrow( "Module 'mod' for plugin 'test' startup failed; caused by Error: NOPE", @@ -275,7 +272,7 @@ describe('BackendInitializer', () => { async init() {}, }); }, - })(), + }), ); init.add( createBackendPlugin({ @@ -286,7 +283,7 @@ describe('BackendInitializer', () => { async init() {}, }); }, - })(), + }), ); await expect(init.start()).rejects.toThrow( "Plugin 'test' is already registered", @@ -306,7 +303,7 @@ describe('BackendInitializer', () => { async init() {}, }); }, - })(), + }), ); init.add( createBackendModule({ @@ -318,7 +315,7 @@ describe('BackendInitializer', () => { async init() {}, }); }, - })(), + }), ); await expect(init.start()).rejects.toThrow( "Module 'mod' for plugin 'test' is already registered", @@ -348,7 +345,7 @@ describe('BackendInitializer', () => { async init() {}, }); }, - })(), + }), ); init.add( createBackendModule({ @@ -361,7 +358,7 @@ describe('BackendInitializer', () => { async init() {}, }); }, - })(), + }), ); await expect(init.start()).rejects.toThrow( "Circular dependency detected for modules of plugin 'test', 'mod-a' -> 'mod-b' -> 'mod-a'", @@ -381,7 +378,7 @@ describe('BackendInitializer', () => { async init() {}, }); }, - })(), + }), ); init.add(testPlugin); init.add( @@ -394,7 +391,7 @@ describe('BackendInitializer', () => { async init() {}, }); }, - })(), + }), ); await expect(init.start()).rejects.toThrow( "Illegal dependency: Module 'mod' for plugin 'test' attempted to depend on extension point 'a' for plugin 'test-a'. Extension points can only be used within their plugin's scope.", diff --git a/packages/backend-app-api/src/wiring/BackstageBackend.ts b/packages/backend-app-api/src/wiring/BackstageBackend.ts index d523481cf7..0dd3ba4423 100644 --- a/packages/backend-app-api/src/wiring/BackstageBackend.ts +++ b/packages/backend-app-api/src/wiring/BackstageBackend.ts @@ -65,9 +65,11 @@ function unwrapFeature( if (typeof feature === 'function') { return feature(); } + if ('$$type' in feature) { return feature; } + // This is a workaround where default exports get transpiled to `exports['default'] = ...` // in CommonJS modules, which in turn results in a double `{ default: { default: ... } }` nesting // when importing using a dynamic import. @@ -78,5 +80,6 @@ function unwrapFeature( ? defaultFeature() : defaultFeature; } + return feature; } diff --git a/packages/backend-common/CHANGELOG.md b/packages/backend-common/CHANGELOG.md index ecf56c5f28..d635b77c72 100644 --- a/packages/backend-common/CHANGELOG.md +++ b/packages/backend-common/CHANGELOG.md @@ -1,5 +1,83 @@ # @backstage/backend-common +## 0.23.2-next.0 + +### Patch Changes + +- 8c09c97: Deprecate legacy status check factory, handler and types. +- d228862: Update default backend plugin created by the cli to use non-deprecated error handling middleware +- c964a3d: Add dependencies that are needed by cross-imports from backend-defaults +- b60db08: Fixing exporting of classes properly from new packages +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/backend-dev-utils@0.1.4 + - @backstage/cli-common@0.1.14 + - @backstage/config@1.2.0 + - @backstage/config-loader@1.8.1 + - @backstage/errors@1.2.4 + - @backstage/integration-aws-node@0.1.12 + - @backstage/types@1.1.1 + +## 0.23.0 + +### Minor Changes + +- 395b973: Implemented `readTree` for Harness provider to support TechDocs functionality +- 02103be: Deprecated and moved over core services to `@backstage/backend-defaults` + +### Patch Changes + +- 9539a0b: Import utility functions from `backend-defaults` instead of `backend-app-api` +- b2c4607: Removed accents on deprecation note +- c6c0919: Updated configuration schema to include the `useRedisSets` cache config option. +- ed3074e: The `database` types, helpers and implementations were moved to the package `@backstage/backend-defaults` and deprecated from the package `@backstage/backend-commons`. +- 9cca724: The `TokenManager` has been deprecated in preparation for the [stable release of the New Backend System](https://github.com/backstage/backstage/issues/24493). Please [migrate](https://backstage.io/docs/tutorials/auth-service-migration) to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead. +- 1779188: In preparation to the new backend system stable release, the `isDatabaseConflictError` helper have been moved to the `@backstage/backend-plugin-api` package and deprecated from `@backstage/backend-common`. +- 78a0b08: Internal refactor to handle `BackendFeature` contract change. +- e171620: Move `cache` implementation and types to the `@backstage/backend-defaults` package. +- 1a6f38a: `ContainerRunner`, `DockerContainerRunner` and `KubernetesContainerRunner` are now deprecated +- 8869b8e: We are deprecating the legacy `createServiceBuilder` factory, so if you are still using it, please checkout the migration guide and [migrate](https://backstage.io/docs/backend-system/building-plugins-and-modules/migrating) your plugin to use the new backend system. +- 0634fdc: Deprecated `dropDatabase` +- b2ee7f3: Moved over all URL reader functionality from `@backstage/backend-common` to `@backstage/backend-defaults/urlReader`. Please update your imports. +- d94a477: Removed the circular dependency on `@backstage/backend-app-api` +- 3bd04bb: We are deprecating the legacy router handlers and contexts in preparation for the new backend system stable release. +- 23ee9ab: Fix AWS CodeCommit integration by allowing to change the host +- e9a03c9: Finalizes the deprecation of legacy backend utilities. Deprecated utilities include the `ServiceBuilder` type, `notFoundHandler` and `redactWintonLogLine` functions. +- 6a576dc: Deprecate legacy service logger helpers and stop using `getVoidLogger` in tests. +- 032a7a6: Deprecate the legacy error and request logging handler types, respectively: `ErrorHandlerOptions` and `RequestLoggingHandlerFactory`. +- Updated dependencies + - @backstage/backend-plugin-api@0.6.19 + - @backstage/plugin-auth-node@0.4.14 + - @backstage/integration@1.12.0 + - @backstage/cli-common@0.1.14 + - @backstage/config-loader@1.8.1 + - @backstage/backend-dev-utils@0.1.4 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/integration-aws-node@0.1.12 + - @backstage/types@1.1.1 + +## 0.23.0-next.3 + +### Patch Changes + +- b2ee7f3: Moved over all URL reader functionality from `@backstage/backend-common` to `@backstage/backend-defaults/urlReader`. Please update your imports. +- 23ee9ab: Fix AWS CodeCommit integration by allowing to change the host +- Updated dependencies + - @backstage/backend-plugin-api@0.6.19-next.3 + - @backstage/plugin-auth-node@0.4.14-next.3 + - @backstage/integration@1.12.0-next.1 + - @backstage/cli-common@0.1.14-next.0 + - @backstage/backend-app-api@0.7.6-next.3 + - @backstage/config-loader@1.8.1-next.0 + - @backstage/backend-dev-utils@0.1.4 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/integration-aws-node@0.1.12 + - @backstage/types@1.1.1 + ## 0.23.0-next.2 ### Minor Changes diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md index 977809071b..52b661bcaf 100644 --- a/packages/backend-common/api-report.md +++ b/packages/backend-common/api-report.md @@ -13,15 +13,16 @@ import { AwsCredentialsManager } from '@backstage/integration-aws-node'; import { AwsS3Integration } from '@backstage/integration'; import { AzureDevOpsCredentialsProvider } from '@backstage/integration'; import { AzureIntegration } from '@backstage/integration'; -import { BackendFeature } from '@backstage/backend-plugin-api'; +import { BackendFeatureCompat } from '@backstage/backend-plugin-api'; import { BitbucketCloudIntegration } from '@backstage/integration'; import { BitbucketIntegration } from '@backstage/integration'; import { BitbucketServerIntegration } from '@backstage/integration'; import { CacheService } from '@backstage/backend-plugin-api'; import { CacheServiceOptions } from '@backstage/backend-plugin-api'; -import type { CacheServiceSetOptions } from '@backstage/backend-plugin-api'; +import { CacheServiceSetOptions } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import cors from 'cors'; +import { DatabaseService } from '@backstage/backend-plugin-api'; import { DiscoveryService } from '@backstage/backend-plugin-api'; import Docker from 'dockerode'; import { ErrorRequestHandler } from 'express'; @@ -32,7 +33,6 @@ import { GithubCredentialsProvider } from '@backstage/integration'; import { GithubIntegration } from '@backstage/integration'; import { GitLabIntegration } from '@backstage/integration'; import { HarnessIntegration } from '@backstage/integration'; -import { HostDiscovery as HostDiscovery_2 } from '@backstage/backend-app-api'; import { HttpAuthService } from '@backstage/backend-plugin-api'; import { IdentityService } from '@backstage/backend-plugin-api'; import { isChildPath as isChildPath_2 } from '@backstage/backend-plugin-api'; @@ -44,37 +44,36 @@ import { Logger } from 'winston'; import { LoggerService } from '@backstage/backend-plugin-api'; import { MergeResult } from 'isomorphic-git'; import { PermissionsService } from '@backstage/backend-plugin-api'; -import { DatabaseService as PluginDatabaseManager } from '@backstage/backend-plugin-api'; import { PluginMetadataService } from '@backstage/backend-plugin-api'; import { PushResult } from 'isomorphic-git'; import { Readable } from 'stream'; import { ReadCommitResult } from 'isomorphic-git'; -import type { ReadTreeOptions as ReadTreeOptions_2 } from '@backstage/backend-plugin-api'; -import type { ReadTreeResponse as ReadTreeResponse_2 } from '@backstage/backend-plugin-api'; -import type { ReadTreeResponseDirOptions as ReadTreeResponseDirOptions_2 } from '@backstage/backend-plugin-api'; -import type { ReadTreeResponseFile as ReadTreeResponseFile_2 } from '@backstage/backend-plugin-api'; -import type { ReadUrlOptions as ReadUrlOptions_2 } from '@backstage/backend-plugin-api'; -import type { ReadUrlResponse as ReadUrlResponse_2 } from '@backstage/backend-plugin-api'; +import { ReadTreeOptions as ReadTreeOptions_2 } from '@backstage/backend-plugin-api'; +import { ReadTreeResponse as ReadTreeResponse_2 } from '@backstage/backend-plugin-api'; +import { ReadTreeResponseDirOptions as ReadTreeResponseDirOptions_2 } from '@backstage/backend-plugin-api'; +import { ReadTreeResponseFile as ReadTreeResponseFile_2 } from '@backstage/backend-plugin-api'; +import { ReadUrlOptions as ReadUrlOptions_2 } from '@backstage/backend-plugin-api'; +import { ReadUrlResponse as ReadUrlResponse_2 } from '@backstage/backend-plugin-api'; import { RequestHandler } from 'express'; import { resolvePackagePath as resolvePackagePath_2 } from '@backstage/backend-plugin-api'; import { resolveSafeChildPath as resolveSafeChildPath_2 } from '@backstage/backend-plugin-api'; import { RootConfigService } from '@backstage/backend-plugin-api'; import { Router } from 'express'; import { SchedulerService } from '@backstage/backend-plugin-api'; -import type { SearchOptions as SearchOptions_2 } from '@backstage/backend-plugin-api'; -import type { SearchResponse as SearchResponse_2 } from '@backstage/backend-plugin-api'; -import type { SearchResponseFile as SearchResponseFile_2 } from '@backstage/backend-plugin-api'; +import { SearchOptions as SearchOptions_2 } from '@backstage/backend-plugin-api'; +import { SearchResponse as SearchResponse_2 } from '@backstage/backend-plugin-api'; +import { SearchResponseFile as SearchResponseFile_2 } from '@backstage/backend-plugin-api'; import { Server } from 'http'; import { ServiceRef } from '@backstage/backend-plugin-api'; -import { TokenManagerService as TokenManager } from '@backstage/backend-plugin-api'; +import { TokenManagerService } from '@backstage/backend-plugin-api'; import { TransportStreamOptions } from 'winston-transport'; -import { UrlReaderReadTreeOptions } from '@backstage/backend-plugin-api'; -import { UrlReaderReadTreeResponse } from '@backstage/backend-plugin-api'; -import { UrlReaderReadUrlOptions } from '@backstage/backend-plugin-api'; -import { UrlReaderReadUrlResponse } from '@backstage/backend-plugin-api'; -import { UrlReaderSearchOptions } from '@backstage/backend-plugin-api'; -import { UrlReaderSearchResponse } from '@backstage/backend-plugin-api'; import { UrlReaderService } from '@backstage/backend-plugin-api'; +import { UrlReaderServiceReadTreeOptions } from '@backstage/backend-plugin-api'; +import { UrlReaderServiceReadTreeResponse } from '@backstage/backend-plugin-api'; +import { UrlReaderServiceReadUrlOptions } from '@backstage/backend-plugin-api'; +import { UrlReaderServiceReadUrlResponse } from '@backstage/backend-plugin-api'; +import { UrlReaderServiceSearchOptions } from '@backstage/backend-plugin-api'; +import { UrlReaderServiceSearchResponse } from '@backstage/backend-plugin-api'; import { UserInfoService } from '@backstage/backend-plugin-api'; import { V1PodTemplateSpec } from '@kubernetes/client-node'; import * as winston from 'winston'; @@ -89,27 +88,27 @@ export type AuthCallbackOptions = { // Warning: (ae-forgotten-export) The symbol "AwsS3UrlReader_2" needs to be exported by the entry point index.d.ts // // @public @deprecated (undocumented) -export const AwsS3UrlReader: typeof AwsS3UrlReader_2; +export class AwsS3UrlReader extends AwsS3UrlReader_2 {} // Warning: (ae-forgotten-export) The symbol "AzureUrlReader_2" needs to be exported by the entry point index.d.ts // // @public @deprecated (undocumented) -export const AzureUrlReader: typeof AzureUrlReader_2; +export class AzureUrlReader extends AzureUrlReader_2 {} // Warning: (ae-forgotten-export) The symbol "BitbucketCloudUrlReader_2" needs to be exported by the entry point index.d.ts // // @public @deprecated (undocumented) -export const BitbucketCloudUrlReader: typeof BitbucketCloudUrlReader_2; +export class BitbucketCloudUrlReader extends BitbucketCloudUrlReader_2 {} // Warning: (ae-forgotten-export) The symbol "BitbucketServerUrlReader_2" needs to be exported by the entry point index.d.ts // // @public @deprecated (undocumented) -export const BitbucketServerUrlReader: typeof BitbucketServerUrlReader_2; +export class BitbucketServerUrlReader extends BitbucketServerUrlReader_2 {} // Warning: (ae-forgotten-export) The symbol "BitbucketUrlReader_2" needs to be exported by the entry point index.d.ts // // @public @deprecated (undocumented) -export const BitbucketUrlReader: typeof BitbucketUrlReader_2; +export class BitbucketUrlReader extends BitbucketUrlReader_2 {} // @public @deprecated (undocumented) export type CacheClient = CacheService; @@ -120,25 +119,15 @@ export type CacheClientOptions = CacheServiceOptions; // @public @deprecated (undocumented) export type CacheClientSetOptions = CacheServiceSetOptions; -// @public -export class CacheManager { - forPlugin(pluginId: string): { - getClient(options?: CacheServiceOptions): CacheService; - }; - static fromConfig( - config: Config, - options?: { - logger?: LoggerService; - onError?: (err: Error) => void; - }, - ): CacheManager; -} +// Warning: (ae-forgotten-export) The symbol "CacheManager_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export class CacheManager extends CacheManager_2 {} -// @public -export type CacheManagerOptions = { - logger?: LoggerService; - onError?: (err: Error) => void; -}; +// Warning: (ae-forgotten-export) The symbol "CacheManagerOptions_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export type CacheManagerOptions = CacheManagerOptions_2; // @public export function cacheToPluginCacheManager(cache: CacheService): { @@ -148,7 +137,7 @@ export function cacheToPluginCacheManager(cache: CacheService): { // @public @deprecated export const coloredFormat: winston.Logform.Format; -// @public +// @public @deprecated export interface ContainerRunner { runContainer(opts: RunContainerOptions): Promise; } @@ -195,53 +184,55 @@ export function createRootLogger( // @public @deprecated export function createServiceBuilder(_module: NodeModule): ServiceBuilder; -// @public +// @public @deprecated export function createStatusCheckRouter(options: { logger: LoggerService; path?: string; statusCheck?: StatusCheck; }): Promise; -// @public +// @public @deprecated (undocumented) export class DatabaseManager implements LegacyRootDatabaseService { + // (undocumented) forPlugin( pluginId: string, - deps?: { - lifecycle: LifecycleService; - pluginMetadata: PluginMetadataService; - }, + deps?: + | { + lifecycle: LifecycleService; + pluginMetadata: PluginMetadataService; + } + | undefined, ): PluginDatabaseManager; + // (undocumented) static fromConfig( config: Config, options?: DatabaseManagerOptions, ): DatabaseManager; } -// @public -export type DatabaseManagerOptions = { - migrations?: PluginDatabaseManager['migrations']; - logger?: LoggerService; -}; +// Warning: (ae-forgotten-export) The symbol "DatabaseManagerOptions_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export type DatabaseManagerOptions = DatabaseManagerOptions_2; -// @public +// @public @deprecated export class DockerContainerRunner implements ContainerRunner { constructor(options: { dockerClient: Docker }); // (undocumented) runContainer(options: RunContainerOptions): Promise; } -// @public @deprecated -export function dropDatabase( - dbConfig: Config, - ...databaseNames: string[] -): Promise; +// Warning: (ae-forgotten-export) The symbol "dropDatabase_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export const dropDatabase: typeof dropDatabase_2; // @public @deprecated export function errorHandler( options?: ErrorHandlerOptions, ): ErrorRequestHandler; -// @public +// @public @deprecated export type ErrorHandlerOptions = { showStackTraces?: boolean; logger?: LoggerService; @@ -251,7 +242,7 @@ export type ErrorHandlerOptions = { // Warning: (ae-forgotten-export) The symbol "FetchUrlReader_2" needs to be exported by the entry point index.d.ts // // @public @deprecated (undocumented) -export const FetchUrlReader: typeof FetchUrlReader_2; +export class FetchUrlReader extends FetchUrlReader_2 {} // Warning: (ae-forgotten-export) The symbol "FromReadableArrayOptions_2" needs to be exported by the entry point index.d.ts // @@ -261,7 +252,7 @@ export type FromReadableArrayOptions = FromReadableArrayOptions_2; // Warning: (ae-forgotten-export) The symbol "GerritUrlReader_2" needs to be exported by the entry point index.d.ts // // @public @deprecated (undocumented) -export const GerritUrlReader: typeof GerritUrlReader_2; +export class GerritUrlReader extends GerritUrlReader_2 {} // @public @deprecated export function getRootLogger(): winston.Logger; @@ -348,25 +339,38 @@ export class Git { // Warning: (ae-forgotten-export) The symbol "GiteaUrlReader_2" needs to be exported by the entry point index.d.ts // // @public @deprecated (undocumented) -export const GiteaUrlReader: typeof GiteaUrlReader_2; +export class GiteaUrlReader extends GiteaUrlReader_2 {} // Warning: (ae-forgotten-export) The symbol "GithubUrlReader_2" needs to be exported by the entry point index.d.ts // // @public @deprecated (undocumented) -export const GithubUrlReader: typeof GithubUrlReader_2; +export class GithubUrlReader extends GithubUrlReader_2 {} // Warning: (ae-forgotten-export) The symbol "GitlabUrlReader_2" needs to be exported by the entry point index.d.ts // // @public @deprecated (undocumented) -export const GitlabUrlReader: typeof GitlabUrlReader_2; +export class GitlabUrlReader extends GitlabUrlReader_2 {} // Warning: (ae-forgotten-export) The symbol "HarnessUrlReader_2" needs to be exported by the entry point index.d.ts // // @public @deprecated (undocumented) -export const HarnessUrlReader: typeof HarnessUrlReader_2; +export class HarnessUrlReader extends HarnessUrlReader_2 {} // @public @deprecated -export const HostDiscovery: typeof HostDiscovery_2; +class HostDiscovery implements DiscoveryService { + static fromConfig( + config: Config, + options?: { + basePath?: string; + }, + ): HostDiscovery; + // (undocumented) + getBaseUrl(pluginId: string): Promise; + // (undocumented) + getExternalBaseUrl(pluginId: string): Promise; +} +export { HostDiscovery }; +export { HostDiscovery as SingleHostDiscovery }; // @public @deprecated (undocumented) export const isChildPath: typeof isChildPath_2; @@ -374,20 +378,20 @@ export const isChildPath: typeof isChildPath_2; // @public @deprecated (undocumented) export const isDatabaseConflictError: typeof isDatabaseConflictError_2; -// @public +// @public @deprecated export class KubernetesContainerRunner implements ContainerRunner { constructor(options: KubernetesContainerRunnerOptions); // (undocumented) runContainer(options: RunContainerOptions): Promise; } -// @public +// @public @deprecated export type KubernetesContainerRunnerMountBase = { volumeName: string; basePath: string; }; -// @public +// @public @deprecated export type KubernetesContainerRunnerOptions = { kubeConfig: KubeConfig; name: string; @@ -409,12 +413,12 @@ export const legacyPlugin: ( { cache: CacheService; config: RootConfigService; - database: PluginDatabaseManager; + database: DatabaseService; discovery: DiscoveryService; logger: LoggerService; permissions: PermissionsService; scheduler: SchedulerService; - tokenManager: TokenManager; + tokenManager: TokenManagerService; reader: UrlReaderService; identity: IdentityService; }, @@ -427,12 +431,12 @@ export const legacyPlugin: ( > >; }>, -) => BackendFeature; +) => BackendFeatureCompat; -// @public -export type LegacyRootDatabaseService = { - forPlugin(pluginId: string): PluginDatabaseManager; -}; +// Warning: (ae-forgotten-export) The symbol "LegacyRootDatabaseService_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export type LegacyRootDatabaseService = LegacyRootDatabaseService_2; // @public @deprecated export function loadBackendConfig(options: { @@ -465,23 +469,23 @@ export function makeLegacyPlugin< createRouterImport: Promise<{ default: LegacyCreateRouter>; }>, -) => BackendFeature; +) => BackendFeatureCompat; -// @public +// @public @deprecated export function notFoundHandler(): RequestHandler; -// @public (undocumented) -export interface PluginCacheManager { - // (undocumented) - getClient(options?: CacheServiceOptions): CacheService; -} +// Warning: (ae-forgotten-export) The symbol "PluginCacheManager_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export type PluginCacheManager = PluginCacheManager_2; -export { PluginDatabaseManager }; +// @public @deprecated (undocumented) +export type PluginDatabaseManager = DatabaseService; // @public @deprecated (undocumented) export type PluginEndpointDiscovery = DiscoveryService; -// @public +// @public @deprecated export interface PullOptions { // (undocumented) [key: string]: unknown; @@ -532,7 +536,7 @@ export type ReadUrlResponse = ReadUrlResponse_2; // Warning: (ae-forgotten-export) The symbol "ReadUrlResponseFactory_2" needs to be exported by the entry point index.d.ts // // @public @deprecated (undocumented) -export const ReadUrlResponseFactory: typeof ReadUrlResponseFactory_2; +export class ReadUrlResponseFactory extends ReadUrlResponseFactory_2 {} // Warning: (ae-forgotten-export) The symbol "ReadUrlResponseFactoryFromStreamOptions_2" needs to be exported by the entry point index.d.ts // @@ -540,7 +544,7 @@ export const ReadUrlResponseFactory: typeof ReadUrlResponseFactory_2; export type ReadUrlResponseFactoryFromStreamOptions = ReadUrlResponseFactoryFromStreamOptions_2; -// @public +// @public @deprecated export function redactWinstonLogLine( info: winston.Logform.TransformableInfo, ): winston.Logform.TransformableInfo; @@ -548,7 +552,7 @@ export function redactWinstonLogLine( // @public @deprecated export function requestLoggingHandler(logger?: LoggerService): RequestHandler; -// @public +// @public @deprecated export type RequestLoggingHandlerFactory = ( logger?: LoggerService, ) => RequestHandler; @@ -559,7 +563,7 @@ export const resolvePackagePath: typeof resolvePackagePath_2; // @public @deprecated (undocumented) export const resolveSafeChildPath: typeof resolveSafeChildPath_2; -// @public +// @public @deprecated export type RunContainerOptions = { imageName: string; command?: string | string[]; @@ -582,7 +586,7 @@ export type SearchResponse = SearchResponse_2; // @public @deprecated (undocumented) export type SearchResponseFile = SearchResponseFile_2; -// @public +// @public @deprecated export class ServerTokenManager implements TokenManager { // (undocumented) authenticate(token: string): Promise; @@ -598,13 +602,13 @@ export class ServerTokenManager implements TokenManager { static noop(): TokenManager; } -// @public +// @public @deprecated export interface ServerTokenManagerOptions { allowDisabledTokenManager?: boolean; logger: LoggerService; } -// @public +// @public @deprecated export type ServiceBuilder = { loadConfig(config: Config): ServiceBuilder; setPort(port: number): ServiceBuilder; @@ -633,9 +637,6 @@ export type ServiceBuilder = { // @public @deprecated export function setRootLogger(newLogger: winston.Logger): void; -// @public @deprecated -export const SingleHostDiscovery: typeof HostDiscovery_2; - // @public @deprecated export type StaticAuthOptions = { username?: string; @@ -644,20 +645,21 @@ export type StaticAuthOptions = { logger?: LoggerService; }; -// @public +// @public @deprecated export type StatusCheck = () => Promise; -// @public +// @public @deprecated export function statusCheckHandler( options?: StatusCheckHandlerOptions, ): Promise; -// @public +// @public @deprecated export interface StatusCheckHandlerOptions { statusCheck?: StatusCheck; } -export { TokenManager }; +// @public @deprecated (undocumented) +export type TokenManager = TokenManagerService; // @public @deprecated (undocumented) export type UrlReader = UrlReaderService; @@ -670,7 +672,7 @@ export type UrlReaderPredicateTuple = UrlReaderPredicateTuple_2; // Warning: (ae-forgotten-export) The symbol "UrlReaders_2" needs to be exported by the entry point index.d.ts // // @public @deprecated (undocumented) -export const UrlReaders: typeof UrlReaders_2; +export class UrlReaders extends UrlReaders_2 {} // Warning: (ae-forgotten-export) The symbol "UrlReadersOptions_2" needs to be exported by the entry point index.d.ts // diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index e5b5806ddf..7944477c88 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/backend-common", - "version": "0.23.0-next.2", + "version": "0.23.2-next.0", "description": "Common functionality library for Backstage backends", "backstage": { "role": "node-library" @@ -59,7 +59,6 @@ "@aws-sdk/client-s3": "^3.350.0", "@aws-sdk/credential-providers": "^3.350.0", "@aws-sdk/types": "^3.347.0", - "@backstage/backend-app-api": "workspace:^", "@backstage/backend-dev-utils": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", "@backstage/cli-common": "workspace:^", @@ -100,12 +99,19 @@ "logform": "^2.3.2", "luxon": "^3.0.0", "minimatch": "^9.0.0", + "minimist": "^1.2.5", + "morgan": "^1.10.0", "mysql2": "^3.0.0", "node-fetch": "^2.6.7", + "node-forge": "^1.3.1", "p-limit": "^3.1.0", + "path-to-regexp": "^6.2.1", "pg": "^8.11.3", "raw-body": "^2.4.1", + "selfsigned": "^2.0.0", + "stoppable": "^1.1.0", "tar": "^6.1.12", + "triple-beam": "^1.4.1", "uuid": "^9.0.0", "winston": "^3.2.1", "winston-transport": "^4.5.0", @@ -122,7 +128,10 @@ "@types/concat-stream": "^2.0.0", "@types/fs-extra": "^11.0.0", "@types/http-errors": "^2.0.0", + "@types/morgan": "^1.9.0", + "@types/node-forge": "^1.3.0", "@types/pg": "^8.6.6", + "@types/stoppable": "^1.1.0", "@types/supertest": "^2.0.8", "@types/tar": "^6.1.1", "@types/webpack-env": "^1.15.2", diff --git a/packages/backend-common/src/alpha.ts b/packages/backend-common/src/alpha.ts index e0a5b2ddc2..0fd15459fe 100644 --- a/packages/backend-common/src/alpha.ts +++ b/packages/backend-common/src/alpha.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export * from './context'; +export * from './deprecated/context'; diff --git a/packages/backend-common/src/cache/reexport.ts b/packages/backend-common/src/cache/reexport.ts deleted file mode 100644 index 9f6106de60..0000000000 --- a/packages/backend-common/src/cache/reexport.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2024 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * NOTE(freben): This is a temporary hack. We use cross-package imports so that - * we do not have to maintain double implementations for the time being, until - * backend-common is properly removed. - */ - -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -export { CacheManager } from '../../../backend-defaults/src/entrypoints/cache/CacheManager'; -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -export { - type PluginCacheManager, - type CacheManagerOptions, -} from '../../../backend-defaults/src/entrypoints/cache/types'; diff --git a/packages/backend-common/src/auth/createLegacyAuthAdapters.test.ts b/packages/backend-common/src/compat/auth/createLegacyAuthAdapters.test.ts similarity index 100% rename from packages/backend-common/src/auth/createLegacyAuthAdapters.test.ts rename to packages/backend-common/src/compat/auth/createLegacyAuthAdapters.test.ts diff --git a/packages/backend-common/src/auth/createLegacyAuthAdapters.ts b/packages/backend-common/src/compat/auth/createLegacyAuthAdapters.ts similarity index 98% rename from packages/backend-common/src/auth/createLegacyAuthAdapters.ts rename to packages/backend-common/src/compat/auth/createLegacyAuthAdapters.ts index 97d8cd6240..0f591eac6c 100644 --- a/packages/backend-common/src/auth/createLegacyAuthAdapters.ts +++ b/packages/backend-common/src/compat/auth/createLegacyAuthAdapters.ts @@ -27,7 +27,6 @@ import { TokenManagerService, UserInfoService, } from '@backstage/backend-plugin-api'; -import { TokenManager } from '../tokens'; import { AuthenticationError, NotAllowedError } from '@backstage/errors'; import type { Request, Response } from 'express'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports @@ -36,14 +35,14 @@ import { createCredentialsWithUserPrincipal, createCredentialsWithNonePrincipal, toInternalBackstageCredentials, -} from '../../../backend-app-api/src/services/implementations/auth/helpers'; +} from '../../../../backend-defaults/src/entrypoints/auth/helpers'; // TODO is this circular thingy a problem? Test in e2e import { type IdentityApiGetIdentityRequest, DefaultIdentityClient, } from '@backstage/plugin-auth-node'; import { decodeJwt } from 'jose'; -import { PluginEndpointDiscovery } from '../discovery'; +import { TokenManager, PluginEndpointDiscovery } from '../../deprecated'; import { JsonObject } from '@backstage/types'; class AuthCompat implements AuthService { diff --git a/packages/backend-common/src/auth/index.ts b/packages/backend-common/src/compat/auth/index.ts similarity index 100% rename from packages/backend-common/src/auth/index.ts rename to packages/backend-common/src/compat/auth/index.ts diff --git a/packages/backend-common/src/cache/cacheToPluginCacheManager.ts b/packages/backend-common/src/compat/cache/cacheToPluginCacheManager.ts similarity index 100% rename from packages/backend-common/src/cache/cacheToPluginCacheManager.ts rename to packages/backend-common/src/compat/cache/cacheToPluginCacheManager.ts diff --git a/packages/backend-common/src/cache/index.ts b/packages/backend-common/src/compat/cache/index.ts similarity index 92% rename from packages/backend-common/src/cache/index.ts rename to packages/backend-common/src/compat/cache/index.ts index 9d05745ebd..bdd857037b 100644 --- a/packages/backend-common/src/cache/index.ts +++ b/packages/backend-common/src/compat/cache/index.ts @@ -15,5 +15,3 @@ */ export { cacheToPluginCacheManager } from './cacheToPluginCacheManager'; -export * from './reexport'; -export * from './types'; diff --git a/packages/backend-common/src/discovery/index.ts b/packages/backend-common/src/compat/index.ts similarity index 79% rename from packages/backend-common/src/discovery/index.ts rename to packages/backend-common/src/compat/index.ts index 827fd059ad..d702772335 100644 --- a/packages/backend-common/src/discovery/index.ts +++ b/packages/backend-common/src/compat/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Backstage Authors + * Copyright 2024 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,8 +14,7 @@ * limitations under the License. */ -export { - HostDiscovery, - SingleHostDiscovery, - type PluginEndpointDiscovery, -} from './HostDiscovery'; +export * from './legacy'; +export * from './auth'; +export * from './cache'; +export * from './logging'; diff --git a/packages/backend-common/src/compat/legacy/index.ts b/packages/backend-common/src/compat/legacy/index.ts new file mode 100644 index 0000000000..1172084cd7 --- /dev/null +++ b/packages/backend-common/src/compat/legacy/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { legacyPlugin, makeLegacyPlugin } from './legacy'; +export type { LegacyCreateRouter } from './legacy'; diff --git a/packages/backend-common/src/legacy.test.ts b/packages/backend-common/src/compat/legacy/legacy.test.ts similarity index 89% rename from packages/backend-common/src/legacy.test.ts rename to packages/backend-common/src/compat/legacy/legacy.test.ts index 1ddebce5c4..e5d395a8f9 100644 --- a/packages/backend-common/src/legacy.test.ts +++ b/packages/backend-common/src/compat/legacy/legacy.test.ts @@ -21,12 +21,12 @@ import { import { mockServices, startTestBackend } from '@backstage/backend-test-utils'; import { EventEmitter } from 'events'; import { Router } from 'express'; -import { createLegacyAuthAdapters } from './auth'; +import { createLegacyAuthAdapters } from '..'; import { legacyPlugin } from './legacy'; -import { - authServiceFactory, - tokenManagerServiceFactory, -} from '@backstage/backend-app-api'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { authServiceFactory } from '../../../../backend-app-api/src/services/implementations/auth'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { tokenManagerServiceFactory } from '../../../../backend-app-api/src/services/implementations/tokenManager'; describe('legacyPlugin', () => { it('can auth across the new and old systems', async () => { diff --git a/packages/backend-common/src/legacy.ts b/packages/backend-common/src/compat/legacy/legacy.ts similarity index 96% rename from packages/backend-common/src/legacy.ts rename to packages/backend-common/src/compat/legacy/legacy.ts index 6aa991489c..57220a8430 100644 --- a/packages/backend-common/src/legacy.ts +++ b/packages/backend-common/src/compat/legacy/legacy.ts @@ -21,9 +21,9 @@ import { ServiceRef, } from '@backstage/backend-plugin-api'; import { RequestHandler } from 'express'; -import { cacheToPluginCacheManager } from './cache'; -import { loggerToWinstonLogger } from './logging'; -import { TokenManager } from './tokens'; +import { cacheToPluginCacheManager } from '../cache'; +import { loggerToWinstonLogger } from '../logging'; +import { TokenManager } from '../../deprecated'; /** * @public diff --git a/packages/backend-common/src/database/index.ts b/packages/backend-common/src/compat/logging/index.ts similarity index 88% rename from packages/backend-common/src/database/index.ts rename to packages/backend-common/src/compat/logging/index.ts index 0e95261d82..10f949050c 100644 --- a/packages/backend-common/src/database/index.ts +++ b/packages/backend-common/src/compat/logging/index.ts @@ -14,5 +14,4 @@ * limitations under the License. */ -export * from './reexport'; -export type { PluginDatabaseManager } from './types'; +export { loggerToWinstonLogger } from './loggerToWinstonLogger'; diff --git a/packages/backend-common/src/logging/loggerToWinstonLogger.ts b/packages/backend-common/src/compat/logging/loggerToWinstonLogger.ts similarity index 100% rename from packages/backend-common/src/logging/loggerToWinstonLogger.ts rename to packages/backend-common/src/compat/logging/loggerToWinstonLogger.ts diff --git a/packages/backend-common/src/database/reexport.ts b/packages/backend-common/src/database/reexport.ts deleted file mode 100644 index 1ecff9be15..0000000000 --- a/packages/backend-common/src/database/reexport.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2024 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * NOTE(freben): This is a temporary hack. We use cross-package imports so that - * we do not have to maintain double implementations for the time being, until - * backend-common is properly removed. When it is, the impleemntation should be - * moved into this part of the repo instead. - */ - -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { - DatabaseManager, - dropDatabase, - type DatabaseManagerOptions, - type LegacyRootDatabaseService, -} from '../../../backend-defaults/src/entrypoints/database/DatabaseManager'; - -export { - DatabaseManager, - dropDatabase, - type DatabaseManagerOptions, - type LegacyRootDatabaseService, -}; diff --git a/packages/backend-common/src/database/types.ts b/packages/backend-common/src/database/types.ts deleted file mode 100644 index a9cceaa1f9..0000000000 --- a/packages/backend-common/src/database/types.ts +++ /dev/null @@ -1,100 +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 { - LifecycleService, - PluginMetadataService, -} from '@backstage/backend-plugin-api'; -import { Config } from '@backstage/config'; -import { Knex } from 'knex'; - -export type { DatabaseService as PluginDatabaseManager } from '@backstage/backend-plugin-api'; - -/** - * Manages an underlying Knex database driver. - */ -export interface DatabaseConnector { - /** - * Provides an instance of a knex database connector. - */ - createClient( - dbConfig: Config, - overrides?: Partial, - deps?: { - lifecycle: LifecycleService; - pluginMetadata: PluginMetadataService; - }, - ): Knex; - - /** - * Provides a partial knex config sufficient to override a database name. - */ - createNameOverride(name: string): Partial; - - /** - * Provides a partial knex config sufficient to override a PostgreSQL schema - * name within utilizing the `searchPath` knex configuration. - */ - createSchemaOverride?(name: string): Partial; - - /** - * Produces a knex connection config object representing a database connection - * string. - */ - parseConnectionString( - connectionString: string, - client?: string, - ): Knex.StaticConnectionConfig; - - /** - * Performs a side-effect to ensure database names passed in are present. - * - * Calling this function on databases which already exist should do nothing. - * Missing databases should be created if needed. - */ - ensureDatabaseExists?( - dbConfig: Config, - ...databases: Array - ): Promise; - - /** - * Performs a side-effect to ensure schema names passed in are present. - * - * Calling this function on schemas which already exist should do nothing. - * Missing schemas should be created if needed. - */ - ensureSchemaExists?( - dbConfig: Config, - ...schemas: Array - ): Promise; - - /** - * Deletes databases. - */ - dropDatabase?(dbConfig: Config, ...databases: Array): Promise; -} - -export interface Connector { - getClient( - pluginId: string, - deps?: { - lifecycle: LifecycleService; - pluginMetadata: PluginMetadataService; - }, - ): Promise; - - dropDatabase(...databaseNames: string[]): Promise; -} diff --git a/packages/backend-common/src/config.ts b/packages/backend-common/src/deprecated/config.ts similarity index 93% rename from packages/backend-common/src/config.ts rename to packages/backend-common/src/deprecated/config.ts index 1dfa9643e2..2d06ca2072 100644 --- a/packages/backend-common/src/config.ts +++ b/packages/backend-common/src/deprecated/config.ts @@ -14,10 +14,11 @@ * limitations under the License. */ +// eslint-disable-next-line @backstage/no-relative-monorepo-imports import { createConfigSecretEnumerator, loadBackendConfig as newLoadBackendConfig, -} from '@backstage/backend-app-api'; +} from '../../../backend-app-api/src/config'; import { LoggerService } from '@backstage/backend-plugin-api'; import { AppConfig, Config } from '@backstage/config'; import { LoadConfigOptionsRemote } from '@backstage/config-loader'; diff --git a/packages/backend-common/src/context/AbortContext.test.ts b/packages/backend-common/src/deprecated/context/AbortContext.test.ts similarity index 100% rename from packages/backend-common/src/context/AbortContext.test.ts rename to packages/backend-common/src/deprecated/context/AbortContext.test.ts diff --git a/packages/backend-common/src/context/AbortContext.ts b/packages/backend-common/src/deprecated/context/AbortContext.ts similarity index 100% rename from packages/backend-common/src/context/AbortContext.ts rename to packages/backend-common/src/deprecated/context/AbortContext.ts diff --git a/packages/backend-common/src/context/Contexts.test.ts b/packages/backend-common/src/deprecated/context/Contexts.test.ts similarity index 100% rename from packages/backend-common/src/context/Contexts.test.ts rename to packages/backend-common/src/deprecated/context/Contexts.test.ts diff --git a/packages/backend-common/src/context/Contexts.ts b/packages/backend-common/src/deprecated/context/Contexts.ts similarity index 100% rename from packages/backend-common/src/context/Contexts.ts rename to packages/backend-common/src/deprecated/context/Contexts.ts diff --git a/packages/backend-common/src/context/RootContext.test.ts b/packages/backend-common/src/deprecated/context/RootContext.test.ts similarity index 100% rename from packages/backend-common/src/context/RootContext.test.ts rename to packages/backend-common/src/deprecated/context/RootContext.test.ts diff --git a/packages/backend-common/src/context/RootContext.ts b/packages/backend-common/src/deprecated/context/RootContext.ts similarity index 100% rename from packages/backend-common/src/context/RootContext.ts rename to packages/backend-common/src/deprecated/context/RootContext.ts diff --git a/packages/backend-common/src/context/ValueContext.test.ts b/packages/backend-common/src/deprecated/context/ValueContext.test.ts similarity index 100% rename from packages/backend-common/src/context/ValueContext.test.ts rename to packages/backend-common/src/deprecated/context/ValueContext.test.ts diff --git a/packages/backend-common/src/context/ValueContext.ts b/packages/backend-common/src/deprecated/context/ValueContext.ts similarity index 100% rename from packages/backend-common/src/context/ValueContext.ts rename to packages/backend-common/src/deprecated/context/ValueContext.ts diff --git a/packages/backend-common/src/context/index.ts b/packages/backend-common/src/deprecated/context/index.ts similarity index 100% rename from packages/backend-common/src/context/index.ts rename to packages/backend-common/src/deprecated/context/index.ts diff --git a/packages/backend-common/src/context/types.ts b/packages/backend-common/src/deprecated/context/types.ts similarity index 100% rename from packages/backend-common/src/context/types.ts rename to packages/backend-common/src/deprecated/context/types.ts diff --git a/packages/backend-common/src/hot.ts b/packages/backend-common/src/deprecated/hot.ts similarity index 100% rename from packages/backend-common/src/hot.ts rename to packages/backend-common/src/deprecated/hot.ts diff --git a/packages/backend-common/src/deprecated/index.ts b/packages/backend-common/src/deprecated/index.ts index d9ca795c3a..e3e4101d25 100644 --- a/packages/backend-common/src/deprecated/index.ts +++ b/packages/backend-common/src/deprecated/index.ts @@ -14,15 +14,255 @@ * limitations under the License. */ -export * from './scm'; +import { Config } from '@backstage/config'; + +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { HostDiscovery as _HostDiscovery } from '../../../backend-defaults/src/entrypoints/discovery/HostDiscovery'; + +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { CacheManager as _CacheManager } from '../../../backend-defaults/src/entrypoints/cache/CacheManager'; + +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { + type PluginCacheManager as _PluginCacheManager, + type CacheManagerOptions as _CacheManagerOptions, +} from '../../../backend-defaults/src/entrypoints/cache/types'; + +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { + dropDatabase as _dropDatabase, + DatabaseManager as _DatabaseManager, + type DatabaseManagerOptions as _DatabaseManagerOptions, + type LegacyRootDatabaseService as _LegacyRootDatabaseService, +} from '../../../backend-defaults/src/entrypoints/database/DatabaseManager'; + +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { AzureUrlReader as _AzureUrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/AzureUrlReader'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { BitbucketCloudUrlReader as _BitbucketCloudUrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/BitbucketCloudUrlReader'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { BitbucketUrlReader as _BitbucketUrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { BitbucketServerUrlReader as _BitbucketServerUrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/BitbucketServerUrlReader'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { GerritUrlReader as _GerritUrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/GerritUrlReader'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { GithubUrlReader as _GithubUrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/GithubUrlReader'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { GitlabUrlReader as _GitlabUrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/GitlabUrlReader'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { GiteaUrlReader as _GiteaUrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/GiteaUrlReader'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { HarnessUrlReader as _HarnessUrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/HarnessUrlReader'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { AwsS3UrlReader as _AwsS3UrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/AwsS3UrlReader'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { FetchUrlReader as _FetchUrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/FetchUrlReader'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { UrlReaders as _UrlReaders } from '../../../backend-defaults/src/entrypoints/urlReader/lib/UrlReaders'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { ReadUrlResponseFactory as _ReadUrlResponseFactory } from '../../../backend-defaults/src/entrypoints/urlReader/lib/ReadUrlResponseFactory'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import type { UrlReadersOptions as _UrlReadersOptions } from '../../../backend-defaults/src/entrypoints/urlReader/lib/UrlReaders'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import type { FromReadableArrayOptions as _FromReadableArrayOptions } from '../../../backend-defaults/src/entrypoints/urlReader/lib/types'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import type { + ReaderFactory as _ReaderFactory, + ReadTreeResponseFactory as _ReadTreeResponseFactory, + ReadTreeResponseFactoryOptions as _ReadTreeResponseFactoryOptions, + ReadUrlResponseFactoryFromStreamOptions as _ReadUrlResponseFactoryFromStreamOptions, + UrlReaderPredicateTuple as _UrlReaderPredicateTuple, +} from '../../../backend-defaults/src/entrypoints/urlReader/lib/types'; import { + DiscoveryService, + CacheService, + CacheServiceOptions, + CacheServiceSetOptions, + DatabaseService as _PluginDatabaseManager, isDatabaseConflictError as _isDatabaseConflictError, resolvePackagePath as _resolvePackagePath, resolveSafeChildPath as _resolveSafeChildPath, isChildPath as _isChildPath, + ReadTreeOptions as _ReadTreeOptions, + ReadTreeResponse as _ReadTreeResponse, + ReadTreeResponseFile as _ReadTreeResponseFile, + ReadTreeResponseDirOptions as _ReadTreeResponseDirOptions, + ReadUrlOptions as _ReadUrlOptions, + ReadUrlResponse as _ReadUrlResponse, + SearchOptions as _SearchOptions, + SearchResponse as _SearchResponse, + SearchResponseFile as _SearchResponseFile, + UrlReaderService as _UrlReaderService, + LifecycleService, + PluginMetadataService, } from '@backstage/backend-plugin-api'; +export * from './hot'; +export * from './config'; +export * from './scm'; +export * from './tokens'; +export * from './logging'; +export * from './service'; +export * from './middleware'; +export * from './util'; + +/** + * @public + * @deprecated Use `DiscoveryService` from `@backstage/backend-plugin-api` instead + */ +export type PluginEndpointDiscovery = DiscoveryService; + +/** + * HostDiscovery is a basic PluginEndpointDiscovery implementation + * that can handle plugins that are hosted in a single or multiple deployments. + * + * The deployment may be scaled horizontally, as long as the external URL + * is the same for all instances. However, internal URLs will always be + * resolved to the same host, so there won't be any balancing of internal traffic. + * + * @public + * @deprecated Please import from `@backstage/backend-defaults/discovery` instead. + */ +export class HostDiscovery implements DiscoveryService { + /** + * Creates a new HostDiscovery discovery instance by reading + * from the `backend` config section, specifically the `.baseUrl` for + * discovering the external URL, and the `.listen` and `.https` config + * for the internal one. + * + * Can be overridden in config by providing a target and corresponding plugins in `discovery.endpoints`. + * eg. + * ```yaml + * discovery: + * endpoints: + * - target: https://internal.example.com/internal-catalog + * plugins: [catalog] + * - target: https://internal.example.com/secure/api/{{pluginId}} + * plugins: [auth, permission] + * - target: + * internal: https://internal.example.com/search + * external: https://example.com/search + * plugins: [search] + * ``` + * + * The basePath defaults to `/api`, meaning the default full internal + * path for the `catalog` plugin will be `http://localhost:7007/api/catalog`. + */ + static fromConfig(config: Config, options?: { basePath?: string }) { + return new HostDiscovery(_HostDiscovery.fromConfig(config, options)); + } + + private constructor(private readonly impl: _HostDiscovery) {} + + async getBaseUrl(pluginId: string): Promise { + return this.impl.getBaseUrl(pluginId); + } + + async getExternalBaseUrl(pluginId: string): Promise { + return this.impl.getExternalBaseUrl(pluginId); + } +} + +/** + * SingleHostDiscovery is a basic PluginEndpointDiscovery implementation + * that assumes that all plugins are hosted in a single deployment. + * + * The deployment may be scaled horizontally, as long as the external URL + * is the same for all instances. However, internal URLs will always be + * resolved to the same host, so there won't be any balancing of internal traffic. + * + * @public + * @deprecated Use `HostDiscovery` from `@backstage/backend-defaults/discovery` instead + */ +export { HostDiscovery as SingleHostDiscovery }; + +/** + * @public + * @deprecated Use `CacheManager` from the `@backstage/backend-defaults` package instead + */ +export class CacheManager extends _CacheManager {} + +/** + * @public + * @deprecated Use `CacheManagerOptions` from the `@backstage/backend-defaults` package instead + */ +export type CacheManagerOptions = _CacheManagerOptions; + +/** + * @public + * @deprecated Use `PluginCacheManager` from the `@backstage/backend-defaults` package instead + */ +export type PluginCacheManager = _PluginCacheManager; + +/** + * @public + * @deprecated Use `CacheService` from the `@backstage/backend-plugin-api` package instead + */ +export type CacheClient = CacheService; + +/** + * @public + * @deprecated Use `CacheServiceSetOptions` from the `@backstage/backend-plugin-api` package instead + */ +export type CacheClientSetOptions = CacheServiceSetOptions; + +/** + * @public + * @deprecated Use `CacheServiceOptions` from the `@backstage/backend-plugin-api` package instead + */ +export type CacheClientOptions = CacheServiceOptions; + +/** + * @public + * @deprecated Use `DatabaseManager` from the `@backstage/backend-defaults` package instead + */ +export class DatabaseManager implements LegacyRootDatabaseService { + private constructor(private readonly _databaseManager: _DatabaseManager) {} + + static fromConfig( + config: Config, + options?: DatabaseManagerOptions, + ): DatabaseManager { + const _databaseManager = _DatabaseManager.fromConfig(config, options); + return new DatabaseManager(_databaseManager); + } + + forPlugin( + pluginId: string, + deps?: + | { lifecycle: LifecycleService; pluginMetadata: PluginMetadataService } + | undefined, + ): PluginDatabaseManager { + return this._databaseManager.forPlugin(pluginId, deps); + } +} + +/** + * @public + * @deprecated Use `DatabaseManagerOptions` from the `@backstage/backend-defaults` package instead + */ +export type DatabaseManagerOptions = _DatabaseManagerOptions; + +/** + * @public + * @deprecated Use `DatabaseService` from the `@backstage/backend-plugin-api` package instead + */ +export type PluginDatabaseManager = _PluginDatabaseManager; + +/** + * @public + * @deprecated Use `LegacyRootDatabaseService` from the `@backstage/backend-defaults` package instead + */ +export type LegacyRootDatabaseService = _LegacyRootDatabaseService; + +/** + * @public + * @deprecated Use `dropDatabase` from the `@backstage/backend-defaults` package instead + */ +export const dropDatabase = _dropDatabase; + /** * @public * @deprecated This function is deprecated and will be removed in a future release, see https://github.com/backstage/backstage/issues/24493. @@ -50,3 +290,184 @@ export const resolveSafeChildPath = _resolveSafeChildPath; * Please use the `isChildPath` function from the `@backstage/cli-common` package instead. */ export const isChildPath = _isChildPath; + +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export class AzureUrlReader extends _AzureUrlReader {} + +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export class BitbucketCloudUrlReader extends _BitbucketCloudUrlReader {} + +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export class BitbucketUrlReader extends _BitbucketUrlReader {} + +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export class BitbucketServerUrlReader extends _BitbucketServerUrlReader {} + +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export class GerritUrlReader extends _GerritUrlReader {} + +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export class GithubUrlReader extends _GithubUrlReader {} + +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export class GitlabUrlReader extends _GitlabUrlReader {} + +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export class GiteaUrlReader extends _GiteaUrlReader {} + +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export class HarnessUrlReader extends _HarnessUrlReader {} + +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export class AwsS3UrlReader extends _AwsS3UrlReader {} + +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export class FetchUrlReader extends _FetchUrlReader {} + +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export class UrlReaders extends _UrlReaders {} + +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export class ReadUrlResponseFactory extends _ReadUrlResponseFactory {} + +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export type UrlReadersOptions = _UrlReadersOptions; + +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export type FromReadableArrayOptions = _FromReadableArrayOptions; + +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export type ReaderFactory = _ReaderFactory; + +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export type ReadTreeResponseFactory = _ReadTreeResponseFactory; + +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export type ReadTreeResponseFactoryOptions = _ReadTreeResponseFactoryOptions; + +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export type ReadUrlResponseFactoryFromStreamOptions = + _ReadUrlResponseFactoryFromStreamOptions; + +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export type UrlReaderPredicateTuple = _UrlReaderPredicateTuple; + +/** + * @public + * @deprecated Use `UrlReaderServiceReadTreeOptions` from `@backstage/backend-plugin-api` instead + */ +export type ReadTreeOptions = _ReadTreeOptions; + +/** + * @public + * @deprecated Use `UrlReaderServiceReadTreeResponse` from `@backstage/backend-plugin-api` instead + */ +export type ReadTreeResponse = _ReadTreeResponse; + +/** + * @public + * @deprecated Use `UrlReaderServiceReadTreeResponseFile` from `@backstage/backend-plugin-api` instead + */ +export type ReadTreeResponseFile = _ReadTreeResponseFile; + +/** + * @public + * @deprecated Use `UrlReaderServiceReadTreeResponseDirOptions` from `@backstage/backend-plugin-api` instead + */ +export type ReadTreeResponseDirOptions = _ReadTreeResponseDirOptions; + +/** + * @public + * @deprecated Use `UrlReaderServiceReadUrlOptions` from `@backstage/backend-plugin-api` instead + */ +export type ReadUrlOptions = _ReadUrlOptions; + +/** + * @public + * @deprecated Use `UrlReaderServiceReadUrlResponse` from `@backstage/backend-plugin-api` instead + */ +export type ReadUrlResponse = _ReadUrlResponse; + +/** + * @public + * @deprecated Use `UrlReaderServiceSearchOptions` from `@backstage/backend-plugin-api` instead + */ +export type SearchOptions = _SearchOptions; + +/** + * @public + * @deprecated Use `UrlReaderServiceSearchResponse` from `@backstage/backend-plugin-api` instead + */ +export type SearchResponse = _SearchResponse; + +/** + * @public + * @deprecated Use `UrlReaderServiceSearchResponseFile` from `@backstage/backend-plugin-api` instead + */ +export type SearchResponseFile = _SearchResponseFile; + +/** + * @public + * @deprecated Use `UrlReaderService` from `@backstage/backend-plugin-api` instead + */ +export type UrlReader = _UrlReaderService; diff --git a/packages/backend-common/src/logging/createRootLogger.ts b/packages/backend-common/src/deprecated/logging/createRootLogger.ts similarity index 86% rename from packages/backend-common/src/logging/createRootLogger.ts rename to packages/backend-common/src/deprecated/logging/createRootLogger.ts index 16554750ef..b177024601 100644 --- a/packages/backend-common/src/logging/createRootLogger.ts +++ b/packages/backend-common/src/deprecated/logging/createRootLogger.ts @@ -14,12 +14,13 @@ * limitations under the License. */ -import { WinstonLogger } from '@backstage/backend-app-api'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { WinstonLogger } from '../../../../backend-app-api/src/logging/WinstonLogger'; import { merge } from 'lodash'; import * as winston from 'winston'; import { format, LoggerOptions } from 'winston'; -import { setRootLogger } from './globalLoggers'; import { TransformableInfo } from 'logform'; +import { setRootLogger } from './globalLoggers'; const getRedacter = (() => { let redacter: ReturnType | undefined = @@ -43,6 +44,8 @@ export const setRootLoggerRedactionList = ( * and replaces them with the corresponding identifier. * * @public + * @deprecated This utility is being deprecated along with the {@link https://github.com/backstage/backstage/issues/24493 |legacy backend system}. + * Migrate your {@link https://backstage.io/docs/backend-system/building-backends/migrating | backend} and {@link https://backstage.io/docs/backend-system/building-plugins-and-modules/migrating | plugin} to the new system and use the {@link https://github.com/backstage/backstage/pull/24730 | RedactionsService} for customization instead. */ export function redactWinstonLogLine( info: winston.Logform.TransformableInfo, diff --git a/packages/backend-common/src/logging/globalLoggers.ts b/packages/backend-common/src/deprecated/logging/globalLoggers.ts similarity index 100% rename from packages/backend-common/src/logging/globalLoggers.ts rename to packages/backend-common/src/deprecated/logging/globalLoggers.ts diff --git a/packages/backend-common/src/logging/index.ts b/packages/backend-common/src/deprecated/logging/index.ts similarity index 92% rename from packages/backend-common/src/logging/index.ts rename to packages/backend-common/src/deprecated/logging/index.ts index e6b29afa15..b223f5c946 100644 --- a/packages/backend-common/src/logging/index.ts +++ b/packages/backend-common/src/deprecated/logging/index.ts @@ -20,4 +20,3 @@ export { redactWinstonLogLine, coloredFormat, } from './createRootLogger'; -export { loggerToWinstonLogger } from './loggerToWinstonLogger'; diff --git a/packages/backend-common/src/middleware/errorHandler.test.ts b/packages/backend-common/src/deprecated/middleware/errorHandler.test.ts similarity index 100% rename from packages/backend-common/src/middleware/errorHandler.test.ts rename to packages/backend-common/src/deprecated/middleware/errorHandler.test.ts index ab07a91022..2544a0a863 100644 --- a/packages/backend-common/src/middleware/errorHandler.test.ts +++ b/packages/backend-common/src/deprecated/middleware/errorHandler.test.ts @@ -14,6 +14,10 @@ * limitations under the License. */ +import express from 'express'; +import { STATUS_CODES } from 'http'; +import createError from 'http-errors'; +import request from 'supertest'; import { AuthenticationError, ConflictError, @@ -23,11 +27,7 @@ import { NotModifiedError, ResponseError, } from '@backstage/errors'; -import express from 'express'; -import createError from 'http-errors'; -import request from 'supertest'; import { errorHandler } from './errorHandler'; -import { STATUS_CODES } from 'http'; describe('errorHandler', () => { it('gives default code and message', async () => { diff --git a/packages/backend-common/src/middleware/errorHandler.ts b/packages/backend-common/src/deprecated/middleware/errorHandler.ts similarity index 84% rename from packages/backend-common/src/middleware/errorHandler.ts rename to packages/backend-common/src/deprecated/middleware/errorHandler.ts index 110734b0a2..b4f07b9320 100644 --- a/packages/backend-common/src/middleware/errorHandler.ts +++ b/packages/backend-common/src/deprecated/middleware/errorHandler.ts @@ -16,14 +16,16 @@ import { ErrorRequestHandler } from 'express'; import { LoggerService } from '@backstage/backend-plugin-api'; -import { getRootLogger } from '../logging'; import { ConfigReader } from '@backstage/config'; -import { MiddlewareFactory } from '@backstage/backend-app-api'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { MiddlewareFactory } from '../../../../backend-defaults/src/entrypoints/rootHttpRouter/http/MiddlewareFactory'; +import { getRootLogger } from '../logging'; /** * Options passed to the {@link errorHandler} middleware. * * @public + * @deprecated This type is being deprecated along with the {@link @backstage/backend-common#errorHandler} function. */ export type ErrorHandlerOptions = { /** @@ -61,7 +63,7 @@ export type ErrorHandlerOptions = { * * @public * @returns An Express error request handler - * @deprecated Use {@link @backstage/backend-app-api#MiddlewareFactory.create.error} instead + * @deprecated Use {@link @backstage/backend-defaults/rootHttpRouter#MiddlewareFactory.create.error} instead */ export function errorHandler( options: ErrorHandlerOptions = {}, diff --git a/packages/backend-common/src/middleware/index.ts b/packages/backend-common/src/deprecated/middleware/index.ts similarity index 100% rename from packages/backend-common/src/middleware/index.ts rename to packages/backend-common/src/deprecated/middleware/index.ts diff --git a/packages/backend-common/src/middleware/notFoundHandler.test.ts b/packages/backend-common/src/deprecated/middleware/notFoundHandler.test.ts similarity index 100% rename from packages/backend-common/src/middleware/notFoundHandler.test.ts rename to packages/backend-common/src/deprecated/middleware/notFoundHandler.test.ts diff --git a/packages/backend-common/src/middleware/notFoundHandler.ts b/packages/backend-common/src/deprecated/middleware/notFoundHandler.ts similarity index 80% rename from packages/backend-common/src/middleware/notFoundHandler.ts rename to packages/backend-common/src/deprecated/middleware/notFoundHandler.ts index 4f29b4f824..bb9504a9ec 100644 --- a/packages/backend-common/src/middleware/notFoundHandler.ts +++ b/packages/backend-common/src/deprecated/middleware/notFoundHandler.ts @@ -14,7 +14,8 @@ * limitations under the License. */ -import { MiddlewareFactory } from '@backstage/backend-app-api'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { MiddlewareFactory } from '../../../../backend-defaults/src/entrypoints/rootHttpRouter/http/MiddlewareFactory'; import { ConfigReader } from '@backstage/config'; import { RequestHandler } from 'express'; import { getRootLogger } from '../logging'; @@ -27,6 +28,7 @@ import { getRootLogger } from '../logging'; * * @public * @returns An Express request handler + * @deprecated Use {@link @backstage/backend-app-api#MiddlewareFactory.create.notFound} instead */ export function notFoundHandler(): RequestHandler { return MiddlewareFactory.create({ diff --git a/packages/backend-common/src/middleware/requestLoggingHandler.test.ts b/packages/backend-common/src/deprecated/middleware/requestLoggingHandler.test.ts similarity index 100% rename from packages/backend-common/src/middleware/requestLoggingHandler.test.ts rename to packages/backend-common/src/deprecated/middleware/requestLoggingHandler.test.ts diff --git a/packages/backend-common/src/middleware/requestLoggingHandler.ts b/packages/backend-common/src/deprecated/middleware/requestLoggingHandler.ts similarity index 80% rename from packages/backend-common/src/middleware/requestLoggingHandler.ts rename to packages/backend-common/src/deprecated/middleware/requestLoggingHandler.ts index 81dfa1d345..f30f2de659 100644 --- a/packages/backend-common/src/middleware/requestLoggingHandler.ts +++ b/packages/backend-common/src/deprecated/middleware/requestLoggingHandler.ts @@ -14,11 +14,12 @@ * limitations under the License. */ -import { MiddlewareFactory } from '@backstage/backend-app-api'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { MiddlewareFactory } from '../../../../backend-defaults/src/entrypoints/rootHttpRouter/http/MiddlewareFactory'; import { RequestHandler } from 'express'; +import { ConfigReader } from '@backstage/config'; import { LoggerService } from '@backstage/backend-plugin-api'; import { getRootLogger } from '../logging'; -import { ConfigReader } from '@backstage/config'; /** * Logs incoming requests. @@ -26,7 +27,7 @@ import { ConfigReader } from '@backstage/config'; * @public * @param logger - An optional logger to use. If not specified, the root logger will be used. * @returns An Express request handler - * @deprecated @deprecated Use {@link @backstage/backend-app-api#MiddlewareFactory.create.logging} instead + * @deprecated Use {@link @backstage/backend-app-api#MiddlewareFactory.create.logging} instead */ export function requestLoggingHandler(logger?: LoggerService): RequestHandler { return MiddlewareFactory.create({ diff --git a/packages/backend-common/src/middleware/statusCheckHandler.test.ts b/packages/backend-common/src/deprecated/middleware/statusCheckHandler.test.ts similarity index 100% rename from packages/backend-common/src/middleware/statusCheckHandler.test.ts rename to packages/backend-common/src/deprecated/middleware/statusCheckHandler.test.ts diff --git a/packages/backend-common/src/middleware/statusCheckHandler.ts b/packages/backend-common/src/deprecated/middleware/statusCheckHandler.ts similarity index 73% rename from packages/backend-common/src/middleware/statusCheckHandler.ts rename to packages/backend-common/src/deprecated/middleware/statusCheckHandler.ts index 4bd1a701c3..ebaf84c1b9 100644 --- a/packages/backend-common/src/middleware/statusCheckHandler.ts +++ b/packages/backend-common/src/deprecated/middleware/statusCheckHandler.ts @@ -21,6 +21,7 @@ import { NextFunction, Request, Response, RequestHandler } from 'express'; * {@link createStatusCheckRouter}. * * @public + * @deprecated Migrate to the {@link https://backstage.io/docs/backend-system/ | new backend system} and use the {@link https://backstage.io/docs/backend-system/core-services/root-health | Root Health Service} instead. */ export type StatusCheck = () => Promise; @@ -28,6 +29,7 @@ export type StatusCheck = () => Promise; * Options passed to {@link statusCheckHandler}. * * @public + * @deprecated Migrate to the {@link https://backstage.io/docs/backend-system/ | new backend system} and use the {@link https://backstage.io/docs/backend-system/core-services/root-health | Root Health Service} instead. */ export interface StatusCheckHandlerOptions { /** @@ -44,6 +46,7 @@ export interface StatusCheckHandlerOptions { * @public * @param options - An optional configuration object. * @returns An Express error request handler + * @deprecated Migrate to the {@link https://backstage.io/docs/backend-system/ | new backend system} and use the {@link https://backstage.io/docs/backend-system/core-services/root-health | Root Health Service} instead. */ export async function statusCheckHandler( options: StatusCheckHandlerOptions = {}, diff --git a/packages/backend-common/src/service/createServiceBuilder.ts b/packages/backend-common/src/deprecated/service/createServiceBuilder.ts similarity index 100% rename from packages/backend-common/src/service/createServiceBuilder.ts rename to packages/backend-common/src/deprecated/service/createServiceBuilder.ts diff --git a/packages/backend-common/src/service/createStatusCheckRouter.test.ts b/packages/backend-common/src/deprecated/service/createStatusCheckRouter.test.ts similarity index 100% rename from packages/backend-common/src/service/createStatusCheckRouter.test.ts rename to packages/backend-common/src/deprecated/service/createStatusCheckRouter.test.ts diff --git a/packages/backend-common/src/service/createStatusCheckRouter.ts b/packages/backend-common/src/deprecated/service/createStatusCheckRouter.ts similarity index 88% rename from packages/backend-common/src/service/createStatusCheckRouter.ts rename to packages/backend-common/src/deprecated/service/createStatusCheckRouter.ts index b43bd5585c..fdece10ec5 100644 --- a/packages/backend-common/src/service/createStatusCheckRouter.ts +++ b/packages/backend-common/src/deprecated/service/createStatusCheckRouter.ts @@ -17,7 +17,7 @@ import { LoggerService } from '@backstage/backend-plugin-api'; import Router from 'express-promise-router'; import express from 'express'; -import { errorHandler, statusCheckHandler, StatusCheck } from '../middleware'; +import { errorHandler, statusCheckHandler, StatusCheck } from '..'; /** * Creates a default status checking router, that you can add to your express @@ -30,6 +30,7 @@ import { errorHandler, statusCheckHandler, StatusCheck } from '../middleware'; * requests. * * @public + * @deprecated Migrate to the {@link https://backstage.io/docs/backend-system/ | new backend system} and use the {@link https://backstage.io/docs/backend-system/core-services/root-health | Root Health Service} instead. */ export async function createStatusCheckRouter(options: { logger: LoggerService; diff --git a/packages/backend-common/src/service/index.ts b/packages/backend-common/src/deprecated/service/index.ts similarity index 100% rename from packages/backend-common/src/service/index.ts rename to packages/backend-common/src/deprecated/service/index.ts diff --git a/packages/backend-common/src/service/lib/ServiceBuilderImpl.test.ts b/packages/backend-common/src/deprecated/service/lib/ServiceBuilderImpl.test.ts similarity index 100% rename from packages/backend-common/src/service/lib/ServiceBuilderImpl.test.ts rename to packages/backend-common/src/deprecated/service/lib/ServiceBuilderImpl.test.ts diff --git a/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts b/packages/backend-common/src/deprecated/service/lib/ServiceBuilderImpl.ts similarity index 97% rename from packages/backend-common/src/service/lib/ServiceBuilderImpl.ts rename to packages/backend-common/src/deprecated/service/lib/ServiceBuilderImpl.ts index f577017b77..b338eb20b1 100644 --- a/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts +++ b/packages/backend-common/src/deprecated/service/lib/ServiceBuilderImpl.ts @@ -30,13 +30,14 @@ import { requestLoggingHandler as defaultRequestLoggingHandler, } from '../../middleware'; import { RequestLoggingHandlerFactory, ServiceBuilder } from '../types'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports import { readCorsOptions, readHelmetOptions, readHttpServerOptions, HttpServerOptions, createHttpServer, -} from '@backstage/backend-app-api'; +} from '../../../../../backend-defaults/src/entrypoints/rootHttpRouter/http'; export type CspOptions = Record; diff --git a/packages/backend-common/src/service/types.ts b/packages/backend-common/src/deprecated/service/types.ts similarity index 93% rename from packages/backend-common/src/service/types.ts rename to packages/backend-common/src/deprecated/service/types.ts index 1fd5b9fff1..ace0712d2f 100644 --- a/packages/backend-common/src/service/types.ts +++ b/packages/backend-common/src/deprecated/service/types.ts @@ -24,6 +24,7 @@ import { LoggerService } from '@backstage/backend-plugin-api'; * A helper for building backend service instances. * * @public + * @deprecated This type is being deprecated along with the {@link @backstage/backend-common#createServiceBuilder} function. */ export type ServiceBuilder = { /** @@ -127,6 +128,7 @@ export type ServiceBuilder = { * A factory for request loggers. * * @public + * @deprecated This type is being deprecated along with the {@link @backstage/backend-common#createServiceBuilder} function. */ export type RequestLoggingHandlerFactory = ( logger?: LoggerService, diff --git a/packages/backend-common/src/tokens/ServerTokenManager.test.ts b/packages/backend-common/src/deprecated/tokens/ServerTokenManager.test.ts similarity index 100% rename from packages/backend-common/src/tokens/ServerTokenManager.test.ts rename to packages/backend-common/src/deprecated/tokens/ServerTokenManager.test.ts diff --git a/packages/backend-common/src/tokens/ServerTokenManager.ts b/packages/backend-common/src/deprecated/tokens/ServerTokenManager.ts similarity index 94% rename from packages/backend-common/src/tokens/ServerTokenManager.ts rename to packages/backend-common/src/deprecated/tokens/ServerTokenManager.ts index a62eb8de55..a9dee0f67a 100644 --- a/packages/backend-common/src/tokens/ServerTokenManager.ts +++ b/packages/backend-common/src/deprecated/tokens/ServerTokenManager.ts @@ -61,6 +61,7 @@ class DisabledTokenManager implements TokenManager { * Options for {@link ServerTokenManager}. * * @public + * @deprecated Please {@link https://backstage.io/docs/tutorials/auth-service-migration | migrate} to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead. */ export interface ServerTokenManagerOptions { /** @@ -79,6 +80,7 @@ export interface ServerTokenManagerOptions { * authentication. * * @public + * @deprecated Please {@link https://backstage.io/docs/tutorials/auth-service-migration | migrate} to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead. */ export class ServerTokenManager implements TokenManager { private readonly options: ServerTokenManagerOptions; diff --git a/packages/backend-common/src/tokens/index.ts b/packages/backend-common/src/deprecated/tokens/index.ts similarity index 100% rename from packages/backend-common/src/tokens/index.ts rename to packages/backend-common/src/deprecated/tokens/index.ts diff --git a/packages/backend-common/src/util/escapeRegExp.ts b/packages/backend-common/src/deprecated/tokens/types.ts similarity index 64% rename from packages/backend-common/src/util/escapeRegExp.ts rename to packages/backend-common/src/deprecated/tokens/types.ts index bc78967ebe..09dc0bb211 100644 --- a/packages/backend-common/src/util/escapeRegExp.ts +++ b/packages/backend-common/src/deprecated/tokens/types.ts @@ -14,11 +14,10 @@ * limitations under the License. */ +import { TokenManagerService } from '@backstage/backend-plugin-api'; + /** - * Escapes a given string to be used inside a RegExp. - * - * Taken from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions + * @public + * @deprecated Please {@link https://backstage.io/docs/tutorials/auth-service-migration | migrate} to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead. */ -export const escapeRegExp = (text: string) => { - return text.replace(/[.*+?^${}(\)|[\]\\]/g, '\\$&'); -}; +export type TokenManager = TokenManagerService; diff --git a/packages/backend-common/src/util/ContainerRunner.ts b/packages/backend-common/src/deprecated/util/ContainerRunner.ts similarity index 87% rename from packages/backend-common/src/util/ContainerRunner.ts rename to packages/backend-common/src/deprecated/util/ContainerRunner.ts index 351a5da613..92081cea16 100644 --- a/packages/backend-common/src/util/ContainerRunner.ts +++ b/packages/backend-common/src/deprecated/util/ContainerRunner.ts @@ -22,6 +22,7 @@ import { Writable } from 'stream'; * {@link https://github.com/apocas/dockerode?tab=readme-ov-file#pull-from-private-repos} * * @public + * @deprecated This interface is deprecated and will be removed in a future release. */ export interface PullOptions { authconfig?: { @@ -39,6 +40,7 @@ export interface PullOptions { * Options passed to the {@link ContainerRunner.runContainer} method. * * @public + * @deprecated This type is deprecated and will be removed in a future release. */ export type RunContainerOptions = { imageName: string; @@ -57,6 +59,7 @@ export type RunContainerOptions = { * Handles the running of containers, on behalf of others. * * @public + * @deprecated This interface is deprecated and will be removed in a future release. */ export interface ContainerRunner { /** diff --git a/packages/backend-common/src/util/DockerContainerRunner.test.ts b/packages/backend-common/src/deprecated/util/DockerContainerRunner.test.ts similarity index 100% rename from packages/backend-common/src/util/DockerContainerRunner.test.ts rename to packages/backend-common/src/deprecated/util/DockerContainerRunner.test.ts diff --git a/packages/backend-common/src/util/DockerContainerRunner.ts b/packages/backend-common/src/deprecated/util/DockerContainerRunner.ts similarity index 98% rename from packages/backend-common/src/util/DockerContainerRunner.ts rename to packages/backend-common/src/deprecated/util/DockerContainerRunner.ts index 89a17fff51..ea576e4a3a 100644 --- a/packages/backend-common/src/util/DockerContainerRunner.ts +++ b/packages/backend-common/src/deprecated/util/DockerContainerRunner.ts @@ -28,6 +28,7 @@ export type UserOptions = { * A {@link ContainerRunner} for Docker containers. * * @public + * @deprecated This class is deprecated and will be removed in a future release. */ export class DockerContainerRunner implements ContainerRunner { private readonly dockerClient: Docker; diff --git a/packages/backend-common/src/util/KubernetesContainerRunner.test.ts b/packages/backend-common/src/deprecated/util/KubernetesContainerRunner.test.ts similarity index 100% rename from packages/backend-common/src/util/KubernetesContainerRunner.test.ts rename to packages/backend-common/src/deprecated/util/KubernetesContainerRunner.test.ts diff --git a/packages/backend-common/src/util/KubernetesContainerRunner.ts b/packages/backend-common/src/deprecated/util/KubernetesContainerRunner.ts similarity index 97% rename from packages/backend-common/src/util/KubernetesContainerRunner.ts rename to packages/backend-common/src/deprecated/util/KubernetesContainerRunner.ts index 4b235caf2c..0402f70079 100644 --- a/packages/backend-common/src/util/KubernetesContainerRunner.ts +++ b/packages/backend-common/src/deprecated/util/KubernetesContainerRunner.ts @@ -37,6 +37,7 @@ import { v4 as uuid } from 'uuid'; * Every mount must start with the 'basePath'. * * @public + * @deprecated This type is deprecated and will be removed in a future release. */ export type KubernetesContainerRunnerMountBase = { volumeName: string; @@ -53,6 +54,7 @@ export type KubernetesContainerRunnerMountBase = { * a volume definition named as the {@link KubernetesContainerRunnerMountBase} 'volumeName'. * * @public + * @deprecated This type is deprecated and will be removed in a future release. */ export type KubernetesContainerRunnerOptions = { kubeConfig: KubeConfig; @@ -69,6 +71,7 @@ export type KubernetesContainerRunnerOptions = { * Runs containers leveraging Jobs on a Kubernetes cluster * * @public + * @deprecated This class is deprecated and will be removed in a future release. */ export class KubernetesContainerRunner implements ContainerRunner { private readonly kubeConfig: KubeConfig; diff --git a/packages/backend-common/src/util/index.ts b/packages/backend-common/src/deprecated/util/index.ts similarity index 100% rename from packages/backend-common/src/util/index.ts rename to packages/backend-common/src/deprecated/util/index.ts diff --git a/packages/backend-common/src/discovery/HostDiscovery.ts b/packages/backend-common/src/discovery/HostDiscovery.ts deleted file mode 100644 index 77810b7f6d..0000000000 --- a/packages/backend-common/src/discovery/HostDiscovery.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { HostDiscovery as _HostDiscovery } from '@backstage/backend-app-api'; -import { DiscoveryService } from '@backstage/backend-plugin-api'; - -/** - * @public - * @deprecated Use `DiscoveryService` from `@backstage/backend-plugin-api` instead - */ -export type PluginEndpointDiscovery = DiscoveryService; - -/** - * HostDiscovery is a basic PluginEndpointDiscovery implementation - * that can handle plugins that are hosted in a single or multiple deployments. - * - * The deployment may be scaled horizontally, as long as the external URL - * is the same for all instances. However, internal URLs will always be - * resolved to the same host, so there won't be any balancing of internal traffic. - * - * @public - * @deprecated Please import from `@backstage/backend-defaults/discovery` instead. - */ -export const HostDiscovery = _HostDiscovery; - -/** - * SingleHostDiscovery is a basic PluginEndpointDiscovery implementation - * that assumes that all plugins are hosted in a single deployment. - * - * The deployment may be scaled horizontally, as long as the external URL - * is the same for all instances. However, internal URLs will always be - * resolved to the same host, so there won't be any balancing of internal traffic. - * - * @public - * @deprecated Use `HostDiscovery` from `@backstage/backend-defaults/discovery` instead - */ -export const SingleHostDiscovery = _HostDiscovery; diff --git a/packages/backend-common/src/index.ts b/packages/backend-common/src/index.ts index 87bfa245f6..ad5621b5a9 100644 --- a/packages/backend-common/src/index.ts +++ b/packages/backend-common/src/index.ts @@ -20,18 +20,5 @@ * @packageDocumentation */ -export { legacyPlugin, makeLegacyPlugin } from './legacy'; -export type { LegacyCreateRouter } from './legacy'; -export * from './auth'; -export * from './cache'; -export { loadBackendConfig } from './config'; export * from './deprecated'; -export * from './database'; -export * from './discovery'; -export * from './hot'; -export * from './logging'; -export * from './middleware'; -export * from './reading'; -export * from './service'; -export * from './tokens'; -export * from './util'; +export * from './compat'; diff --git a/packages/backend-common/src/reading/index.ts b/packages/backend-common/src/reading/index.ts deleted file mode 100644 index 0b037ed6c2..0000000000 --- a/packages/backend-common/src/reading/index.ts +++ /dev/null @@ -1,220 +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. - */ - -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { AzureUrlReader as _AzureUrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/AzureUrlReader'; -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { BitbucketCloudUrlReader as _BitbucketCloudUrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/BitbucketCloudUrlReader'; -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { BitbucketUrlReader as _BitbucketUrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader'; -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { BitbucketServerUrlReader as _BitbucketServerUrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/BitbucketServerUrlReader'; -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { GerritUrlReader as _GerritUrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/GerritUrlReader'; -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { GithubUrlReader as _GithubUrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/GithubUrlReader'; -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { GitlabUrlReader as _GitlabUrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/GitlabUrlReader'; -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { GiteaUrlReader as _GiteaUrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/GiteaUrlReader'; -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { HarnessUrlReader as _HarnessUrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/HarnessUrlReader'; -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { AwsS3UrlReader as _AwsS3UrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/AwsS3UrlReader'; -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { FetchUrlReader as _FetchUrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/FetchUrlReader'; -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { UrlReaders as _UrlReaders } from '../../../backend-defaults/src/entrypoints/urlReader/lib/UrlReaders'; -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { ReadUrlResponseFactory as _ReadUrlResponseFactory } from '../../../backend-defaults/src/entrypoints/urlReader/lib/ReadUrlResponseFactory'; -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import type { UrlReadersOptions as _UrlReadersOptions } from '../../../backend-defaults/src/entrypoints/urlReader/lib/UrlReaders'; -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import type { FromReadableArrayOptions as _FromReadableArrayOptions } from '../../../backend-defaults/src/entrypoints/urlReader/lib/types'; -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import type { - ReaderFactory as _ReaderFactory, - ReadTreeResponseFactory as _ReadTreeResponseFactory, - ReadTreeResponseFactoryOptions as _ReadTreeResponseFactoryOptions, - ReadUrlResponseFactoryFromStreamOptions as _ReadUrlResponseFactoryFromStreamOptions, - UrlReaderPredicateTuple as _UrlReaderPredicateTuple, -} from '../../../backend-defaults/src/entrypoints/urlReader/lib/types'; - -import type { - ReadTreeOptions as _ReadTreeOptions, - ReadTreeResponse as _ReadTreeResponse, - ReadTreeResponseFile as _ReadTreeResponseFile, - ReadTreeResponseDirOptions as _ReadTreeResponseDirOptions, - ReadUrlOptions as _ReadUrlOptions, - ReadUrlResponse as _ReadUrlResponse, - SearchOptions as _SearchOptions, - SearchResponse as _SearchResponse, - SearchResponseFile as _SearchResponseFile, - UrlReaderService as _UrlReaderService, -} from '@backstage/backend-plugin-api'; - -/** - * @public - * @deprecated Import from `@backstage/backend-defaults/urlReader` instead - */ -export const AzureUrlReader = _AzureUrlReader; -/** - * @public - * @deprecated Import from `@backstage/backend-defaults/urlReader` instead - */ -export const BitbucketCloudUrlReader = _BitbucketCloudUrlReader; -/** - * @public - * @deprecated Import from `@backstage/backend-defaults/urlReader` instead - */ -export const BitbucketUrlReader = _BitbucketUrlReader; -/** - * @public - * @deprecated Import from `@backstage/backend-defaults/urlReader` instead - */ -export const BitbucketServerUrlReader = _BitbucketServerUrlReader; -/** - * @public - * @deprecated Import from `@backstage/backend-defaults/urlReader` instead - */ -export const GerritUrlReader = _GerritUrlReader; -/** - * @public - * @deprecated Import from `@backstage/backend-defaults/urlReader` instead - */ -export const GithubUrlReader = _GithubUrlReader; -/** - * @public - * @deprecated Import from `@backstage/backend-defaults/urlReader` instead - */ -export const GitlabUrlReader = _GitlabUrlReader; -/** - * @public - * @deprecated Import from `@backstage/backend-defaults/urlReader` instead - */ -export const GiteaUrlReader = _GiteaUrlReader; -/** - * @public - * @deprecated Import from `@backstage/backend-defaults/urlReader` instead - */ -export const HarnessUrlReader = _HarnessUrlReader; -/** - * @public - * @deprecated Import from `@backstage/backend-defaults/urlReader` instead - */ -export const AwsS3UrlReader = _AwsS3UrlReader; -/** - * @public - * @deprecated Import from `@backstage/backend-defaults/urlReader` instead - */ -export const FetchUrlReader = _FetchUrlReader; -/** - * @public - * @deprecated Import from `@backstage/backend-defaults/urlReader` instead - */ -export const UrlReaders = _UrlReaders; -/** - * @public - * @deprecated Import from `@backstage/backend-defaults/urlReader` instead - */ -export const ReadUrlResponseFactory = _ReadUrlResponseFactory; -/** - * @public - * @deprecated Import from `@backstage/backend-defaults/urlReader` instead - */ -export type UrlReadersOptions = _UrlReadersOptions; -/** - * @public - * @deprecated Import from `@backstage/backend-defaults/urlReader` instead - */ -export type FromReadableArrayOptions = _FromReadableArrayOptions; -/** - * @public - * @deprecated Import from `@backstage/backend-defaults/urlReader` instead - */ -export type ReaderFactory = _ReaderFactory; -/** - * @public - * @deprecated Import from `@backstage/backend-defaults/urlReader` instead - */ -export type ReadTreeResponseFactory = _ReadTreeResponseFactory; -/** - * @public - * @deprecated Import from `@backstage/backend-defaults/urlReader` instead - */ -export type ReadTreeResponseFactoryOptions = _ReadTreeResponseFactoryOptions; -/** - * @public - * @deprecated Import from `@backstage/backend-defaults/urlReader` instead - */ -export type ReadUrlResponseFactoryFromStreamOptions = - _ReadUrlResponseFactoryFromStreamOptions; -/** - * @public - * @deprecated Import from `@backstage/backend-defaults/urlReader` instead - */ -export type UrlReaderPredicateTuple = _UrlReaderPredicateTuple; - -/** - * @public - * @deprecated Use `ÙrlReaderReadTreeOptions` from `@backstage/backend-plugin-api` instead - */ -export type ReadTreeOptions = _ReadTreeOptions; -/** - * @public - * @deprecated Use `ÙrlReaderReadTreeResponse` from `@backstage/backend-plugin-api` instead - */ -export type ReadTreeResponse = _ReadTreeResponse; -/** - * @public - * @deprecated Use `ÙrlReaderReadTreeResponseFile` from `@backstage/backend-plugin-api` instead - */ -export type ReadTreeResponseFile = _ReadTreeResponseFile; -/** - * @public - * @deprecated Use `ÙrlReaderReadTreeResponseDirOptions` from `@backstage/backend-plugin-api` instead - */ -export type ReadTreeResponseDirOptions = _ReadTreeResponseDirOptions; -/** - * @public - * @deprecated Use `ÙrlReaderReadUrlOptions` from `@backstage/backend-plugin-api` instead - */ -export type ReadUrlOptions = _ReadUrlOptions; -/** - * @public - * @deprecated Use `ÙrlReaderReadUrlResponse` from `@backstage/backend-plugin-api` instead - */ -export type ReadUrlResponse = _ReadUrlResponse; -/** - * @public - * @deprecated Use `ÙrlReaderSearchOptions` from `@backstage/backend-plugin-api` instead - */ -export type SearchOptions = _SearchOptions; -/** - * @public - * @deprecated Use `ÙrlReaderSearchResponse` from `@backstage/backend-plugin-api` instead - */ -export type SearchResponse = _SearchResponse; -/** - * @public - * @deprecated Use `ÙrlReaderSearchResponseFile` from `@backstage/backend-plugin-api` instead - */ -export type SearchResponseFile = _SearchResponseFile; -/** - * @public - * @deprecated Use `ÙrlReaderService` from `@backstage/backend-plugin-api` instead - */ -export type UrlReader = _UrlReaderService; diff --git a/packages/backend-common/src/util/escapeRegExp.test.ts b/packages/backend-common/src/util/escapeRegExp.test.ts deleted file mode 100644 index 13c6ae4a5a..0000000000 --- a/packages/backend-common/src/util/escapeRegExp.test.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 { escapeRegExp } from './escapeRegExp'; - -describe('escapeRegExp', () => { - test('does not escape non-regex characters', () => { - expect(escapeRegExp('Backstage Backstage')).toBe('Backstage Backstage'); - }); - - test('all the characters', () => { - expect(escapeRegExp('^$\\.*+?()[]{}|')).toBe( - '\\^\\$\\\\\\.\\*\\+\\?\\(\\)\\[\\]\\{\\}\\|', - ); - }); - - test('character: ^', () => { - expect(escapeRegExp('^')).toBe('\\^'); - }); - - test('character: $', () => { - expect(escapeRegExp('$')).toBe('\\$'); - }); - - test('character: \\', () => { - expect(escapeRegExp('\\')).toBe('\\\\'); - }); - - test('character: .', () => { - expect(escapeRegExp('.')).toBe('\\.'); - }); - - test('character: *', () => { - expect(escapeRegExp('*')).toBe('\\*'); - }); - - test('character: +', () => { - expect(escapeRegExp('+')).toBe('\\+'); - }); - - test('character: ?', () => { - expect(escapeRegExp('?')).toBe('\\?'); - }); - - test('character: (', () => { - expect(escapeRegExp('(')).toBe('\\('); - }); - - test('character: )', () => { - expect(escapeRegExp(')')).toBe('\\)'); - }); - - test('character: [', () => { - expect(escapeRegExp('[')).toBe('\\['); - }); - - test('character: ]', () => { - expect(escapeRegExp(']')).toBe('\\]'); - }); - - test('character: {', () => { - expect(escapeRegExp('{')).toBe('\\{'); - }); - - test('character: }', () => { - expect(escapeRegExp('}')).toBe('\\}'); - }); - - test('character: |', () => { - expect(escapeRegExp('|')).toBe('\\|'); - }); -}); diff --git a/packages/backend-defaults/CHANGELOG.md b/packages/backend-defaults/CHANGELOG.md index 7556cbbab8..7e9788756f 100644 --- a/packages/backend-defaults/CHANGELOG.md +++ b/packages/backend-defaults/CHANGELOG.md @@ -1,5 +1,90 @@ # @backstage/backend-defaults +## 0.3.3-next.0 + +### Patch Changes + +- 53ced70: Added a new Root Health Service which adds new endpoints for health checks. +- 083eaf9: Fix bug where ISO durations could no longer be used for schedules +- cb14a05: Repack the package to fix issues with typescript with named exports +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/backend-app-api@0.7.9-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/plugin-events-node@0.3.7-next.0 + - @backstage/plugin-permission-node@0.7.32-next.0 + - @backstage/backend-dev-utils@0.1.4 + - @backstage/cli-common@0.1.14 + - @backstage/config@1.2.0 + - @backstage/config-loader@1.8.1 + - @backstage/errors@1.2.4 + - @backstage/integration-aws-node@0.1.12 + - @backstage/types@1.1.1 + +## 0.3.0 + +### Minor Changes + +- 662dce8: **BREAKING**: The `workdir` argument have been removed from The `GerritUrlReader` constructor. + + **BREAKING**: The Gerrit `readTree` implementation will now only use the Gitiles api. Support + for using git to clone the repo has been removed. + +- 02103be: Deprecated and moved over core services to `@backstage/backend-defaults` + +### Patch Changes + +- 1897169: Exposed `DefaultSchedulerService` +- b5bc997: Refactor cache manager inline types. +- e171620: Remove dependency with `@backstage/backend-commons` package. +- 6551b3d: Added core service factories and implementations from + `@backstage/backend-app-api`. They are now available as subpath exports, e.g. + `@backstage/backend-defaults/scheduler` is where the service factory and default + implementation of `coreServices.scheduler` now lives. They have been marked as + deprecated in their old locations. +- 8aab451: Internal minor refactors of the database connectors +- 0634fdc: Deprecated `dropDatabase` +- b2ee7f3: Moved over all URL reader functionality from `@backstage/backend-common` to `@backstage/backend-defaults/urlReader`. Please update your imports. +- 9539a0b: Added `@backstage/backend-defaults/auth`, `@backstage/backend-defaults/httpAuth`, and `@backstage/backend-defaults/userInfo` to house their respective backend service factories. You should now import these services from those new locations, instead of `@backstage/backend-app-api`. +- Updated dependencies + - @backstage/backend-app-api@0.7.6 + - @backstage/backend-common@0.23.0 + - @backstage/backend-plugin-api@0.6.19 + - @backstage/plugin-auth-node@0.4.14 + - @backstage/integration@1.12.0 + - @backstage/plugin-events-node@0.3.5 + - @backstage/plugin-permission-node@0.7.30 + - @backstage/cli-common@0.1.14 + - @backstage/config-loader@1.8.1 + - @backstage/backend-dev-utils@0.1.4 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/integration-aws-node@0.1.12 + - @backstage/types@1.1.1 + +## 0.3.0-next.3 + +### Patch Changes + +- 1897169: Exposed `DefaultSchedulerService` +- 8aab451: Internal minor refactors of the database connectors +- b2ee7f3: Moved over all URL reader functionality from `@backstage/backend-common` to `@backstage/backend-defaults/urlReader`. Please update your imports. +- Updated dependencies + - @backstage/backend-plugin-api@0.6.19-next.3 + - @backstage/integration@1.12.0-next.1 + - @backstage/plugin-permission-node@0.7.30-next.3 + - @backstage/plugin-events-node@0.3.5-next.2 + - @backstage/backend-common@0.23.0-next.3 + - @backstage/backend-app-api@0.7.6-next.3 + - @backstage/config-loader@1.8.1-next.0 + - @backstage/backend-dev-utils@0.1.4 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/integration-aws-node@0.1.12 + - @backstage/types@1.1.1 + ## 0.3.0-next.2 ### Patch Changes diff --git a/packages/backend-defaults/api-report-auth.md b/packages/backend-defaults/api-report-auth.md new file mode 100644 index 0000000000..d64ce5bc2a --- /dev/null +++ b/packages/backend-defaults/api-report-auth.md @@ -0,0 +1,13 @@ +## API Report File for "@backstage/backend-defaults" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { AuthService } from '@backstage/backend-plugin-api'; +import { ServiceFactory } from '@backstage/backend-plugin-api'; + +// @public +export const authServiceFactory: () => ServiceFactory; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/backend-defaults/api-report-cache.md b/packages/backend-defaults/api-report-cache.md index 2cd2f3efc9..0bfd7eb463 100644 --- a/packages/backend-defaults/api-report-cache.md +++ b/packages/backend-defaults/api-report-cache.md @@ -11,15 +11,10 @@ import { ServiceFactory } from '@backstage/backend-plugin-api'; // @public export class CacheManager { - forPlugin(pluginId: string): { - getClient(options?: CacheServiceOptions): CacheService; - }; + forPlugin(pluginId: string): PluginCacheManager; static fromConfig( config: Config, - options?: { - logger?: LoggerService; - onError?: (err: Error) => void; - }, + options?: CacheManagerOptions, ): CacheManager; } @@ -29,7 +24,7 @@ export type CacheManagerOptions = { onError?: (err: Error) => void; }; -// @public (undocumented) +// @public export const cacheServiceFactory: () => ServiceFactory; // @public (undocumented) diff --git a/packages/backend-defaults/api-report-database.md b/packages/backend-defaults/api-report-database.md index 598a3bd1b0..116830343a 100644 --- a/packages/backend-defaults/api-report-database.md +++ b/packages/backend-defaults/api-report-database.md @@ -7,7 +7,6 @@ import { Config } from '@backstage/config'; import { DatabaseService } from '@backstage/backend-plugin-api'; import { LifecycleService } from '@backstage/backend-plugin-api'; import { LoggerService } from '@backstage/backend-plugin-api'; -import { PluginDatabaseManager } from '@backstage/backend-common'; import { PluginMetadataService } from '@backstage/backend-plugin-api'; import { ServiceFactory } from '@backstage/backend-plugin-api'; @@ -32,9 +31,9 @@ export type DatabaseManagerOptions = { logger?: LoggerService; }; -// @public (undocumented) +// @public export const databaseServiceFactory: () => ServiceFactory< - PluginDatabaseManager, + DatabaseService, 'plugin' >; diff --git a/packages/backend-defaults/api-report-discovery.md b/packages/backend-defaults/api-report-discovery.md index 0ff734b8a7..b434dab6fc 100644 --- a/packages/backend-defaults/api-report-discovery.md +++ b/packages/backend-defaults/api-report-discovery.md @@ -7,7 +7,7 @@ import { Config } from '@backstage/config'; import { DiscoveryService } from '@backstage/backend-plugin-api'; import { ServiceFactory } from '@backstage/backend-plugin-api'; -// @public (undocumented) +// @public export const discoveryServiceFactory: () => ServiceFactory< DiscoveryService, 'plugin' diff --git a/packages/backend-defaults/api-report-httpAuth.md b/packages/backend-defaults/api-report-httpAuth.md new file mode 100644 index 0000000000..6ffe3d6539 --- /dev/null +++ b/packages/backend-defaults/api-report-httpAuth.md @@ -0,0 +1,16 @@ +## API Report File for "@backstage/backend-defaults" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { HttpAuthService } from '@backstage/backend-plugin-api'; +import { ServiceFactory } from '@backstage/backend-plugin-api'; + +// @public +export const httpAuthServiceFactory: () => ServiceFactory< + HttpAuthService, + 'plugin' +>; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/backend-defaults/api-report-httpRouter.md b/packages/backend-defaults/api-report-httpRouter.md new file mode 100644 index 0000000000..a7ca2c8dd3 --- /dev/null +++ b/packages/backend-defaults/api-report-httpRouter.md @@ -0,0 +1,35 @@ +## API Report File for "@backstage/backend-defaults" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { HttpRouterService } from '@backstage/backend-plugin-api'; +import { HumanDuration } from '@backstage/types'; +import { LifecycleService } from '@backstage/backend-plugin-api'; +import { RequestHandler } from 'express'; +import { ServiceFactory } from '@backstage/backend-plugin-api'; + +// @public +export function createLifecycleMiddleware( + options: LifecycleMiddlewareOptions, +): RequestHandler; + +// @public (undocumented) +export interface HttpRouterFactoryOptions { + getPath?(pluginId: string): string; +} + +// @public +export const httpRouterServiceFactory: ( + options?: HttpRouterFactoryOptions | undefined, +) => ServiceFactory; + +// @public +export interface LifecycleMiddlewareOptions { + // (undocumented) + lifecycle: LifecycleService; + startupRequestPauseTimeout?: HumanDuration; +} + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/backend-defaults/api-report-logger.md b/packages/backend-defaults/api-report-logger.md new file mode 100644 index 0000000000..fa9018a40c --- /dev/null +++ b/packages/backend-defaults/api-report-logger.md @@ -0,0 +1,16 @@ +## API Report File for "@backstage/backend-defaults" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { LoggerService } from '@backstage/backend-plugin-api'; +import { ServiceFactory } from '@backstage/backend-plugin-api'; + +// @public +export const loggerServiceFactory: () => ServiceFactory< + LoggerService, + 'plugin' +>; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/backend-defaults/api-report-permissions.md b/packages/backend-defaults/api-report-permissions.md index 9006a62018..c436443ff1 100644 --- a/packages/backend-defaults/api-report-permissions.md +++ b/packages/backend-defaults/api-report-permissions.md @@ -6,7 +6,7 @@ import { PermissionsService } from '@backstage/backend-plugin-api'; import { ServiceFactory } from '@backstage/backend-plugin-api'; -// @public (undocumented) +// @public export const permissionsServiceFactory: () => ServiceFactory< PermissionsService, 'plugin' diff --git a/packages/backend-defaults/api-report-rootConfig.md b/packages/backend-defaults/api-report-rootConfig.md index 60c8fbcb57..317c451e1b 100644 --- a/packages/backend-defaults/api-report-rootConfig.md +++ b/packages/backend-defaults/api-report-rootConfig.md @@ -3,11 +3,21 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import type { Config } from '@backstage/config'; +import { ConfigSchema } from '@backstage/config-loader'; +import { LoggerService } from '@backstage/backend-plugin-api'; import { RemoteConfigSourceOptions } from '@backstage/config-loader'; import { RootConfigService } from '@backstage/backend-plugin-api'; import { ServiceFactory } from '@backstage/backend-plugin-api'; // @public (undocumented) +export function createConfigSecretEnumerator(options: { + logger: LoggerService; + dir?: string; + schema?: ConfigSchema; +}): Promise<(config: Config) => Iterable>; + +// @public export interface RootConfigFactoryOptions { argv?: string[]; remote?: Pick; diff --git a/packages/backend-defaults/api-report-rootHealth.md b/packages/backend-defaults/api-report-rootHealth.md new file mode 100644 index 0000000000..ffa067605a --- /dev/null +++ b/packages/backend-defaults/api-report-rootHealth.md @@ -0,0 +1,16 @@ +## API Report File for "@backstage/backend-defaults" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { RootHealthService } from '@backstage/backend-plugin-api'; +import { ServiceFactory } from '@backstage/backend-plugin-api'; + +// @public (undocumented) +export const rootHealthServiceFactory: () => ServiceFactory< + RootHealthService, + 'root' +>; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/backend-defaults/api-report-rootHttpRouter.md b/packages/backend-defaults/api-report-rootHttpRouter.md new file mode 100644 index 0000000000..d9727fd36d --- /dev/null +++ b/packages/backend-defaults/api-report-rootHttpRouter.md @@ -0,0 +1,149 @@ +## API Report File for "@backstage/backend-defaults" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +/// + +import { Config } from '@backstage/config'; +import { CorsOptions } from 'cors'; +import { ErrorRequestHandler } from 'express'; +import { Express as Express_2 } from 'express'; +import { Handler } from 'express'; +import { HelmetOptions } from 'helmet'; +import * as http from 'http'; +import { LifecycleService } from '@backstage/backend-plugin-api'; +import { LoggerService } from '@backstage/backend-plugin-api'; +import { RequestHandler } from 'express'; +import { RequestListener } from 'http'; +import { RootConfigService } from '@backstage/backend-plugin-api'; +import { RootHttpRouterService } from '@backstage/backend-plugin-api'; +import type { Server } from 'node:http'; +import { ServiceFactory } from '@backstage/backend-plugin-api'; + +// @public +export function createHttpServer( + listener: RequestListener, + options: HttpServerOptions, + deps: { + logger: LoggerService; + }, +): Promise; + +// @public +export class DefaultRootHttpRouter implements RootHttpRouterService { + // (undocumented) + static create(options?: DefaultRootHttpRouterOptions): DefaultRootHttpRouter; + // (undocumented) + handler(): Handler; + // (undocumented) + use(path: string, handler: Handler): void; +} + +// @public +export interface DefaultRootHttpRouterOptions { + indexPath?: string | false; +} + +// @public +export interface ExtendedHttpServer extends http.Server { + // (undocumented) + port(): number; + // (undocumented) + start(): Promise; + // (undocumented) + stop(): Promise; +} + +// @public +export type HttpServerCertificateOptions = + | { + type: 'pem'; + key: string; + cert: string; + } + | { + type: 'generated'; + hostname: string; + }; + +// @public +export type HttpServerOptions = { + listen: { + port: number; + host: string; + }; + https?: { + certificate: HttpServerCertificateOptions; + }; +}; + +// @public +export class MiddlewareFactory { + compression(): RequestHandler; + cors(): RequestHandler; + static create(options: MiddlewareFactoryOptions): MiddlewareFactory; + error(options?: MiddlewareFactoryErrorOptions): ErrorRequestHandler; + helmet(): RequestHandler; + logging(): RequestHandler; + notFound(): RequestHandler; +} + +// @public +export interface MiddlewareFactoryErrorOptions { + logAllErrors?: boolean; + showStackTraces?: boolean; +} + +// @public +export interface MiddlewareFactoryOptions { + // (undocumented) + config: RootConfigService; + // (undocumented) + logger: LoggerService; +} + +// @public +export function readCorsOptions(config?: Config): CorsOptions; + +// @public +export function readHelmetOptions(config?: Config): HelmetOptions; + +// @public +export function readHttpServerOptions(config?: Config): HttpServerOptions; + +// @public (undocumented) +export interface RootHttpRouterConfigureContext { + // (undocumented) + app: Express_2; + // (undocumented) + applyDefaults: () => void; + // (undocumented) + config: RootConfigService; + // (undocumented) + healthRouter: RequestHandler; + // (undocumented) + lifecycle: LifecycleService; + // (undocumented) + logger: LoggerService; + // (undocumented) + middleware: MiddlewareFactory; + // (undocumented) + routes: RequestHandler; + // (undocumented) + server: Server; +} + +// @public +export type RootHttpRouterFactoryOptions = { + indexPath?: string | false; + configure?(context: RootHttpRouterConfigureContext): void; +}; + +// @public (undocumented) +export const rootHttpRouterServiceFactory: ( + options?: RootHttpRouterFactoryOptions | undefined, +) => ServiceFactory; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/backend-defaults/api-report-rootLogger.md b/packages/backend-defaults/api-report-rootLogger.md new file mode 100644 index 0000000000..70dc0deee6 --- /dev/null +++ b/packages/backend-defaults/api-report-rootLogger.md @@ -0,0 +1,54 @@ +## API Report File for "@backstage/backend-defaults" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { Format } from 'logform'; +import { JsonObject } from '@backstage/types'; +import { LoggerService } from '@backstage/backend-plugin-api'; +import { RootLoggerService } from '@backstage/backend-plugin-api'; +import { ServiceFactory } from '@backstage/backend-plugin-api'; +import { transport } from 'winston'; + +// @public +export const rootLoggerServiceFactory: () => ServiceFactory< + RootLoggerService, + 'root' +>; + +// @public +export class WinstonLogger implements RootLoggerService { + // (undocumented) + addRedactions(redactions: Iterable): void; + // (undocumented) + child(meta: JsonObject): LoggerService; + static colorFormat(): Format; + static create(options: WinstonLoggerOptions): WinstonLogger; + // (undocumented) + debug(message: string, meta?: JsonObject): void; + // (undocumented) + error(message: string, meta?: JsonObject): void; + // (undocumented) + info(message: string, meta?: JsonObject): void; + static redacter(): { + format: Format; + add: (redactions: Iterable) => void; + }; + // (undocumented) + warn(message: string, meta?: JsonObject): void; +} + +// @public (undocumented) +export interface WinstonLoggerOptions { + // (undocumented) + format?: Format; + // (undocumented) + level?: string; + // (undocumented) + meta?: JsonObject; + // (undocumented) + transports?: transport[]; +} + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/backend-defaults/api-report-urlReader.md b/packages/backend-defaults/api-report-urlReader.md index d9300d731a..c56cdba69b 100644 --- a/packages/backend-defaults/api-report-urlReader.md +++ b/packages/backend-defaults/api-report-urlReader.md @@ -22,13 +22,13 @@ import { HarnessIntegration } from '@backstage/integration'; import { LoggerService } from '@backstage/backend-plugin-api'; import { Readable } from 'stream'; import { ServiceFactory } from '@backstage/backend-plugin-api'; -import { UrlReaderReadTreeOptions } from '@backstage/backend-plugin-api'; -import { UrlReaderReadTreeResponse } from '@backstage/backend-plugin-api'; -import { UrlReaderReadUrlOptions } from '@backstage/backend-plugin-api'; -import { UrlReaderReadUrlResponse } from '@backstage/backend-plugin-api'; -import { UrlReaderSearchOptions } from '@backstage/backend-plugin-api'; -import { UrlReaderSearchResponse } from '@backstage/backend-plugin-api'; import { UrlReaderService } from '@backstage/backend-plugin-api'; +import { UrlReaderServiceReadTreeOptions } from '@backstage/backend-plugin-api'; +import { UrlReaderServiceReadTreeResponse } from '@backstage/backend-plugin-api'; +import { UrlReaderServiceReadUrlOptions } from '@backstage/backend-plugin-api'; +import { UrlReaderServiceReadUrlResponse } from '@backstage/backend-plugin-api'; +import { UrlReaderServiceSearchOptions } from '@backstage/backend-plugin-api'; +import { UrlReaderServiceSearchResponse } from '@backstage/backend-plugin-api'; // @public export class AwsS3UrlReader implements UrlReaderService { @@ -46,15 +46,15 @@ export class AwsS3UrlReader implements UrlReaderService { // (undocumented) readTree( url: string, - options?: UrlReaderReadTreeOptions, - ): Promise; + options?: UrlReaderServiceReadTreeOptions, + ): Promise; // (undocumented) readUrl( url: string, - options?: UrlReaderReadUrlOptions, - ): Promise; + options?: UrlReaderServiceReadUrlOptions, + ): Promise; // (undocumented) - search(): Promise; + search(): Promise; // (undocumented) toString(): string; } @@ -75,18 +75,18 @@ export class AzureUrlReader implements UrlReaderService { // (undocumented) readTree( url: string, - options?: UrlReaderReadTreeOptions, - ): Promise; + options?: UrlReaderServiceReadTreeOptions, + ): Promise; // (undocumented) readUrl( url: string, - options?: UrlReaderReadUrlOptions, - ): Promise; + options?: UrlReaderServiceReadUrlOptions, + ): Promise; // (undocumented) search( url: string, - options?: UrlReaderSearchOptions, - ): Promise; + options?: UrlReaderServiceSearchOptions, + ): Promise; // (undocumented) toString(): string; } @@ -106,18 +106,18 @@ export class BitbucketCloudUrlReader implements UrlReaderService { // (undocumented) readTree( url: string, - options?: UrlReaderReadTreeOptions, - ): Promise; + options?: UrlReaderServiceReadTreeOptions, + ): Promise; // (undocumented) readUrl( url: string, - options?: UrlReaderReadUrlOptions, - ): Promise; + options?: UrlReaderServiceReadUrlOptions, + ): Promise; // (undocumented) search( url: string, - options?: UrlReaderSearchOptions, - ): Promise; + options?: UrlReaderServiceSearchOptions, + ): Promise; // (undocumented) toString(): string; } @@ -137,18 +137,18 @@ export class BitbucketServerUrlReader implements UrlReaderService { // (undocumented) readTree( url: string, - options?: UrlReaderReadTreeOptions, - ): Promise; + options?: UrlReaderServiceReadTreeOptions, + ): Promise; // (undocumented) readUrl( url: string, - options?: UrlReaderReadUrlOptions, - ): Promise; + options?: UrlReaderServiceReadUrlOptions, + ): Promise; // (undocumented) search( url: string, - options?: UrlReaderSearchOptions, - ): Promise; + options?: UrlReaderServiceSearchOptions, + ): Promise; // (undocumented) toString(): string; } @@ -169,18 +169,18 @@ export class BitbucketUrlReader implements UrlReaderService { // (undocumented) readTree( url: string, - options?: UrlReaderReadTreeOptions, - ): Promise; + options?: UrlReaderServiceReadTreeOptions, + ): Promise; // (undocumented) readUrl( url: string, - options?: UrlReaderReadUrlOptions, - ): Promise; + options?: UrlReaderServiceReadUrlOptions, + ): Promise; // (undocumented) search( url: string, - options?: UrlReaderSearchOptions, - ): Promise; + options?: UrlReaderServiceSearchOptions, + ): Promise; // (undocumented) toString(): string; } @@ -191,14 +191,14 @@ export class FetchUrlReader implements UrlReaderService { // (undocumented) read(url: string): Promise; // (undocumented) - readTree(): Promise; + readTree(): Promise; // (undocumented) readUrl( url: string, - options?: UrlReaderReadUrlOptions, - ): Promise; + options?: UrlReaderServiceReadUrlOptions, + ): Promise; // (undocumented) - search(): Promise; + search(): Promise; // (undocumented) toString(): string; } @@ -217,7 +217,6 @@ export class GerritUrlReader implements UrlReaderService { deps: { treeResponseFactory: ReadTreeResponseFactory; }, - workDir: string, ); // (undocumented) static factory: ReaderFactory; @@ -226,15 +225,15 @@ export class GerritUrlReader implements UrlReaderService { // (undocumented) readTree( url: string, - options?: UrlReaderReadTreeOptions, - ): Promise; + options?: UrlReaderServiceReadTreeOptions, + ): Promise; // (undocumented) readUrl( url: string, - options?: UrlReaderReadUrlOptions, - ): Promise; + options?: UrlReaderServiceReadUrlOptions, + ): Promise; // (undocumented) - search(): Promise; + search(): Promise; // (undocumented) toString(): string; } @@ -254,15 +253,15 @@ export class GiteaUrlReader implements UrlReaderService { // (undocumented) readTree( url: string, - options?: UrlReaderReadTreeOptions, - ): Promise; + options?: UrlReaderServiceReadTreeOptions, + ): Promise; // (undocumented) readUrl( url: string, - options?: UrlReaderReadUrlOptions, - ): Promise; + options?: UrlReaderServiceReadUrlOptions, + ): Promise; // (undocumented) - search(): Promise; + search(): Promise; // (undocumented) toString(): string; } @@ -283,18 +282,18 @@ export class GithubUrlReader implements UrlReaderService { // (undocumented) readTree( url: string, - options?: UrlReaderReadTreeOptions, - ): Promise; + options?: UrlReaderServiceReadTreeOptions, + ): Promise; // (undocumented) readUrl( url: string, - options?: UrlReaderReadUrlOptions, - ): Promise; + options?: UrlReaderServiceReadUrlOptions, + ): Promise; // (undocumented) search( url: string, - options?: UrlReaderSearchOptions, - ): Promise; + options?: UrlReaderServiceSearchOptions, + ): Promise; // (undocumented) toString(): string; } @@ -314,18 +313,18 @@ export class GitlabUrlReader implements UrlReaderService { // (undocumented) readTree( url: string, - options?: UrlReaderReadTreeOptions, - ): Promise; + options?: UrlReaderServiceReadTreeOptions, + ): Promise; // (undocumented) readUrl( url: string, - options?: UrlReaderReadUrlOptions, - ): Promise; + options?: UrlReaderServiceReadUrlOptions, + ): Promise; // (undocumented) search( url: string, - options?: UrlReaderSearchOptions, - ): Promise; + options?: UrlReaderServiceSearchOptions, + ): Promise; // (undocumented) toString(): string; } @@ -345,15 +344,15 @@ export class HarnessUrlReader implements UrlReaderService { // (undocumented) readTree( url: string, - options?: UrlReaderReadTreeOptions, - ): Promise; + options?: UrlReaderServiceReadTreeOptions, + ): Promise; // (undocumented) readUrl( url: string, - options?: UrlReaderReadUrlOptions, - ): Promise; + options?: UrlReaderServiceReadUrlOptions, + ): Promise; // (undocumented) - search(): Promise; + search(): Promise; // (undocumented) toString(): string; } @@ -370,17 +369,17 @@ export interface ReadTreeResponseFactory { // (undocumented) fromReadableArray( options: FromReadableArrayOptions, - ): Promise; + ): Promise; // (undocumented) fromTarArchive( options: ReadTreeResponseFactoryOptions & { stripFirstDirectory?: boolean; }, - ): Promise; + ): Promise; // (undocumented) fromZipArchive( options: ReadTreeResponseFactoryOptions, - ): Promise; + ): Promise; } // @public @@ -401,11 +400,11 @@ export class ReadUrlResponseFactory { static fromNodeJSReadable( oldStyleStream: NodeJS.ReadableStream, options?: ReadUrlResponseFactoryFromStreamOptions, - ): Promise; + ): Promise; static fromReadable( stream: Readable, options?: ReadUrlResponseFactoryFromStreamOptions, - ): Promise; + ): Promise; } // @public @@ -426,7 +425,7 @@ export class UrlReaders { static default(options: UrlReadersOptions): UrlReaderService; } -// @public (undocumented) +// @public export const urlReaderServiceFactory: () => ServiceFactory< UrlReaderService, 'plugin' diff --git a/packages/backend-defaults/api-report-userInfo.md b/packages/backend-defaults/api-report-userInfo.md new file mode 100644 index 0000000000..d11fb69718 --- /dev/null +++ b/packages/backend-defaults/api-report-userInfo.md @@ -0,0 +1,16 @@ +## API Report File for "@backstage/backend-defaults" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { ServiceFactory } from '@backstage/backend-plugin-api'; +import { UserInfoService } from '@backstage/backend-plugin-api'; + +// @public +export const userInfoServiceFactory: () => ServiceFactory< + UserInfoService, + 'plugin' +>; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/backend-defaults/config.d.ts b/packages/backend-defaults/config.d.ts index 569ab436db..ab1e443fc2 100644 --- a/packages/backend-defaults/config.d.ts +++ b/packages/backend-defaults/config.d.ts @@ -15,6 +15,283 @@ */ export interface Config { + backend?: { + /** + * Options used by the default auth, httpAuth and userInfo services. + */ + auth?: { + /** + * This disables the otherwise default auth policy, which requires all + * requests to be authenticated with either user or service credentials. + * + * Disabling this check means that the backend will no longer block + * unauthenticated requests, but instead allow them to pass through to + * plugins. + * + * If permissions are enabled, unauthenticated requests will be treated + * exactly as such, leaving it to the permission policy to determine what + * permissions should be allowed for an unauthenticated identity. Note + * that this will also apply to service-to-service calls between plugins + * unless you configure credentials for service calls. + */ + dangerouslyDisableDefaultAuthPolicy?: boolean; + + /** Controls how to store keys for plugin-to-plugin auth */ + pluginKeyStore?: + | { type: 'database' } + | { + type: 'static'; + static: { + /** + * Must be declared at least once and the first one will be used for signing. + */ + keys: Array<{ + /** + * Path to the public key file in the SPKI format. Should be an absolute path. + */ + publicKeyFile: string; + /** + * Path to the matching private key file in the PKCS#8 format. Should be an absolute path. + * + * The first array entry must specify a private key file, the rest must not. + */ + privateKeyFile?: string; + /** + * ID to uniquely identify this key within the JWK set. + */ + keyId: string; + /** + * JWS "alg" (Algorithm) Header Parameter value. Defaults to ES256. + * Must match the algorithm used to generate the keys in the provided files + */ + algorithm?: string; + }>; + }; + }; + + /** + * Configures methods of external access, ie ways for callers outside of + * the Backstage ecosystem to get authorized for access to APIs that do + * not permit unauthorized access. + */ + externalAccess: Array< + | { + /** + * This is the legacy service-to-service access method, where a set + * of static keys were shared among plugins and used for symmetric + * signing and verification. These correspond to the old + * `backend.auth.keys` set and retain their behavior for backwards + * compatibility. Please migrate to other access methods when + * possible. + * + * Callers generate JWT tokens with the following payload: + * + * ```json + * { + * "sub": "backstage-plugin", + * "exp": + * } + * ``` + * + * And sign them with HS256, using the base64 decoded secret. The + * tokens are then passed along with requests in the Authorization + * header: + * + * ``` + * Authorization: Bearer eyJhbGciOiJIUzI... + * ``` + */ + type: 'legacy'; + options: { + /** + * Any set of base64 encoded random bytes to be used as both the + * signing and verification key. Should be sufficiently long so as + * not to be easy to guess by brute force. + * + * Can be generated eg using + * + * ```sh + * node -p 'require("crypto").randomBytes(24).toString("base64")' + * ``` + * + * @visibility secret + */ + secret: string; + + /** + * Sets the subject of the principal, when matching this token. + * Useful for debugging and tracking purposes. + */ + subject: string; + }; + /** + * Restricts what types of access that are permitted for this access + * method. If no access restrictions are given, it'll have unlimited + * access. This access restriction applies for the framework level; + * individual plugins may have their own access control mechanisms + * on top of this. + */ + accessRestrictions?: Array<{ + /** + * Permit access to make requests to this plugin. + * + * Can be further refined by setting additional fields below. + */ + plugin: string; + /** + * If given, this method is limited to only performing actions + * with these named permissions in this plugin. + * + * Note that this only applies where permissions checks are + * enabled in the first place. Endpoints that are not protected by + * the permissions system at all, are not affected by this + * setting. + */ + permission?: string | Array; + /** + * If given, this method is limited to only performing actions + * whose permissions have these attributes. + * + * Note that this only applies where permissions checks are + * enabled in the first place. Endpoints that are not protected by + * the permissions system at all, are not affected by this + * setting. + */ + permissionAttribute?: { + /** + * One of more of 'create', 'read', 'update', or 'delete'. + */ + action?: string | Array; + }; + }>; + } + | { + /** + * This access method consists of random static tokens that can be + * handed out to callers. + * + * The tokens are then passed along verbatim with requests in the + * Authorization header: + * + * ``` + * Authorization: Bearer eZv5o+fW3KnR3kVabMW4ZcDNLPl8nmMW + * ``` + */ + type: 'static'; + options: { + /** + * A raw token that can be any string, but for security reasons + * should be sufficiently long so as not to be easy to guess by + * brute force. + * + * Can be generated eg using + * + * ```sh + * node -p 'require("crypto").randomBytes(24).toString("base64")' + * ``` + * + * Since the tokens can be any string, you are free to add + * additional identifying data to them if you like. For example, + * adding a `freben-local-dev-` prefix for debugging purposes to a + * token that you know will be handed out for use as a personal + * access token during development. + * + * @visibility secret + */ + token: string; + + /** + * Sets the subject of the principal, when matching this token. + * Useful for debugging and tracking purposes. + */ + subject: string; + }; + /** + * Restricts what types of access that are permitted for this access + * method. If no access restrictions are given, it'll have unlimited + * access. This access restriction applies for the framework level; + * individual plugins may have their own access control mechanisms + * on top of this. + */ + accessRestrictions?: Array<{ + /** + * Permit access to make requests to this plugin. + * + * Can be further refined by setting additional fields below. + */ + plugin: string; + /** + * If given, this method is limited to only performing actions + * with these named permissions in this plugin. + * + * Note that this only applies where permissions checks are + * enabled in the first place. Endpoints that are not protected by + * the permissions system at all, are not affected by this + * setting. + */ + permission?: string | Array; + /** + * If given, this method is limited to only performing actions + * whose permissions have these attributes. + * + * Note that this only applies where permissions checks are + * enabled in the first place. Endpoints that are not protected by + * the permissions system at all, are not affected by this + * setting. + */ + permissionAttribute?: { + /** + * One of more of 'create', 'read', 'update', or 'delete'. + */ + action?: string | Array; + }; + }>; + } + | { + /** + * This access method consists of a JWKS endpoint that can be used to + * verify JWT tokens. + * + * Callers generate JWT tokens via 3rd party tooling + * and pass them in the Authorization header: + * + * ``` + * Authorization: Bearer eZv5o+fW3KnR3kVabMW4ZcDNLPl8nmMW + * ``` + */ + type: 'jwks'; + options: { + /** + * The full URL of the JWKS endpoint. + */ + url: string; + /** + * Sets the algorithm(s) that should be used to verify the JWT tokens. + * The passed JWTs must have been signed using one of the listed algorithms. + */ + algorithm?: string | string[]; + /** + * Sets the issuer(s) that should be used to verify the JWT tokens. + * Passed JWTs must have an `iss` claim which matches one of the specified issuers. + */ + issuer?: string | string[]; + /** + * Sets the audience(s) that should be used to verify the JWT tokens. + * The passed JWTs must have an "aud" claim that matches one of the audiences specified, + * or have no audience specified. + */ + audience?: string | string[]; + /** + * Sets an optional subject prefix. Passes the subject to called plugins. + * Useful for debugging and tracking purposes. + */ + subjectPrefix?: string; + }; + } + >; + }; + }; + /** * Options used by the default discovery service. */ diff --git a/packages/backend-app-api/migrations/20240327104803_public_keys.js b/packages/backend-defaults/migrations/auth/20240327104803_public_keys.js similarity index 100% rename from packages/backend-app-api/migrations/20240327104803_public_keys.js rename to packages/backend-defaults/migrations/auth/20240327104803_public_keys.js diff --git a/packages/backend-defaults/package.json b/packages/backend-defaults/package.json index 19d0781e7e..376aa9d36f 100644 --- a/packages/backend-defaults/package.json +++ b/packages/backend-defaults/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/backend-defaults", - "version": "0.3.0-next.2", + "version": "0.3.3-next.0", "description": "Backend defaults used by Backstage backend apps", "backstage": { "role": "node-library" @@ -20,21 +20,32 @@ "license": "Apache-2.0", "exports": { ".": "./src/index.ts", + "./auth": "./src/entrypoints/auth/index.ts", "./cache": "./src/entrypoints/cache/index.ts", "./database": "./src/entrypoints/database/index.ts", "./discovery": "./src/entrypoints/discovery/index.ts", + "./httpAuth": "./src/entrypoints/httpAuth/index.ts", + "./httpRouter": "./src/entrypoints/httpRouter/index.ts", "./lifecycle": "./src/entrypoints/lifecycle/index.ts", + "./logger": "./src/entrypoints/logger/index.ts", "./permissions": "./src/entrypoints/permissions/index.ts", "./rootConfig": "./src/entrypoints/rootConfig/index.ts", + "./rootHealth": "./src/entrypoints/rootHealth/index.ts", + "./rootHttpRouter": "./src/entrypoints/rootHttpRouter/index.ts", "./rootLifecycle": "./src/entrypoints/rootLifecycle/index.ts", + "./rootLogger": "./src/entrypoints/rootLogger/index.ts", "./scheduler": "./src/entrypoints/scheduler/index.ts", "./urlReader": "./src/entrypoints/urlReader/index.ts", + "./userInfo": "./src/entrypoints/userInfo/index.ts", "./package.json": "./package.json" }, "main": "src/index.ts", "types": "src/index.ts", "typesVersions": { "*": { + "auth": [ + "src/entrypoints/auth/index.ts" + ], "cache": [ "src/entrypoints/cache/index.ts" ], @@ -44,24 +55,45 @@ "discovery": [ "src/entrypoints/discovery/index.ts" ], + "httpAuth": [ + "src/entrypoints/httpAuth/index.ts" + ], + "httpRouter": [ + "src/entrypoints/httpRouter/index.ts" + ], "lifecycle": [ "src/entrypoints/lifecycle/index.ts" ], + "logger": [ + "src/entrypoints/logger/index.ts" + ], "permissions": [ "src/entrypoints/permissions/index.ts" ], "rootConfig": [ "src/entrypoints/rootConfig/index.ts" ], + "rootHealth": [ + "src/entrypoints/rootHealth/index.ts" + ], + "rootHttpRouter": [ + "src/entrypoints/rootHttpRouter/index.ts" + ], "rootLifecycle": [ "src/entrypoints/rootLifecycle/index.ts" ], + "rootLogger": [ + "src/entrypoints/rootLogger/index.ts" + ], "scheduler": [ "src/entrypoints/scheduler/index.ts" ], "urlReader": [ "src/entrypoints/urlReader/index.ts" ], + "userInfo": [ + "src/entrypoints/userInfo/index.ts" + ], "package.json": [ "package.json" ] @@ -91,40 +123,62 @@ "@backstage/backend-common": "workspace:^", "@backstage/backend-dev-utils": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", + "@backstage/cli-common": "workspace:^", "@backstage/config": "workspace:^", "@backstage/config-loader": "workspace:^", "@backstage/errors": "workspace:^", "@backstage/integration": "workspace:^", "@backstage/integration-aws-node": "workspace:^", + "@backstage/plugin-auth-node": "workspace:^", "@backstage/plugin-events-node": "workspace:^", "@backstage/plugin-permission-node": "workspace:^", "@backstage/types": "workspace:^", "@google-cloud/storage": "^7.0.0", "@keyv/memcache": "^1.3.5", "@keyv/redis": "^2.5.3", + "@manypkg/get-packages": "^1.1.3", "@octokit/rest": "^19.0.3", "@opentelemetry/api": "^1.3.0", + "@types/cors": "^2.8.6", + "@types/express": "^4.17.6", "archiver": "^6.0.0", "base64-stream": "^1.0.0", "better-sqlite3": "^9.0.0", + "compression": "^1.7.4", "concat-stream": "^2.0.0", + "cookie": "^0.6.0", + "cors": "^2.8.5", "cron": "^3.0.0", + "express": "^4.17.1", + "express-promise-router": "^4.1.0", "fs-extra": "^11.2.0", "git-url-parse": "^14.0.0", + "helmet": "^6.0.0", "isomorphic-git": "^1.23.0", + "jose": "^5.0.0", "keyv": "^4.5.2", "knex": "^3.0.0", "lodash": "^4.17.21", + "logform": "^2.3.2", "luxon": "^3.0.0", "minimatch": "^9.0.0", + "minimist": "^1.2.5", + "morgan": "^1.10.0", "mysql2": "^3.0.0", "node-fetch": "^2.6.7", + "node-forge": "^1.3.1", "p-limit": "^3.1.0", + "path-to-regexp": "^6.2.1", "pg": "^8.11.3", "pg-connection-string": "^2.3.0", "raw-body": "^2.4.1", + "selfsigned": "^2.0.0", + "stoppable": "^1.1.0", "tar": "^6.1.12", + "triple-beam": "^1.4.1", "uuid": "^9.0.0", + "winston": "^3.2.1", + "winston-transport": "^4.5.0", "yauzl": "^3.0.0", "yn": "^4.0.0", "zod": "^3.22.4" @@ -134,8 +188,14 @@ "@backstage/backend-plugin-api": "workspace:^", "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", + "@types/http-errors": "^2.0.0", + "@types/morgan": "^1.9.0", + "@types/node-forge": "^1.3.0", + "@types/stoppable": "^1.1.0", "aws-sdk-client-mock": "^4.0.0", + "http-errors": "^2.0.0", "msw": "^1.0.0", + "supertest": "^6.1.3", "wait-for-expect": "^3.0.2" }, "configSchema": "config.d.ts" diff --git a/packages/backend-defaults/src/CreateBackend.ts b/packages/backend-defaults/src/CreateBackend.ts index 823b3c2833..e3195748a6 100644 --- a/packages/backend-defaults/src/CreateBackend.ts +++ b/packages/backend-defaults/src/CreateBackend.ts @@ -16,26 +16,27 @@ import { Backend, - authServiceFactory, createSpecializedBackend, - httpAuthServiceFactory, - httpRouterServiceFactory, identityServiceFactory, - loggerServiceFactory, - rootHttpRouterServiceFactory, - rootLoggerServiceFactory, tokenManagerServiceFactory, - userInfoServiceFactory, } from '@backstage/backend-app-api'; +import { authServiceFactory } from '@backstage/backend-defaults/auth'; import { cacheServiceFactory } from '@backstage/backend-defaults/cache'; import { databaseServiceFactory } from '@backstage/backend-defaults/database'; import { discoveryServiceFactory } from '@backstage/backend-defaults/discovery'; +import { httpAuthServiceFactory } from '@backstage/backend-defaults/httpAuth'; +import { httpRouterServiceFactory } from '@backstage/backend-defaults/httpRouter'; import { lifecycleServiceFactory } from '@backstage/backend-defaults/lifecycle'; +import { loggerServiceFactory } from '@backstage/backend-defaults/logger'; import { permissionsServiceFactory } from '@backstage/backend-defaults/permissions'; import { rootConfigServiceFactory } from '@backstage/backend-defaults/rootConfig'; +import { rootHealthServiceFactory } from '@backstage/backend-defaults/rootHealth'; +import { rootHttpRouterServiceFactory } from '@backstage/backend-defaults/rootHttpRouter'; import { rootLifecycleServiceFactory } from '@backstage/backend-defaults/rootLifecycle'; +import { rootLoggerServiceFactory } from '@backstage/backend-defaults/rootLogger'; import { schedulerServiceFactory } from '@backstage/backend-defaults/scheduler'; import { urlReaderServiceFactory } from '@backstage/backend-defaults/urlReader'; +import { userInfoServiceFactory } from '@backstage/backend-defaults/userInfo'; import { eventsServiceFactory } from '@backstage/plugin-events-node'; export const defaultServiceFactories = [ @@ -50,6 +51,7 @@ export const defaultServiceFactories = [ lifecycleServiceFactory(), loggerServiceFactory(), permissionsServiceFactory(), + rootHealthServiceFactory(), rootHttpRouterServiceFactory(), rootLifecycleServiceFactory(), rootLoggerServiceFactory(), diff --git a/packages/backend-app-api/src/services/implementations/auth/DefaultAuthService.ts b/packages/backend-defaults/src/entrypoints/auth/DefaultAuthService.ts similarity index 93% rename from packages/backend-app-api/src/services/implementations/auth/DefaultAuthService.ts rename to packages/backend-defaults/src/entrypoints/auth/DefaultAuthService.ts index b4feb46cce..159da79435 100644 --- a/packages/backend-app-api/src/services/implementations/auth/DefaultAuthService.ts +++ b/packages/backend-defaults/src/entrypoints/auth/DefaultAuthService.ts @@ -27,15 +27,15 @@ import { AuthenticationError, ForwardedError } from '@backstage/errors'; import { JsonObject } from '@backstage/types'; import { decodeJwt } from 'jose'; import { ExternalTokenHandler } from './external/ExternalTokenHandler'; -import { PluginTokenHandler } from './plugin/PluginTokenHandler'; -import { UserTokenHandler } from './user/UserTokenHandler'; import { createCredentialsWithNonePrincipal, createCredentialsWithServicePrincipal, createCredentialsWithUserPrincipal, toInternalBackstageCredentials, } from './helpers'; -import { KeyStore } from './types'; +import { PluginTokenHandler } from './plugin/PluginTokenHandler'; +import { PluginKeySource } from './plugin/keys/types'; +import { UserTokenHandler } from './user/UserTokenHandler'; /** @internal */ export class DefaultAuthService implements AuthService { @@ -46,11 +46,15 @@ export class DefaultAuthService implements AuthService { private readonly tokenManager: TokenManager, private readonly pluginId: string, private readonly disableDefaultAuthPolicy: boolean, - private readonly publicKeyStore: KeyStore, + private readonly pluginKeySource: PluginKeySource, ) {} - // allowLimitedAccess is currently ignored, since we currently always use the full user tokens - async authenticate(token: string): Promise { + async authenticate( + token: string, + options?: { + allowLimitedAccess?: boolean; + }, + ): Promise { const pluginResult = await this.pluginTokenHandler.verifyToken(token); if (pluginResult) { if (pluginResult.limitedUserToken) { @@ -73,6 +77,13 @@ export class DefaultAuthService implements AuthService { const userResult = await this.userTokenHandler.verifyToken(token); if (userResult) { + if ( + !options?.allowLimitedAccess && + this.userTokenHandler.isLimitedUserToken(token) + ) { + throw new AuthenticationError('Illegal limited user token'); + } + return createCredentialsWithUserPrincipal( userResult.userEntityRef, token, @@ -209,7 +220,7 @@ export class DefaultAuthService implements AuthService { } async listPublicServiceKeys(): Promise<{ keys: JsonObject[] }> { - const { keys } = await this.publicKeyStore.listKeys(); + const { keys } = await this.pluginKeySource.listKeys(); return { keys: keys.map(({ key }) => key) }; } diff --git a/packages/backend-app-api/src/services/implementations/auth/JwksClient.ts b/packages/backend-defaults/src/entrypoints/auth/JwksClient.ts similarity index 100% rename from packages/backend-app-api/src/services/implementations/auth/JwksClient.ts rename to packages/backend-defaults/src/entrypoints/auth/JwksClient.ts diff --git a/packages/backend-app-api/src/services/implementations/auth/authServiceFactory.test.ts b/packages/backend-defaults/src/entrypoints/auth/authServiceFactory.test.ts similarity index 89% rename from packages/backend-app-api/src/services/implementations/auth/authServiceFactory.test.ts rename to packages/backend-defaults/src/entrypoints/auth/authServiceFactory.test.ts index 71fbe64963..22357d0f49 100644 --- a/packages/backend-app-api/src/services/implementations/auth/authServiceFactory.test.ts +++ b/packages/backend-defaults/src/entrypoints/auth/authServiceFactory.test.ts @@ -19,6 +19,7 @@ import { mockServices, setupRequestMockHandlers, } from '@backstage/backend-test-utils'; +import { tokenManagerServiceFactory } from '@backstage/backend-app-api'; import { authServiceFactory } from './authServiceFactory'; import { base64url, decodeJwt } from 'jose'; import { discoveryServiceFactory } from '../discovery'; @@ -26,7 +27,6 @@ import { BackstageServicePrincipal, BackstageUserPrincipal, } from '@backstage/backend-plugin-api'; -import { tokenManagerServiceFactory } from '../tokenManager'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; import { InternalBackstageCredentials } from './types'; @@ -218,6 +218,17 @@ describe('authServiceFactory', () => { }); it('should issue limited user tokens', async () => { + /* Corresponding private key in case this test needs to be updated in the future: + { + kty: 'EC', + x: 'c9cPvv_S7zETBKDlAa3oOjr7RvyUueIYIak0TRph7mg', + y: 'bKaxDRAWgmEJ9Ix8e85blH_IsnbQxX31x0oQTVwLZ2c', + crv: 'P-256', + d: '2eJlhCDdGx9fxKDL1D9BnY3CCTEKxL60Bkms0hmubmY', + kid: '8d01c3db-56f9-45f0-86dd-05b3c835b3d3', + alg: 'ES256' + } + */ server.use( rest.get( 'http://localhost:7007/api/auth/.well-known/jwks.json', @@ -227,8 +238,8 @@ describe('authServiceFactory', () => { keys: [ { kty: 'EC', - x: '78-Ei1H3nKM23ZpGMMzte2mVoYCcnfnSiLTm1P7vZM0', - y: 'Z9-PjG_EU598tLLUc2f8sCqxT7bjs8WpoV-lHm9GJHY', + x: 'c9cPvv_S7zETBKDlAa3oOjr7RvyUueIYIak0TRph7mg', + y: 'bKaxDRAWgmEJ9Ix8e85blH_IsnbQxX31x0oQTVwLZ2c', crv: 'P-256', kid: '8d01c3db-56f9-45f0-86dd-05b3c835b3d3', alg: 'ES256', @@ -253,7 +264,7 @@ describe('authServiceFactory', () => { const catalogAuth = await tester.get('catalog'); const fullToken = - 'eyJ0eXAiOiJ2bmQuYmFja3N0YWdlLnVzZXIiLCJhbGciOiJFUzI1NiIsImtpZCI6IjhkMDFjM2RiLTU2ZjktNDVmMC04NmRkLTA1YjNjODM1YjNkMyJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjcwMDcvYXBpL2F1dGgiLCJzdWIiOiJ1c2VyOmRldmVsb3BtZW50L2d1ZXN0IiwiZW50IjpbInVzZXI6ZGV2ZWxvcG1lbnQvZ3Vlc3QiLCJncm91cDpkZWZhdWx0L3RlYW0tYSJdLCJhdWQiOiJiYWNrc3RhZ2UiLCJpYXQiOjE3MTIwNzE3MTQsImV4cCI6MTcxMjA3NTMxNCwidWlwIjoiMDFBUUJfSWpHTXRWc2gyWmgzZEg1NXhOX29pSVlhQ1F3ODJjeDZ5M1BQMXlpTjM4eGMzMVpMS2U0YVNDQlJTTy10cjFzZFUzT29ELUxJYV8tNV9RVUEifQ.mjIrZGqbZ2t68fS4U3crlGw-bYJZnMlhMHf-YL7q_u1HfaLr4NMTcHkxdnNS2wfJxCmUBxRfUS8b3nSAKsxcHA'; + 'eyJ0eXAiOiJ2bmQuYmFja3N0YWdlLnVzZXIiLCJhbGciOiJFUzI1NiIsImtpZCI6IjhkMDFjM2RiLTU2ZjktNDVmMC04NmRkLTA1YjNjODM1YjNkMyJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjcwMDcvYXBpL2F1dGgiLCJzdWIiOiJ1c2VyOmRldmVsb3BtZW50L2d1ZXN0IiwiZW50IjpbInVzZXI6ZGV2ZWxvcG1lbnQvZ3Vlc3QiLCJncm91cDpkZWZhdWx0L3RlYW0tYSJdLCJhdWQiOiJiYWNrc3RhZ2UiLCJpYXQiOjE3MTIwNzE3MTQsImV4cCI6MTcxMjA3NTMxNCwidWlwIjoiSmwxVEpycG9VUjR1NENjUE9nalJMeHpEMi1FMGZPR3ptSm81UWI2eS1aN19meG5oVVBEdWVWRE1CS0l6WF9pc0lvSDhlZm9EUFA5bG9aQnpPblB5Z2cifQ.1gVMq1ofO8PzRctu72D6c4IMqXuIabT79WdGEhW6vIrBRs_qhuWAa94Wvz_KYKpBTb2nxgzXJ5OeddeoYApMyQ'; const credentials = await catalogAuth.authenticate(fullToken); if (!catalogAuth.isPrincipal(credentials, 'user')) { @@ -275,7 +286,6 @@ describe('authServiceFactory', () => { const expectedTokenPayload = base64url.encode( JSON.stringify({ sub: 'user:development/guest', - ent: ['user:development/guest', 'group:default/team-a'], iat: expectedIssuedAt, exp: expectedExpiresAt, }), @@ -312,6 +322,17 @@ describe('authServiceFactory', () => { const catalogAuth = await tester.get('catalog'); const permissionAuth = await tester.get('permission'); + /* Corresponding private key in case this test needs to be updated in the future: + { + kty: 'EC', + x: 'c9cPvv_S7zETBKDlAa3oOjr7RvyUueIYIak0TRph7mg', + y: 'bKaxDRAWgmEJ9Ix8e85blH_IsnbQxX31x0oQTVwLZ2c', + crv: 'P-256', + d: '2eJlhCDdGx9fxKDL1D9BnY3CCTEKxL60Bkms0hmubmY', + kid: '8d01c3db-56f9-45f0-86dd-05b3c835b3d3', + alg: 'ES256' + } + */ server.use( rest.get( 'http://localhost:7007/api/auth/.well-known/jwks.json', @@ -321,8 +342,8 @@ describe('authServiceFactory', () => { keys: [ { kty: 'EC', - x: '78-Ei1H3nKM23ZpGMMzte2mVoYCcnfnSiLTm1P7vZM0', - y: 'Z9-PjG_EU598tLLUc2f8sCqxT7bjs8WpoV-lHm9GJHY', + x: 'c9cPvv_S7zETBKDlAa3oOjr7RvyUueIYIak0TRph7mg', + y: 'bKaxDRAWgmEJ9Ix8e85blH_IsnbQxX31x0oQTVwLZ2c', crv: 'P-256', kid: '8d01c3db-56f9-45f0-86dd-05b3c835b3d3', alg: 'ES256', @@ -360,7 +381,7 @@ describe('authServiceFactory', () => { }); const fullToken = - 'eyJ0eXAiOiJ2bmQuYmFja3N0YWdlLnVzZXIiLCJhbGciOiJFUzI1NiIsImtpZCI6IjhkMDFjM2RiLTU2ZjktNDVmMC04NmRkLTA1YjNjODM1YjNkMyJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjcwMDcvYXBpL2F1dGgiLCJzdWIiOiJ1c2VyOmRldmVsb3BtZW50L2d1ZXN0IiwiZW50IjpbInVzZXI6ZGV2ZWxvcG1lbnQvZ3Vlc3QiLCJncm91cDpkZWZhdWx0L3RlYW0tYSJdLCJhdWQiOiJiYWNrc3RhZ2UiLCJpYXQiOjE3MTIwNzE3MTQsImV4cCI6MTcxMjA3NTMxNCwidWlwIjoiMDFBUUJfSWpHTXRWc2gyWmgzZEg1NXhOX29pSVlhQ1F3ODJjeDZ5M1BQMXlpTjM4eGMzMVpMS2U0YVNDQlJTTy10cjFzZFUzT29ELUxJYV8tNV9RVUEifQ.mjIrZGqbZ2t68fS4U3crlGw-bYJZnMlhMHf-YL7q_u1HfaLr4NMTcHkxdnNS2wfJxCmUBxRfUS8b3nSAKsxcHA'; + 'eyJ0eXAiOiJ2bmQuYmFja3N0YWdlLnVzZXIiLCJhbGciOiJFUzI1NiIsImtpZCI6IjhkMDFjM2RiLTU2ZjktNDVmMC04NmRkLTA1YjNjODM1YjNkMyJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjcwMDcvYXBpL2F1dGgiLCJzdWIiOiJ1c2VyOmRldmVsb3BtZW50L2d1ZXN0IiwiZW50IjpbInVzZXI6ZGV2ZWxvcG1lbnQvZ3Vlc3QiLCJncm91cDpkZWZhdWx0L3RlYW0tYSJdLCJhdWQiOiJiYWNrc3RhZ2UiLCJpYXQiOjE3MTIwNzE3MTQsImV4cCI6MTcxMjA3NTMxNCwidWlwIjoiSmwxVEpycG9VUjR1NENjUE9nalJMeHpEMi1FMGZPR3ptSm81UWI2eS1aN19meG5oVVBEdWVWRE1CS0l6WF9pc0lvSDhlZm9EUFA5bG9aQnpPblB5Z2cifQ.1gVMq1ofO8PzRctu72D6c4IMqXuIabT79WdGEhW6vIrBRs_qhuWAa94Wvz_KYKpBTb2nxgzXJ5OeddeoYApMyQ'; const credentials = await searchAuth.authenticate(fullToken); if (!searchAuth.isPrincipal(credentials, 'user')) { diff --git a/packages/backend-defaults/src/entrypoints/auth/authServiceFactory.ts b/packages/backend-defaults/src/entrypoints/auth/authServiceFactory.ts new file mode 100644 index 0000000000..e275e2be00 --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/auth/authServiceFactory.ts @@ -0,0 +1,93 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + coreServices, + createServiceFactory, +} from '@backstage/backend-plugin-api'; +import { DefaultAuthService } from './DefaultAuthService'; +import { ExternalTokenHandler } from './external/ExternalTokenHandler'; +import { PluginTokenHandler } from './plugin/PluginTokenHandler'; +import { createPluginKeySource } from './plugin/keys/createPluginKeySource'; +import { UserTokenHandler } from './user/UserTokenHandler'; + +/** + * Handles token authentication and credentials management. + * + * See {@link @backstage/code-plugin-api#AuthService} + * and {@link https://backstage.io/docs/backend-system/core-services/auth | the service docs} + * for more information. + * + * @public + */ +export const authServiceFactory = createServiceFactory({ + service: coreServices.auth, + deps: { + config: coreServices.rootConfig, + logger: coreServices.rootLogger, + discovery: coreServices.discovery, + plugin: coreServices.pluginMetadata, + database: coreServices.database, + // Re-using the token manager makes sure that we use the same generated keys for + // development as plugins that have not yet been migrated. It's important that this + // keeps working as long as there are plugins that have not been migrated to the + // new auth services in the new backend system. + tokenManager: coreServices.tokenManager, + }, + async factory({ config, discovery, plugin, tokenManager, logger, database }) { + const disableDefaultAuthPolicy = + config.getOptionalBoolean( + 'backend.auth.dangerouslyDisableDefaultAuthPolicy', + ) ?? false; + + const keyDuration = { hours: 1 }; + + const keySource = await createPluginKeySource({ + config, + database, + logger, + keyDuration, + }); + + const userTokens = UserTokenHandler.create({ + discovery, + }); + + const pluginTokens = PluginTokenHandler.create({ + ownPluginId: plugin.getId(), + logger, + keySource, + keyDuration, + discovery, + }); + + const externalTokens = ExternalTokenHandler.create({ + ownPluginId: plugin.getId(), + config, + logger, + }); + + return new DefaultAuthService( + userTokens, + pluginTokens, + externalTokens, + tokenManager, + plugin.getId(), + disableDefaultAuthPolicy, + keySource, + ); + }, +}); diff --git a/packages/backend-app-api/src/services/implementations/auth/external/ExternalTokenHandler.test.ts b/packages/backend-defaults/src/entrypoints/auth/external/ExternalTokenHandler.test.ts similarity index 100% rename from packages/backend-app-api/src/services/implementations/auth/external/ExternalTokenHandler.test.ts rename to packages/backend-defaults/src/entrypoints/auth/external/ExternalTokenHandler.test.ts diff --git a/packages/backend-app-api/src/services/implementations/auth/external/ExternalTokenHandler.ts b/packages/backend-defaults/src/entrypoints/auth/external/ExternalTokenHandler.ts similarity index 100% rename from packages/backend-app-api/src/services/implementations/auth/external/ExternalTokenHandler.ts rename to packages/backend-defaults/src/entrypoints/auth/external/ExternalTokenHandler.ts diff --git a/packages/backend-app-api/src/services/implementations/auth/external/helpers.test.ts b/packages/backend-defaults/src/entrypoints/auth/external/helpers.test.ts similarity index 100% rename from packages/backend-app-api/src/services/implementations/auth/external/helpers.test.ts rename to packages/backend-defaults/src/entrypoints/auth/external/helpers.test.ts diff --git a/packages/backend-app-api/src/services/implementations/auth/external/helpers.ts b/packages/backend-defaults/src/entrypoints/auth/external/helpers.ts similarity index 100% rename from packages/backend-app-api/src/services/implementations/auth/external/helpers.ts rename to packages/backend-defaults/src/entrypoints/auth/external/helpers.ts diff --git a/packages/backend-app-api/src/services/implementations/auth/external/jwks.test.ts b/packages/backend-defaults/src/entrypoints/auth/external/jwks.test.ts similarity index 100% rename from packages/backend-app-api/src/services/implementations/auth/external/jwks.test.ts rename to packages/backend-defaults/src/entrypoints/auth/external/jwks.test.ts diff --git a/packages/backend-app-api/src/services/implementations/auth/external/jwks.ts b/packages/backend-defaults/src/entrypoints/auth/external/jwks.ts similarity index 100% rename from packages/backend-app-api/src/services/implementations/auth/external/jwks.ts rename to packages/backend-defaults/src/entrypoints/auth/external/jwks.ts diff --git a/packages/backend-app-api/src/services/implementations/auth/external/legacy.test.ts b/packages/backend-defaults/src/entrypoints/auth/external/legacy.test.ts similarity index 100% rename from packages/backend-app-api/src/services/implementations/auth/external/legacy.test.ts rename to packages/backend-defaults/src/entrypoints/auth/external/legacy.test.ts diff --git a/packages/backend-app-api/src/services/implementations/auth/external/legacy.ts b/packages/backend-defaults/src/entrypoints/auth/external/legacy.ts similarity index 100% rename from packages/backend-app-api/src/services/implementations/auth/external/legacy.ts rename to packages/backend-defaults/src/entrypoints/auth/external/legacy.ts diff --git a/packages/backend-app-api/src/services/implementations/auth/external/static.test.ts b/packages/backend-defaults/src/entrypoints/auth/external/static.test.ts similarity index 100% rename from packages/backend-app-api/src/services/implementations/auth/external/static.test.ts rename to packages/backend-defaults/src/entrypoints/auth/external/static.test.ts diff --git a/packages/backend-app-api/src/services/implementations/auth/external/static.ts b/packages/backend-defaults/src/entrypoints/auth/external/static.ts similarity index 100% rename from packages/backend-app-api/src/services/implementations/auth/external/static.ts rename to packages/backend-defaults/src/entrypoints/auth/external/static.ts diff --git a/packages/backend-app-api/src/services/implementations/auth/external/types.ts b/packages/backend-defaults/src/entrypoints/auth/external/types.ts similarity index 100% rename from packages/backend-app-api/src/services/implementations/auth/external/types.ts rename to packages/backend-defaults/src/entrypoints/auth/external/types.ts diff --git a/packages/backend-app-api/src/services/implementations/auth/helpers.ts b/packages/backend-defaults/src/entrypoints/auth/helpers.ts similarity index 100% rename from packages/backend-app-api/src/services/implementations/auth/helpers.ts rename to packages/backend-defaults/src/entrypoints/auth/helpers.ts diff --git a/packages/backend-common/src/tokens/types.ts b/packages/backend-defaults/src/entrypoints/auth/index.ts similarity index 81% rename from packages/backend-common/src/tokens/types.ts rename to packages/backend-defaults/src/entrypoints/auth/index.ts index 4e0fd698df..1b55d46a83 100644 --- a/packages/backend-common/src/tokens/types.ts +++ b/packages/backend-defaults/src/entrypoints/auth/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2021 The Backstage Authors + * Copyright 2024 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,4 +14,4 @@ * limitations under the License. */ -export type { TokenManagerService as TokenManager } from '@backstage/backend-plugin-api'; +export { authServiceFactory } from './authServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/auth/plugin/PluginTokenHandler.test.ts b/packages/backend-defaults/src/entrypoints/auth/plugin/PluginTokenHandler.test.ts similarity index 55% rename from packages/backend-app-api/src/services/implementations/auth/plugin/PluginTokenHandler.test.ts rename to packages/backend-defaults/src/entrypoints/auth/plugin/PluginTokenHandler.test.ts index 424e01660f..ce470eff04 100644 --- a/packages/backend-app-api/src/services/implementations/auth/plugin/PluginTokenHandler.test.ts +++ b/packages/backend-defaults/src/entrypoints/auth/plugin/PluginTokenHandler.test.ts @@ -19,23 +19,36 @@ import { PluginTokenHandler } from './PluginTokenHandler'; import { decodeJwt } from 'jose'; describe('PluginTokenHandler', () => { + const mockPublicKey = { + kty: 'EC', + x: 'GHlwg744e8JekzukPTdtix6R868D6fcWy0ooOx-NEZI', + y: 'Lyujcm0M6X9_yQi3l1eH09z0brU8K9cwrLml_fRFKro', + crv: 'P-256', + kid: 'mock', + alg: 'ES256', + }; + const mockPrivateKey = { + ...mockPublicKey, + d: 'KEn_mDqXYbZdRHb-JnCrW53LDOv5x4NL1FnlKcqBsFI', + }; + beforeEach(() => { jest.useRealTimers(); }); - it('issues token with correct expiration of token and generated key', async () => { + it('runs issueToken', async () => { jest.useFakeTimers({ now: new Date(0), }); - const addKeyMock = jest.fn(); + const getKeyMock = jest.fn(async () => mockPrivateKey); const handler = PluginTokenHandler.create({ discovery: mockServices.discovery(), keyDuration: { seconds: 10 }, logger: mockServices.logger.mock(), ownPluginId: 'test', - publicKeyStore: { - addKey: addKeyMock, + keySource: { + getPrivateSigningKey: getKeyMock, listKeys: jest.fn(), }, }); @@ -45,38 +58,13 @@ describe('PluginTokenHandler', () => { targetPluginId: 'other', }); const payload = decodeJwt(token); - expect(payload.iat).toBe(0); - expect(payload.exp).toBe(10); - - expect(addKeyMock).toHaveBeenCalledTimes(1); - expect(addKeyMock).toHaveBeenCalledWith({ - id: expect.any(String), - key: expect.any(Object), - expiresAt: new Date(30_000), + expect(payload).toMatchObject({ + iat: 0, + exp: 10, + sub: 'test', + aud: 'other', }); - jest.advanceTimersByTime(5_000); - await handler.issueToken({ - pluginId: 'test', - targetPluginId: 'other', - }); - expect(addKeyMock).toHaveBeenCalledTimes(1); - - jest.advanceTimersByTime(10_000); - await handler.issueToken({ - pluginId: 'test', - targetPluginId: 'other', - }); - expect(addKeyMock).toHaveBeenCalledTimes(2); - - expect(addKeyMock.mock.calls[0][0].id).not.toBe( - addKeyMock.mock.calls[1][0].id, - ); - - expect(addKeyMock).toHaveBeenNthCalledWith(2, { - id: expect.any(String), - key: expect.any(Object), - expiresAt: new Date(45_000), - }); + expect(getKeyMock).toHaveBeenCalledTimes(1); }); }); diff --git a/packages/backend-app-api/src/services/implementations/auth/plugin/PluginTokenHandler.ts b/packages/backend-defaults/src/entrypoints/auth/plugin/PluginTokenHandler.ts similarity index 68% rename from packages/backend-app-api/src/services/implementations/auth/plugin/PluginTokenHandler.ts rename to packages/backend-defaults/src/entrypoints/auth/plugin/PluginTokenHandler.ts index fef33907a5..a401469fdc 100644 --- a/packages/backend-app-api/src/services/implementations/auth/plugin/PluginTokenHandler.ts +++ b/packages/backend-defaults/src/entrypoints/auth/plugin/PluginTokenHandler.ts @@ -15,51 +15,36 @@ */ import { DiscoveryService, LoggerService } from '@backstage/backend-plugin-api'; -import { - decodeJwt, - exportJWK, - generateKeyPair, - JWK, - importJWK, - SignJWT, - decodeProtectedHeader, -} from 'jose'; -import { v4 as uuid } from 'uuid'; -import { InternalKey, KeyStore } from '../types'; +import { decodeJwt, importJWK, SignJWT, decodeProtectedHeader } from 'jose'; import { AuthenticationError } from '@backstage/errors'; import { jwtVerify } from 'jose'; import { tokenTypes } from '@backstage/plugin-auth-node'; import { JwksClient } from '../JwksClient'; import { HumanDuration, durationToMilliseconds } from '@backstage/types'; +import { PluginKeySource } from './keys/types'; -/** - * The margin for how many times longer we make the public key available - * compared to how long we use the private key to sign new tokens. - */ -const KEY_EXPIRATION_MARGIN_FACTOR = 3; const SECONDS_IN_MS = 1000; const ALLOWED_PLUGIN_ID_PATTERN = /^[a-z0-9_-]+$/i; type Options = { ownPluginId: string; - publicKeyStore: KeyStore; + keyDuration: HumanDuration; + keySource: PluginKeySource; discovery: DiscoveryService; logger: LoggerService; - /** Expiration time of signing keys */ - keyDuration: HumanDuration; - /** JWS "alg" (Algorithm) Header Parameter value. Defaults to ES256. + /** + * JWS "alg" (Algorithm) Header Parameter value. Defaults to ES256. * Must match one of the algorithms defined for IdentityClient. * When setting a different algorithm, check if the `key` field * of the `signing_keys` table can fit the length of the generated keys. * If not, add a knex migration file in the migrations folder. - * More info on supported algorithms: https://github.com/panva/jose */ + * More info on supported algorithms: https://github.com/panva/jose + */ algorithm?: string; }; export class PluginTokenHandler { - private privateKeyPromise?: Promise; - private keyExpiry?: Date; private jwksMap = new Map(); // Tracking state for isTargetPluginSupported @@ -70,9 +55,9 @@ export class PluginTokenHandler { return new PluginTokenHandler( options.logger, options.ownPluginId, - options.publicKeyStore, - Math.round(durationToMilliseconds(options.keyDuration) / 1000), + options.keySource, options.algorithm ?? 'ES256', + Math.round(durationToMilliseconds(options.keyDuration) / 1000), options.discovery, ); } @@ -80,9 +65,9 @@ export class PluginTokenHandler { private constructor( private readonly logger: LoggerService, private readonly ownPluginId: string, - private readonly publicKeyStore: KeyStore, - private readonly keyDurationSeconds: number, + private readonly keySource: PluginKeySource, private readonly algorithm: string, + private readonly keyDurationSeconds: number, private readonly discovery: DiscoveryService, ) {} @@ -132,7 +117,7 @@ export class PluginTokenHandler { onBehalfOf?: { token: string; expiresAt: Date }; }): Promise<{ token: string }> { const { pluginId, targetPluginId, onBehalfOf } = options; - const key = await this.getKey(); + const key = await this.keySource.getPrivateSigningKey(); const sub = pluginId; const aud = targetPluginId; @@ -229,65 +214,4 @@ export class PluginTokenHandler { this.jwksMap.set(pluginId, newClient); return newClient; } - - private async getKey(): Promise { - // Make sure that we only generate one key at a time - if (this.privateKeyPromise) { - if (this.keyExpiry && this.keyExpiry.getTime() > Date.now()) { - return this.privateKeyPromise; - } - this.logger.info(`Signing key has expired, generating new key`); - delete this.privateKeyPromise; - } - - this.keyExpiry = new Date( - Date.now() + this.keyDurationSeconds * SECONDS_IN_MS, - ); - - const promise = (async () => { - // This generates a new signing key to be used to sign tokens until the next key rotation - const kid = uuid(); - const key = await generateKeyPair(this.algorithm); - const publicKey = await exportJWK(key.publicKey); - const privateKey = await exportJWK(key.privateKey); - publicKey.kid = privateKey.kid = kid; - publicKey.alg = privateKey.alg = this.algorithm; - - // We're not allowed to use the key until it has been successfully stored - // TODO: some token verification implementations aggressively cache the list of keys, and - // don't attempt to fetch new ones even if they encounter an unknown kid. Therefore we - // may want to keep using the existing key for some period of time until we switch to - // the new one. This also needs to be implemented cross-service though, meaning new services - // that boot up need to be able to grab an existing key to use for signing. - this.logger.info(`Created new signing key ${kid}`); - - await this.publicKeyStore.addKey({ - id: kid, - key: publicKey as InternalKey, - expiresAt: new Date( - Date.now() + - this.keyDurationSeconds * - SECONDS_IN_MS * - KEY_EXPIRATION_MARGIN_FACTOR, - ), - }); - - // At this point we are allowed to start using the new key - return privateKey; - })(); - - this.privateKeyPromise = promise; - - try { - // If we fail to generate a new key, we need to clear the state so that - // the next caller will try to generate another key. - await promise; - } catch (error) { - this.logger.error(`Failed to generate new signing key, ${error}`); - delete this.keyExpiry; - delete this.privateKeyPromise; - } - - return promise; - } } diff --git a/packages/backend-app-api/src/services/implementations/auth/DatabaseKeyStore.test.ts b/packages/backend-defaults/src/entrypoints/auth/plugin/keys/DatabaseKeyStore.test.ts similarity index 99% rename from packages/backend-app-api/src/services/implementations/auth/DatabaseKeyStore.test.ts rename to packages/backend-defaults/src/entrypoints/auth/plugin/keys/DatabaseKeyStore.test.ts index 136017efdb..551cccaf73 100644 --- a/packages/backend-app-api/src/services/implementations/auth/DatabaseKeyStore.test.ts +++ b/packages/backend-defaults/src/entrypoints/auth/plugin/keys/DatabaseKeyStore.test.ts @@ -34,6 +34,8 @@ const testKey2 = { n: 'test', }; +jest.setTimeout(60_000); + describe('DatabaseKeyStore', () => { const databases = TestDatabases.create(); diff --git a/packages/backend-app-api/src/services/implementations/auth/DatabaseKeyStore.ts b/packages/backend-defaults/src/entrypoints/auth/plugin/keys/DatabaseKeyStore.ts similarity index 98% rename from packages/backend-app-api/src/services/implementations/auth/DatabaseKeyStore.ts rename to packages/backend-defaults/src/entrypoints/auth/plugin/keys/DatabaseKeyStore.ts index 5bf9244707..9f5c278a9c 100644 --- a/packages/backend-app-api/src/services/implementations/auth/DatabaseKeyStore.ts +++ b/packages/backend-defaults/src/entrypoints/auth/plugin/keys/DatabaseKeyStore.ts @@ -19,12 +19,13 @@ import { LoggerService, resolvePackagePath, } from '@backstage/backend-plugin-api'; -import { DateTime } from 'luxon'; -import { Knex } from 'knex'; import { JsonObject } from '@backstage/types'; +import { Knex } from 'knex'; +import { DateTime } from 'luxon'; import { KeyStore } from './types'; const MIGRATIONS_TABLE = 'backstage_backend_public_keys__knex_migrations'; + /** @internal */ export const TABLE = 'backstage_backend_public_keys__keys'; @@ -36,8 +37,8 @@ type Row = { export function applyDatabaseMigrations(knex: Knex): Promise { const migrationsDir = resolvePackagePath( - '@backstage/backend-app-api', - 'migrations', + '@backstage/backend-defaults', + 'migrations/auth', ); return knex.migrate.latest({ diff --git a/packages/backend-defaults/src/entrypoints/auth/plugin/keys/DatabasePluginKeySource.test.ts b/packages/backend-defaults/src/entrypoints/auth/plugin/keys/DatabasePluginKeySource.test.ts new file mode 100644 index 0000000000..7a51700a7f --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/auth/plugin/keys/DatabasePluginKeySource.test.ts @@ -0,0 +1,77 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { mockServices } from '@backstage/backend-test-utils'; +import { DatabasePluginKeySource } from './DatabasePluginKeySource'; + +describe('DatabasePluginKeySource', () => { + beforeEach(() => { + jest.useRealTimers(); + }); + + it('issues token with correct expiration of token and generated key', async () => { + jest.useFakeTimers({ + now: new Date(0), + }); + + const keyStore = { + addKey: jest.fn(), + listKeys: jest.fn(), + }; + + const source = new DatabasePluginKeySource( + keyStore, + mockServices.logger.mock(), + 10, + 'ES256', + ); + + const key = await source.getPrivateSigningKey(); + expect(key).toMatchObject({ + alg: 'ES256', + d: expect.any(String), + }); + + expect(keyStore.addKey).toHaveBeenCalledTimes(1); + expect(keyStore.addKey).toHaveBeenCalledWith({ + id: expect.any(String), + key: expect.any(Object), + expiresAt: new Date(30_000), + }); + + jest.advanceTimersByTime(5_000); + + let newKey = await source.getPrivateSigningKey(); + expect(keyStore.addKey).toHaveBeenCalledTimes(1); + expect(newKey).toBe(key); + + jest.advanceTimersByTime(10_000); + + newKey = await source.getPrivateSigningKey(); + expect(keyStore.addKey).toHaveBeenCalledTimes(2); + expect(newKey).not.toBe(key); + + expect(keyStore.addKey.mock.calls[0][0].id).not.toBe( + keyStore.addKey.mock.calls[1][0].id, + ); + + expect(keyStore.addKey).toHaveBeenNthCalledWith(2, { + id: expect.any(String), + key: expect.any(Object), + expiresAt: new Date(45_000), + }); + }); +}); diff --git a/packages/backend-defaults/src/entrypoints/auth/plugin/keys/DatabasePluginKeySource.ts b/packages/backend-defaults/src/entrypoints/auth/plugin/keys/DatabasePluginKeySource.ts new file mode 100644 index 0000000000..37cb1aeb5c --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/auth/plugin/keys/DatabasePluginKeySource.ts @@ -0,0 +1,127 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { DatabaseService, LoggerService } from '@backstage/backend-plugin-api'; +import { HumanDuration, durationToMilliseconds } from '@backstage/types'; +import { JWK, exportJWK, generateKeyPair } from 'jose'; +import { v4 as uuid } from 'uuid'; +import { DatabaseKeyStore } from './DatabaseKeyStore'; +import { InternalKey, KeyPayload, KeyStore } from './types'; +import { PluginKeySource } from './types'; + +const SECONDS_IN_MS = 1000; + +/** + * The margin for how many times longer we make the public key available + * compared to how long we use the private key to sign new tokens. + */ +const KEY_EXPIRATION_MARGIN_FACTOR = 3; + +export class DatabasePluginKeySource implements PluginKeySource { + private privateKeyPromise?: Promise; + private keyExpiry?: Date; + + constructor( + private readonly keyStore: KeyStore, + private readonly logger: LoggerService, + private readonly keyDurationSeconds: number, + private readonly algorithm: string, + ) {} + + public static async create(options: { + logger: LoggerService; + database: DatabaseService; + keyDuration: HumanDuration; + algorithm?: string; + }): Promise { + const keyStore = await DatabaseKeyStore.create({ + database: options.database, + logger: options.logger, + }); + + return new DatabasePluginKeySource( + keyStore, + options.logger, + Math.round(durationToMilliseconds(options.keyDuration) / 1000), + options.algorithm ?? 'ES256', + ); + } + + async getPrivateSigningKey(): Promise { + // Make sure that we only generate one key at a time + if (this.privateKeyPromise) { + if (this.keyExpiry && this.keyExpiry.getTime() > Date.now()) { + return this.privateKeyPromise; + } + this.logger.info(`Signing key has expired, generating new key`); + delete this.privateKeyPromise; + } + + this.keyExpiry = new Date( + Date.now() + this.keyDurationSeconds * SECONDS_IN_MS, + ); + + const promise = (async () => { + // This generates a new signing key to be used to sign tokens until the next key rotation + const kid = uuid(); + const key = await generateKeyPair(this.algorithm); + const publicKey = await exportJWK(key.publicKey); + const privateKey = await exportJWK(key.privateKey); + publicKey.kid = privateKey.kid = kid; + publicKey.alg = privateKey.alg = this.algorithm; + + // We're not allowed to use the key until it has been successfully stored + // TODO: some token verification implementations aggressively cache the list of keys, and + // don't attempt to fetch new ones even if they encounter an unknown kid. Therefore we + // may want to keep using the existing key for some period of time until we switch to + // the new one. This also needs to be implemented cross-service though, meaning new services + // that boot up need to be able to grab an existing key to use for signing. + this.logger.info(`Created new signing key ${kid}`); + + await this.keyStore.addKey({ + id: kid, + key: publicKey as InternalKey, + expiresAt: new Date( + Date.now() + + this.keyDurationSeconds * + SECONDS_IN_MS * + KEY_EXPIRATION_MARGIN_FACTOR, + ), + }); + + // At this point we are allowed to start using the new key + return privateKey; + })(); + + this.privateKeyPromise = promise; + + try { + // If we fail to generate a new key, we need to clear the state so that + // the next caller will try to generate another key. + await promise; + } catch (error) { + this.logger.error(`Failed to generate new signing key, ${error}`); + delete this.keyExpiry; + delete this.privateKeyPromise; + } + + return promise; + } + + listKeys(): Promise<{ keys: KeyPayload[] }> { + return this.keyStore.listKeys(); + } +} diff --git a/packages/backend-defaults/src/entrypoints/auth/plugin/keys/StaticConfigPluginKeySource.test.ts b/packages/backend-defaults/src/entrypoints/auth/plugin/keys/StaticConfigPluginKeySource.test.ts new file mode 100644 index 0000000000..4b3260cb79 --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/auth/plugin/keys/StaticConfigPluginKeySource.test.ts @@ -0,0 +1,124 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { StaticConfigPluginKeySource } from './StaticConfigPluginKeySource'; +import { ConfigReader } from '@backstage/config'; +import { createMockDirectory } from '@backstage/backend-test-utils'; + +const privateKey = ` +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgR8Ja2ppMEgOm1KeY +Kpje00U1luybndt6yC263vcgeKqhRANCAAS+slUrS9JXgtHB1RcDnmlveuu4H3Zm +hQRjvYdO+Mg/3FJss6FaExESTzhPSr3X+be/exarkTMchbDXNEdCKwpn +-----END PRIVATE KEY----- +`.trim(); + +const publicKey = ` +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEvrJVK0vSV4LRwdUXA55pb3rruB92 +ZoUEY72HTvjIP9xSbLOhWhMREk84T0q91/m3v3sWq5EzHIWw1zRHQisKZw== +-----END PUBLIC KEY----- +`.trim(); + +describe('StaticConfigPluginKeySource', () => { + const mockDir = createMockDirectory({ + content: { + 'public.pem': publicKey, + 'private.pem': privateKey, + }, + }); + const publicKeyPath = mockDir.resolve('public.pem'); + const privateKeyPath = mockDir.resolve('private.pem'); + + it('should provide keys from disk', async () => { + const staticKeyStore = await StaticConfigPluginKeySource.create({ + sourceConfig: new ConfigReader({ + type: 'static', + static: { + keys: [ + { + publicKeyFile: publicKeyPath, + privateKeyFile: privateKeyPath, + keyId: '1', + algorithm: 'ES256', + }, + { + // intentionally only private key + // skipping explicit alg + publicKeyFile: publicKeyPath, + keyId: '2', + }, + ], + }, + }), + keyDuration: { hours: 1 }, + }); + + const keys = await staticKeyStore.listKeys(); + expect(keys.keys.length).toEqual(2); + expect(keys.keys[0].key).toMatchObject({ + kid: '1', + alg: 'ES256', + }); + expect(keys.keys[1].key).toMatchObject({ + kid: '2', + alg: 'ES256', + }); + + const pk = await staticKeyStore.getPrivateSigningKey(); + expect(pk).toMatchObject({ + kid: '1', + alg: 'ES256', + }); + expect(pk.d).toBeDefined(); + }); + + it('throws an error for misconfigurations', async () => { + await expect( + StaticConfigPluginKeySource.create({ + sourceConfig: new ConfigReader({ + type: 'static', + static: { + keys: [], + }, + }), + keyDuration: { hours: 1 }, + }), + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"At least one key pair must be provided in static.keys, when the static key store type is used"`, + ); + + await expect( + StaticConfigPluginKeySource.create({ + sourceConfig: new ConfigReader({ + type: 'static', + static: { + keys: [ + { + publicKeyFile: publicKeyPath, + keyId: '1', + algorithm: 'ES256', + }, + ], + }, + }), + keyDuration: { hours: 1 }, + }), + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Private key for signing must be provided in the first key pair in static.keys, when the static key store type is used"`, + ); + }); +}); diff --git a/packages/backend-defaults/src/entrypoints/auth/plugin/keys/StaticConfigPluginKeySource.ts b/packages/backend-defaults/src/entrypoints/auth/plugin/keys/StaticConfigPluginKeySource.ts new file mode 100644 index 0000000000..658a88a368 --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/auth/plugin/keys/StaticConfigPluginKeySource.ts @@ -0,0 +1,183 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Config } from '@backstage/config'; +import { HumanDuration, durationToMilliseconds } from '@backstage/types'; +import { promises as fs } from 'fs'; +import { JWK, exportJWK, importPKCS8, importSPKI } from 'jose'; +import { KeyLike } from 'jose/dist/types/types'; +import { KeyPayload } from './types'; +import { PluginKeySource } from './types'; + +export type KeyPair = { + publicKey: JWK; + privateKey?: JWK; + keyId: string; +}; + +export type StaticKeyConfig = { + publicKeyFile: string; + privateKeyFile?: string; + keyId: string; + algorithm: string; +}; + +const DEFAULT_ALGORITHM = 'ES256'; + +const SECONDS_IN_MS = 1000; + +/** + * Key source that loads predefined public/private key pairs from disk. + * + * The private key should be represented using the PKCS#8 format, + * while the public key should be in the SPKI format. + * + * @remarks + * + * You can generate a public and private key pair, using + * openssl: + * + * Generate a private key using the ES256 algorithm + * ```sh + * openssl ecparam -name prime256v1 -genkey -out private.ec.key + * ``` + * Convert it to PKCS#8 format + * ```sh + * openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in private.ec.key -out private.key + * ``` + * Extract the public key + * ```sh + * openssl ec -inform PEM -outform PEM -pubout -in private.key -out public.key + * ``` + * + * Provide the paths to private.key and public.key as the respective + * private and public key paths in the `create` method. + */ +export class StaticConfigPluginKeySource implements PluginKeySource { + private constructor( + private readonly keyPairs: KeyPair[], + private readonly keyDurationSeconds: number, + ) {} + + public static async create(options: { + sourceConfig: Config; + keyDuration: HumanDuration; + }): Promise { + const keyConfigs = options.sourceConfig + .getConfigArray('static.keys') + .map(c => { + const staticKeyConfig: StaticKeyConfig = { + publicKeyFile: c.getString('publicKeyFile'), + privateKeyFile: c.getOptionalString('privateKeyFile'), + keyId: c.getString('keyId'), + algorithm: c.getOptionalString('algorithm') ?? DEFAULT_ALGORITHM, + }; + + return staticKeyConfig; + }); + + const keyPairs = await Promise.all( + keyConfigs.map(async k => await this.loadKeyPair(k)), + ); + + if (keyPairs.length < 1) { + throw new Error( + 'At least one key pair must be provided in static.keys, when the static key store type is used', + ); + } else if (!keyPairs[0].privateKey) { + throw new Error( + 'Private key for signing must be provided in the first key pair in static.keys, when the static key store type is used', + ); + } + + return new StaticConfigPluginKeySource( + keyPairs, + durationToMilliseconds(options.keyDuration) / SECONDS_IN_MS, + ); + } + + async getPrivateSigningKey(): Promise { + return this.keyPairs[0].privateKey!; + } + + async listKeys(): Promise<{ keys: KeyPayload[] }> { + const keys = this.keyPairs.map(k => this.keyPairToStoredKey(k)); + return { keys }; + } + + private static async loadKeyPair(options: StaticKeyConfig): Promise { + const algorithm = options.algorithm; + const keyId = options.keyId; + const publicKey = await this.loadPublicKeyFromFile( + options.publicKeyFile, + keyId, + algorithm, + ); + const privateKey = options.privateKeyFile + ? await this.loadPrivateKeyFromFile( + options.privateKeyFile, + keyId, + algorithm, + ) + : undefined; + + return { publicKey, privateKey, keyId }; + } + + private static async loadPublicKeyFromFile( + path: string, + keyId: string, + algorithm: string, + ): Promise { + return this.loadKeyFromFile(path, keyId, algorithm, importSPKI); + } + + private static async loadPrivateKeyFromFile( + path: string, + keyId: string, + algorithm: string, + ): Promise { + return this.loadKeyFromFile(path, keyId, algorithm, importPKCS8); + } + + private static async loadKeyFromFile( + path: string, + keyId: string, + algorithm: string, + importer: (content: string, algorithm: string) => Promise, + ): Promise { + const content = await fs.readFile(path, { encoding: 'utf8', flag: 'r' }); + const key = await importer(content, algorithm); + const jwk = await exportJWK(key); + jwk.kid = keyId; + jwk.alg = algorithm; + + return jwk; + } + + private keyPairToStoredKey(keyPair: KeyPair): KeyPayload { + const publicKey = { + ...keyPair.publicKey, + kid: keyPair.keyId, + }; + + return { + key: publicKey, + id: keyPair.keyId, + expiresAt: new Date(Date.now() + this.keyDurationSeconds * SECONDS_IN_MS), + }; + } +} diff --git a/packages/backend-defaults/src/entrypoints/auth/plugin/keys/createPluginKeySource.test.ts b/packages/backend-defaults/src/entrypoints/auth/plugin/keys/createPluginKeySource.test.ts new file mode 100644 index 0000000000..68ac322da5 --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/auth/plugin/keys/createPluginKeySource.test.ts @@ -0,0 +1,170 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { createPluginKeySource } from './createPluginKeySource'; +import { + TestDatabases, + createMockDirectory, + mockServices, +} from '@backstage/backend-test-utils'; +import { ConfigReader } from '@backstage/config'; + +jest.setTimeout(60_000); + +describe('createPluginKeySource', () => { + const databases = TestDatabases.create(); + const mockDir = createMockDirectory(); + + it.each(databases.eachSupportedId())( + 'works for implicit database (no config), %p', + async databaseId => { + const knex = await databases.init(databaseId); + + const getClient = jest.fn(async () => knex); + + const source = await createPluginKeySource({ + config: new ConfigReader({}), + database: mockServices.database.mock({ getClient }), + logger: mockServices.logger.mock(), + keyDuration: { seconds: 10 }, + }); + + expect(getClient).toHaveBeenCalled(); + + const key = await source.getPrivateSigningKey(); + expect(key).toMatchObject({ + alg: 'ES256', + d: expect.any(String), + }); + + const keys = await source.listKeys(); + expect(keys).toEqual({ + keys: [ + expect.objectContaining({ + id: key.kid, + key: expect.objectContaining({ + kid: key.kid, + }), + }), + ], + }); + }, + ); + + it.each(databases.eachSupportedId())( + 'works for explicit database, %p', + async databaseId => { + const knex = await databases.init(databaseId); + + const getClient = jest.fn(async () => knex); + + const source = await createPluginKeySource({ + config: new ConfigReader({ + backend: { auth: { pluginKeyStore: { type: 'database' } } }, + }), + database: mockServices.database.mock({ getClient }), + logger: mockServices.logger.mock(), + keyDuration: { seconds: 10 }, + }); + + expect(getClient).toHaveBeenCalled(); + + const key = await source.getPrivateSigningKey(); + expect(key).toMatchObject({ + alg: 'ES256', + d: expect.any(String), + }); + + const keys = await source.listKeys(); + expect(keys).toEqual({ + keys: [ + expect.objectContaining({ + id: key.kid, + key: expect.objectContaining({ + kid: key.kid, + }), + }), + ], + }); + }, + ); + + it('works for static', async () => { + const privateKey = ` + -----BEGIN PRIVATE KEY----- + MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgR8Ja2ppMEgOm1KeY + Kpje00U1luybndt6yC263vcgeKqhRANCAAS+slUrS9JXgtHB1RcDnmlveuu4H3Zm + hQRjvYdO+Mg/3FJss6FaExESTzhPSr3X+be/exarkTMchbDXNEdCKwpn + -----END PRIVATE KEY----- + `.trim(); + + const publicKey = ` + -----BEGIN PUBLIC KEY----- + MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEvrJVK0vSV4LRwdUXA55pb3rruB92 + ZoUEY72HTvjIP9xSbLOhWhMREk84T0q91/m3v3sWq5EzHIWw1zRHQisKZw== + -----END PUBLIC KEY----- + `.trim(); + + mockDir.setContent({ + 'public.pem': publicKey, + 'private.pem': privateKey, + }); + const publicKeyPath = mockDir.resolve('public.pem'); + const privateKeyPath = mockDir.resolve('private.pem'); + + const getClient = jest.fn(); + + const source = await createPluginKeySource({ + config: new ConfigReader({ + backend: { + auth: { + pluginKeyStore: { + type: 'static', + static: { + keys: [ + { + publicKeyFile: publicKeyPath, + privateKeyFile: privateKeyPath, + keyId: '1', + }, + ], + }, + }, + }, + }, + }), + database: mockServices.database.mock({ getClient }), + logger: mockServices.logger.mock(), + keyDuration: { seconds: 10 }, + }); + + expect(getClient).not.toHaveBeenCalled(); + + const keys = await source.listKeys(); + expect(keys.keys.length).toEqual(1); + expect(keys.keys[0].key).toMatchObject({ + kid: '1', + alg: 'ES256', + }); + + const pk = await source.getPrivateSigningKey(); + expect(pk).toMatchObject({ + kid: '1', + alg: 'ES256', + d: expect.any(String), + }); + }); +}); diff --git a/packages/backend-defaults/src/entrypoints/auth/plugin/keys/createPluginKeySource.ts b/packages/backend-defaults/src/entrypoints/auth/plugin/keys/createPluginKeySource.ts new file mode 100644 index 0000000000..08cd1115a5 --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/auth/plugin/keys/createPluginKeySource.ts @@ -0,0 +1,56 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + DatabaseService, + LoggerService, + RootConfigService, +} from '@backstage/backend-plugin-api'; +import { HumanDuration } from '@backstage/types'; +import { DatabasePluginKeySource } from './DatabasePluginKeySource'; +import { StaticConfigPluginKeySource } from './StaticConfigPluginKeySource'; +import { PluginKeySource } from './types'; + +const CONFIG_ROOT_KEY = 'backend.auth.pluginKeyStore'; + +export async function createPluginKeySource(options: { + config: RootConfigService; + database: DatabaseService; + logger: LoggerService; + keyDuration: HumanDuration; + algorithm?: string; +}): Promise { + const keyStoreConfig = options.config.getOptionalConfig(CONFIG_ROOT_KEY); + const type = keyStoreConfig?.getOptionalString('type') ?? 'database'; + + if (!keyStoreConfig || type === 'database') { + return DatabasePluginKeySource.create({ + database: options.database, + logger: options.logger, + keyDuration: options.keyDuration, + algorithm: options.algorithm, + }); + } else if (type === 'static') { + return StaticConfigPluginKeySource.create({ + sourceConfig: keyStoreConfig, + keyDuration: options.keyDuration, + }); + } + + throw new Error( + `Unsupported config value ${CONFIG_ROOT_KEY}.type '${type}'; expected one of 'database', 'static'`, + ); +} diff --git a/packages/backend-app-api/src/services/implementations/auth/types.ts b/packages/backend-defaults/src/entrypoints/auth/plugin/keys/types.ts similarity index 79% rename from packages/backend-app-api/src/services/implementations/auth/types.ts rename to packages/backend-defaults/src/entrypoints/auth/plugin/keys/types.ts index 11a8fcdfcf..b02e650757 100644 --- a/packages/backend-app-api/src/services/implementations/auth/types.ts +++ b/packages/backend-defaults/src/entrypoints/auth/plugin/keys/types.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { BackstageCredentials } from '@backstage/backend-plugin-api'; +import { JWK } from 'jose'; import { JsonObject } from '@backstage/types'; export type KeyStore = { @@ -30,9 +30,7 @@ export type KeyPayload = { export type InternalKey = JsonObject & { kid: string }; -/** @internal */ -export type InternalBackstageCredentials = - BackstageCredentials & { - version: string; - token?: string; - }; +export interface PluginKeySource { + getPrivateSigningKey(): Promise; + listKeys(): Promise<{ keys: KeyPayload[] }>; +} diff --git a/packages/backend-defaults/src/entrypoints/auth/types.ts b/packages/backend-defaults/src/entrypoints/auth/types.ts new file mode 100644 index 0000000000..08ed6db421 --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/auth/types.ts @@ -0,0 +1,24 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { BackstageCredentials } from '@backstage/backend-plugin-api'; + +/** @internal */ +export type InternalBackstageCredentials = + BackstageCredentials & { + version: string; + token?: string; + }; diff --git a/packages/backend-app-api/src/services/implementations/auth/user/UserTokenHandler.test.ts b/packages/backend-defaults/src/entrypoints/auth/user/UserTokenHandler.test.ts similarity index 99% rename from packages/backend-app-api/src/services/implementations/auth/user/UserTokenHandler.test.ts rename to packages/backend-defaults/src/entrypoints/auth/user/UserTokenHandler.test.ts index b0e8418655..76bafb2a8f 100644 --- a/packages/backend-app-api/src/services/implementations/auth/user/UserTokenHandler.test.ts +++ b/packages/backend-defaults/src/entrypoints/auth/user/UserTokenHandler.test.ts @@ -346,7 +346,6 @@ describe('UserTokenHandler', () => { header: { typ: 'vnd.backstage.limited-user', alg: 'ES256' }, payload: { sub: 'mock', - ent: ['mock'], iat: 1, exp: 2, }, @@ -384,7 +383,6 @@ describe('UserTokenHandler', () => { new TextEncoder().encode( JSON.stringify({ sub: parts.payload.sub, - ent: parts.payload.ent, iat: parts.payload.iat, exp: parts.payload.exp, }), diff --git a/packages/backend-app-api/src/services/implementations/auth/user/UserTokenHandler.ts b/packages/backend-defaults/src/entrypoints/auth/user/UserTokenHandler.ts similarity index 99% rename from packages/backend-app-api/src/services/implementations/auth/user/UserTokenHandler.ts rename to packages/backend-defaults/src/entrypoints/auth/user/UserTokenHandler.ts index bd73d8701f..4dd1874843 100644 --- a/packages/backend-app-api/src/services/implementations/auth/user/UserTokenHandler.ts +++ b/packages/backend-defaults/src/entrypoints/auth/user/UserTokenHandler.ts @@ -137,7 +137,6 @@ export class UserTokenHandler { base64url.encode( JSON.stringify({ sub: payload.sub, - ent: payload.ent, iat: payload.iat, exp: payload.exp, }), diff --git a/packages/backend-defaults/src/entrypoints/cache/CacheManager.ts b/packages/backend-defaults/src/entrypoints/cache/CacheManager.ts index 70f952ea46..89fabfe977 100644 --- a/packages/backend-defaults/src/entrypoints/cache/CacheManager.ts +++ b/packages/backend-defaults/src/entrypoints/cache/CacheManager.ts @@ -15,24 +15,16 @@ */ import { - CacheService, CacheServiceOptions, LoggerService, } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import Keyv from 'keyv'; import { DefaultCacheClient } from './CacheClient'; -import { CacheManagerOptions } from './types'; +import { CacheManagerOptions, PluginCacheManager } from './types'; type StoreFactory = (pluginId: string, defaultTtl: number | undefined) => Keyv; -/* - * TODO(freben): This class intentionally inlines the CacheManagerOptions and - * PluginCacheManager types, to not break the api reports in backend-common - * which re-exports it. When backend-common is deprecated, we can stop inlining - * those types. - */ - /** * Implements a Cache Manager which will automatically create new cache clients * for plugins when requested. All requested cache clients are created with the @@ -66,18 +58,7 @@ export class CacheManager { */ static fromConfig( config: Config, - options: { - /** - * An optional logger for use by the PluginCacheManager. - */ - logger?: LoggerService; - - /** - * An optional handler for connection errors emitted from the underlying data - * store. - */ - onError?: (err: Error) => void; - } = {}, + options: CacheManagerOptions = {}, ): CacheManager { // If no `backend.cache` config is provided, instantiate the CacheManager // with an in-memory cache client. @@ -126,9 +107,7 @@ export class CacheManager { * @param pluginId - The plugin that the cache manager should be created for. * Plugin names should be unique. */ - forPlugin(pluginId: string): { - getClient(options?: CacheServiceOptions): CacheService; - } { + forPlugin(pluginId: string): PluginCacheManager { return { getClient: (defaultOptions = {}) => { const clientFactory = (options: CacheServiceOptions) => { diff --git a/packages/backend-defaults/src/entrypoints/cache/cacheServiceFactory.ts b/packages/backend-defaults/src/entrypoints/cache/cacheServiceFactory.ts index f60d770644..f16b306d81 100644 --- a/packages/backend-defaults/src/entrypoints/cache/cacheServiceFactory.ts +++ b/packages/backend-defaults/src/entrypoints/cache/cacheServiceFactory.ts @@ -21,6 +21,12 @@ import { import { CacheManager } from './CacheManager'; /** + * Key-value store for caching data. + * + * See {@link @backstage/code-plugin-api#CacheService} + * and {@link https://backstage.io/docs/backend-system/core-services/cache | the service docs} + * for more information. + * * @public */ export const cacheServiceFactory = createServiceFactory({ diff --git a/packages/backend-defaults/src/entrypoints/database/connectors/sqlite3.ts b/packages/backend-defaults/src/entrypoints/database/connectors/sqlite3.ts index f7d55b34da..97ba6d46fd 100644 --- a/packages/backend-defaults/src/entrypoints/database/connectors/sqlite3.ts +++ b/packages/backend-defaults/src/entrypoints/database/connectors/sqlite3.ts @@ -192,7 +192,7 @@ export class Sqlite3Connector implements Connector { const pluginDivisionMode = this.getPluginDivisionModeConfig(); if (pluginDivisionMode !== 'database') { throw new Error( - `The SQLite driver does not suppoert plugin division mode '${pluginDivisionMode}'`, + `The SQLite driver does not support plugin division mode '${pluginDivisionMode}'`, ); } diff --git a/packages/backend-defaults/src/entrypoints/database/databaseServiceFactory.ts b/packages/backend-defaults/src/entrypoints/database/databaseServiceFactory.ts index 12e4e569bd..3bdf1790f3 100644 --- a/packages/backend-defaults/src/entrypoints/database/databaseServiceFactory.ts +++ b/packages/backend-defaults/src/entrypoints/database/databaseServiceFactory.ts @@ -14,14 +14,20 @@ * limitations under the License. */ -import { DatabaseManager } from '@backstage/backend-common'; import { coreServices, createServiceFactory, } from '@backstage/backend-plugin-api'; import { ConfigReader } from '@backstage/config'; +import { DatabaseManager } from './DatabaseManager'; /** + * Database access and management via `knex`. + * + * See {@link @backstage/code-plugin-api#DatabaseService} + * and {@link https://backstage.io/docs/backend-system/core-services/database | the service docs} + * for more information. + * * @public */ export const databaseServiceFactory = createServiceFactory({ diff --git a/packages/backend-defaults/src/entrypoints/discovery/HostDiscovery.ts b/packages/backend-defaults/src/entrypoints/discovery/HostDiscovery.ts index 180c8706d5..559dda2aa0 100644 --- a/packages/backend-defaults/src/entrypoints/discovery/HostDiscovery.ts +++ b/packages/backend-defaults/src/entrypoints/discovery/HostDiscovery.ts @@ -15,8 +15,8 @@ */ import { Config } from '@backstage/config'; -import { readHttpServerOptions } from '@backstage/backend-app-api'; import { DiscoveryService } from '@backstage/backend-plugin-api'; +import { readHttpServerOptions } from '../rootHttpRouter/http/config'; type Target = string | { internal: string; external: string }; diff --git a/packages/backend-defaults/src/entrypoints/discovery/discoveryServiceFactory.ts b/packages/backend-defaults/src/entrypoints/discovery/discoveryServiceFactory.ts index bfc5a6a489..18ceac4a91 100644 --- a/packages/backend-defaults/src/entrypoints/discovery/discoveryServiceFactory.ts +++ b/packages/backend-defaults/src/entrypoints/discovery/discoveryServiceFactory.ts @@ -20,7 +20,15 @@ import { } from '@backstage/backend-plugin-api'; import { HostDiscovery } from './HostDiscovery'; -/** @public */ +/** + * Service discovery for inter-plugin communication. + * + * See {@link @backstage/code-plugin-api#DiscoveryService} + * and {@link https://backstage.io/docs/backend-system/core-services/discovery | the service docs} + * for more information. + * + * @public + */ export const discoveryServiceFactory = createServiceFactory({ service: coreServices.discovery, deps: { diff --git a/packages/backend-defaults/src/entrypoints/httpAuth/httpAuthServiceFactory.ts b/packages/backend-defaults/src/entrypoints/httpAuth/httpAuthServiceFactory.ts new file mode 100644 index 0000000000..76550873f6 --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/httpAuth/httpAuthServiceFactory.ts @@ -0,0 +1,294 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + AuthService, + BackstageCredentials, + BackstagePrincipalTypes, + BackstageUserPrincipal, + DiscoveryService, + HttpAuthService, + coreServices, + createServiceFactory, +} from '@backstage/backend-plugin-api'; +import { AuthenticationError, NotAllowedError } from '@backstage/errors'; +import { parse as parseCookie } from 'cookie'; +import { Request, Response } from 'express'; + +const FIVE_MINUTES_MS = 5 * 60 * 1000; + +const BACKSTAGE_AUTH_COOKIE = 'backstage-auth'; + +function getTokenFromRequest(req: Request) { + // TODO: support multiple auth headers (iterate rawHeaders) + const authHeader = req.headers.authorization; + if (typeof authHeader === 'string') { + const matches = authHeader.match(/^Bearer[ ]+(\S+)$/i); + const token = matches?.[1]; + if (token) { + return token; + } + } + + return undefined; +} + +function getCookieFromRequest(req: Request) { + const cookieHeader = req.headers.cookie; + if (cookieHeader) { + const cookies = parseCookie(cookieHeader); + const token = cookies[BACKSTAGE_AUTH_COOKIE]; + if (token) { + return token; + } + } + + return undefined; +} + +function willExpireSoon(expiresAt: Date) { + return Date.now() + FIVE_MINUTES_MS > expiresAt.getTime(); +} + +const credentialsSymbol = Symbol('backstage-credentials'); +const limitedCredentialsSymbol = Symbol('backstage-limited-credentials'); + +type RequestWithCredentials = Request & { + [credentialsSymbol]?: Promise; + [limitedCredentialsSymbol]?: Promise; +}; + +class DefaultHttpAuthService implements HttpAuthService { + readonly #auth: AuthService; + readonly #discovery: DiscoveryService; + readonly #pluginId: string; + + constructor( + auth: AuthService, + discovery: DiscoveryService, + pluginId: string, + ) { + this.#auth = auth; + this.#discovery = discovery; + this.#pluginId = pluginId; + } + + async #extractCredentialsFromRequest(req: Request) { + const token = getTokenFromRequest(req); + if (!token) { + return await this.#auth.getNoneCredentials(); + } + + return await this.#auth.authenticate(token); + } + + async #extractLimitedCredentialsFromRequest(req: Request) { + const token = getTokenFromRequest(req); + if (token) { + return await this.#auth.authenticate(token, { + allowLimitedAccess: true, + }); + } + + const cookie = getCookieFromRequest(req); + if (cookie) { + return await this.#auth.authenticate(cookie, { + allowLimitedAccess: true, + }); + } + + return await this.#auth.getNoneCredentials(); + } + + async #getCredentials(req: RequestWithCredentials) { + return (req[credentialsSymbol] ??= + this.#extractCredentialsFromRequest(req)); + } + + async #getLimitedCredentials(req: RequestWithCredentials) { + return (req[limitedCredentialsSymbol] ??= + this.#extractLimitedCredentialsFromRequest(req)); + } + + async credentials( + req: Request, + options?: { + allow?: Array; + allowLimitedAccess?: boolean; + }, + ): Promise> { + // Limited and full credentials are treated as two separate cases, this lets + // us avoid internal dependencies between the AuthService and + // HttpAuthService implementations + const credentials = options?.allowLimitedAccess + ? await this.#getLimitedCredentials(req) + : await this.#getCredentials(req); + + const allowed = options?.allow; + if (!allowed) { + return credentials as any; + } + + if (this.#auth.isPrincipal(credentials, 'none')) { + if (allowed.includes('none' as TAllowed)) { + return credentials as any; + } + + throw new AuthenticationError('Missing credentials'); + } else if (this.#auth.isPrincipal(credentials, 'user')) { + if (allowed.includes('user' as TAllowed)) { + return credentials as any; + } + + throw new NotAllowedError( + `This endpoint does not allow 'user' credentials`, + ); + } else if (this.#auth.isPrincipal(credentials, 'service')) { + if (allowed.includes('service' as TAllowed)) { + return credentials as any; + } + + throw new NotAllowedError( + `This endpoint does not allow 'service' credentials`, + ); + } + + throw new NotAllowedError( + 'Unknown principal type, this should never happen', + ); + } + + async issueUserCookie( + res: Response, + options?: { credentials?: BackstageCredentials }, + ): Promise<{ expiresAt: Date }> { + if (res.headersSent) { + throw new Error('Failed to issue user cookie, headers were already sent'); + } + + let credentials: BackstageCredentials; + if (options?.credentials) { + if (this.#auth.isPrincipal(options.credentials, 'none')) { + res.clearCookie( + BACKSTAGE_AUTH_COOKIE, + await this.#getCookieOptions(res.req), + ); + return { expiresAt: new Date() }; + } + if (!this.#auth.isPrincipal(options.credentials, 'user')) { + throw new AuthenticationError( + 'Refused to issue cookie for non-user principal', + ); + } + credentials = options.credentials; + } else { + credentials = await this.credentials(res.req, { allow: ['user'] }); + } + + const existingExpiresAt = await this.#existingCookieExpiration(res.req); + if (existingExpiresAt && !willExpireSoon(existingExpiresAt)) { + return { expiresAt: existingExpiresAt }; + } + + const { token, expiresAt } = await this.#auth.getLimitedUserToken( + credentials, + ); + if (!token) { + throw new Error('User credentials is unexpectedly missing token'); + } + + res.cookie(BACKSTAGE_AUTH_COOKIE, token, { + ...(await this.#getCookieOptions(res.req)), + expires: expiresAt, + }); + + return { expiresAt }; + } + + async #getCookieOptions(_req: Request): Promise<{ + domain: string; + httpOnly: true; + secure: boolean; + priority: 'high'; + sameSite: 'none' | 'lax'; + }> { + // TODO: eventually we should read from `${req.protocol}://${req.hostname}` + // once https://github.com/backstage/backstage/issues/24169 has landed + const externalBaseUrlStr = await this.#discovery.getExternalBaseUrl( + this.#pluginId, + ); + const externalBaseUrl = new URL(externalBaseUrlStr); + + const secure = + externalBaseUrl.protocol === 'https:' || + externalBaseUrl.hostname === 'localhost'; + + return { + domain: externalBaseUrl.hostname, + httpOnly: true, + secure, + priority: 'high', + sameSite: secure ? 'none' : 'lax', + }; + } + + async #existingCookieExpiration(req: Request): Promise { + const existingCookie = getCookieFromRequest(req); + if (!existingCookie) { + return undefined; + } + + try { + const existingCredentials = await this.#auth.authenticate( + existingCookie, + { + allowLimitedAccess: true, + }, + ); + if (!this.#auth.isPrincipal(existingCredentials, 'user')) { + return undefined; + } + + return existingCredentials.expiresAt; + } catch (error) { + if (error.name === 'AuthenticationError') { + return undefined; + } + throw error; + } + } +} + +/** + * Authentication of HTTP requests. + * + * See {@link @backstage/code-plugin-api#HttpAuthService} + * and {@link https://backstage.io/docs/backend-system/core-services/http-auth | the service docs} + * for more information. + * + * @public + */ +export const httpAuthServiceFactory = createServiceFactory({ + service: coreServices.httpAuth, + deps: { + auth: coreServices.auth, + discovery: coreServices.discovery, + plugin: coreServices.pluginMetadata, + }, + async factory({ auth, discovery, plugin }) { + return new DefaultHttpAuthService(auth, discovery, plugin.getId()); + }, +}); diff --git a/packages/backend-defaults/src/entrypoints/httpAuth/index.ts b/packages/backend-defaults/src/entrypoints/httpAuth/index.ts new file mode 100644 index 0000000000..edd7e53026 --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/httpAuth/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { httpAuthServiceFactory } from './httpAuthServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/httpRouter/createAuthIntegrationRouter.ts b/packages/backend-defaults/src/entrypoints/httpRouter/createAuthIntegrationRouter.ts similarity index 99% rename from packages/backend-app-api/src/services/implementations/httpRouter/createAuthIntegrationRouter.ts rename to packages/backend-defaults/src/entrypoints/httpRouter/createAuthIntegrationRouter.ts index 94650199f3..ef36e7ba2d 100644 --- a/packages/backend-app-api/src/services/implementations/httpRouter/createAuthIntegrationRouter.ts +++ b/packages/backend-defaults/src/entrypoints/httpRouter/createAuthIntegrationRouter.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { AuthService } from '@backstage/backend-plugin-api'; import express from 'express'; import Router from 'express-promise-router'; diff --git a/packages/backend-app-api/src/services/implementations/httpRouter/createCookieAuthRefreshMiddleware.test.ts b/packages/backend-defaults/src/entrypoints/httpRouter/createCookieAuthRefreshMiddleware.test.ts similarity index 100% rename from packages/backend-app-api/src/services/implementations/httpRouter/createCookieAuthRefreshMiddleware.test.ts rename to packages/backend-defaults/src/entrypoints/httpRouter/createCookieAuthRefreshMiddleware.test.ts diff --git a/packages/backend-app-api/src/services/implementations/httpRouter/createCookieAuthRefreshMiddleware.ts b/packages/backend-defaults/src/entrypoints/httpRouter/createCookieAuthRefreshMiddleware.ts similarity index 100% rename from packages/backend-app-api/src/services/implementations/httpRouter/createCookieAuthRefreshMiddleware.ts rename to packages/backend-defaults/src/entrypoints/httpRouter/createCookieAuthRefreshMiddleware.ts diff --git a/packages/backend-app-api/src/services/implementations/httpRouter/createCredentialsBarrier.test.ts b/packages/backend-defaults/src/entrypoints/httpRouter/createCredentialsBarrier.test.ts similarity index 98% rename from packages/backend-app-api/src/services/implementations/httpRouter/createCredentialsBarrier.test.ts rename to packages/backend-defaults/src/entrypoints/httpRouter/createCredentialsBarrier.test.ts index a5246c91b2..124acf277b 100644 --- a/packages/backend-app-api/src/services/implementations/httpRouter/createCredentialsBarrier.test.ts +++ b/packages/backend-defaults/src/entrypoints/httpRouter/createCredentialsBarrier.test.ts @@ -20,7 +20,7 @@ import express from 'express'; import request from 'supertest'; import { createCredentialsBarrier } from './createCredentialsBarrier'; import { mockCredentials, mockServices } from '@backstage/backend-test-utils'; -import { MiddlewareFactory } from '../../../http'; +import { MiddlewareFactory } from '../rootHttpRouter/http'; const errorMiddleware = MiddlewareFactory.create({ config: mockServices.rootConfig(), diff --git a/packages/backend-app-api/src/services/implementations/httpRouter/createCredentialsBarrier.ts b/packages/backend-defaults/src/entrypoints/httpRouter/createCredentialsBarrier.ts similarity index 100% rename from packages/backend-app-api/src/services/implementations/httpRouter/createCredentialsBarrier.ts rename to packages/backend-defaults/src/entrypoints/httpRouter/createCredentialsBarrier.ts diff --git a/packages/backend-app-api/src/services/implementations/httpRouter/createLifecycleMiddleware.test.ts b/packages/backend-defaults/src/entrypoints/httpRouter/createLifecycleMiddleware.test.ts similarity index 100% rename from packages/backend-app-api/src/services/implementations/httpRouter/createLifecycleMiddleware.test.ts rename to packages/backend-defaults/src/entrypoints/httpRouter/createLifecycleMiddleware.test.ts diff --git a/packages/backend-defaults/src/entrypoints/httpRouter/createLifecycleMiddleware.ts b/packages/backend-defaults/src/entrypoints/httpRouter/createLifecycleMiddleware.ts new file mode 100644 index 0000000000..3f8ee3ea69 --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/httpRouter/createLifecycleMiddleware.ts @@ -0,0 +1,106 @@ +/* + * 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 { LifecycleService } from '@backstage/backend-plugin-api'; +import { ServiceUnavailableError } from '@backstage/errors'; +import { HumanDuration, durationToMilliseconds } from '@backstage/types'; +import { RequestHandler } from 'express'; + +export const DEFAULT_TIMEOUT = { seconds: 5 }; + +/** + * Options for {@link createLifecycleMiddleware}. + * @public + */ +export interface LifecycleMiddlewareOptions { + lifecycle: LifecycleService; + /** + * The maximum time that paused requests will wait for the service to start, before returning an error. + * + * Defaults to 5 seconds. + */ + startupRequestPauseTimeout?: HumanDuration; +} + +/** + * Creates a middleware that pauses requests until the service has started. + * + * @remarks + * + * Requests that arrive before the service has started will be paused until startup is complete. + * If the service does not start within the provided timeout, the request will be rejected with a + * {@link @backstage/errors#ServiceUnavailableError}. + * + * If the service is shutting down, all requests will be rejected with a + * {@link @backstage/errors#ServiceUnavailableError}. + * + * @public + */ +export function createLifecycleMiddleware( + options: LifecycleMiddlewareOptions, +): RequestHandler { + const { lifecycle, startupRequestPauseTimeout = DEFAULT_TIMEOUT } = options; + + let state: 'init' | 'up' | 'down' = 'init'; + const waiting = new Set<{ + next: (err?: Error) => void; + timeout: NodeJS.Timeout; + }>(); + + lifecycle.addStartupHook(async () => { + if (state === 'init') { + state = 'up'; + for (const item of waiting) { + clearTimeout(item.timeout); + item.next(); + } + waiting.clear(); + } + }); + + lifecycle.addShutdownHook(async () => { + state = 'down'; + + for (const item of waiting) { + clearTimeout(item.timeout); + item.next(new ServiceUnavailableError('Service is shutting down')); + } + waiting.clear(); + }); + + const timeoutMs = durationToMilliseconds(startupRequestPauseTimeout); + + return (_req, _res, next) => { + if (state === 'up') { + next(); + return; + } else if (state === 'down') { + next(new ServiceUnavailableError('Service is shutting down')); + return; + } + + const item = { + next, + timeout: setTimeout(() => { + if (waiting.delete(item)) { + next(new ServiceUnavailableError('Service has not started up yet')); + } + }, timeoutMs), + }; + + waiting.add(item); + }; +} diff --git a/packages/backend-app-api/src/services/implementations/httpRouter/httpRouterServiceFactory.test.ts b/packages/backend-defaults/src/entrypoints/httpRouter/httpRouterServiceFactory.test.ts similarity index 100% rename from packages/backend-app-api/src/services/implementations/httpRouter/httpRouterServiceFactory.test.ts rename to packages/backend-defaults/src/entrypoints/httpRouter/httpRouterServiceFactory.test.ts diff --git a/packages/backend-defaults/src/entrypoints/httpRouter/httpRouterServiceFactory.ts b/packages/backend-defaults/src/entrypoints/httpRouter/httpRouterServiceFactory.ts new file mode 100644 index 0000000000..4a0dec49e6 --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/httpRouter/httpRouterServiceFactory.ts @@ -0,0 +1,101 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Handler } from 'express'; +import PromiseRouter from 'express-promise-router'; +import { + coreServices, + createServiceFactory, + HttpRouterServiceAuthPolicy, +} from '@backstage/backend-plugin-api'; +import { createLifecycleMiddleware } from './createLifecycleMiddleware'; +import { createCredentialsBarrier } from './createCredentialsBarrier'; +import { createAuthIntegrationRouter } from './createAuthIntegrationRouter'; +import { createCookieAuthRefreshMiddleware } from './createCookieAuthRefreshMiddleware'; + +/** + * @public + */ +export interface HttpRouterFactoryOptions { + /** + * A callback used to generate the path for each plugin, defaults to `/api/{pluginId}`. + */ + getPath?(pluginId: string): string; +} + +/** + * HTTP route registration for plugins. + * + * See {@link @backstage/code-plugin-api#HttpRouterService} + * and {@link https://backstage.io/docs/backend-system/core-services/http-router | the service docs} + * for more information. + * + * @public + */ +export const httpRouterServiceFactory = createServiceFactory( + (options?: HttpRouterFactoryOptions) => ({ + service: coreServices.httpRouter, + initialization: 'always', + deps: { + plugin: coreServices.pluginMetadata, + config: coreServices.rootConfig, + logger: coreServices.logger, + lifecycle: coreServices.lifecycle, + rootHttpRouter: coreServices.rootHttpRouter, + auth: coreServices.auth, + httpAuth: coreServices.httpAuth, + }, + async factory({ + auth, + httpAuth, + config, + logger, + plugin, + rootHttpRouter, + lifecycle, + }) { + if (options?.getPath) { + logger.warn( + `DEPRECATION WARNING: The 'getPath' option for HttpRouterService is deprecated. The ability to reconfigure the '/api/' path prefix for plugins will be removed in the future.`, + ); + } + const getPath = options?.getPath ?? (id => `/api/${id}`); + const path = getPath(plugin.getId()); + + const router = PromiseRouter(); + rootHttpRouter.use(path, router); + + const credentialsBarrier = createCredentialsBarrier({ + httpAuth, + config, + }); + + router.use(createAuthIntegrationRouter({ auth })); + router.use(createLifecycleMiddleware({ lifecycle })); + router.use(credentialsBarrier.middleware); + router.use(createCookieAuthRefreshMiddleware({ auth, httpAuth })); + + return { + use(handler: Handler): void { + router.use(handler); + }, + addAuthPolicy(policy: HttpRouterServiceAuthPolicy): void { + credentialsBarrier.addAuthPolicy(policy); + }, + }; + }, + }), +); diff --git a/packages/backend-defaults/src/entrypoints/httpRouter/index.ts b/packages/backend-defaults/src/entrypoints/httpRouter/index.ts new file mode 100644 index 0000000000..928a232131 --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/httpRouter/index.ts @@ -0,0 +1,20 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { httpRouterServiceFactory } from './httpRouterServiceFactory'; +export type { HttpRouterFactoryOptions } from './httpRouterServiceFactory'; +export { createLifecycleMiddleware } from './createLifecycleMiddleware'; +export type { LifecycleMiddlewareOptions } from './createLifecycleMiddleware'; diff --git a/packages/backend-defaults/src/entrypoints/lifecycle/lifecycleServiceFactory.ts b/packages/backend-defaults/src/entrypoints/lifecycle/lifecycleServiceFactory.ts index 3eb43d6c6e..192886ca61 100644 --- a/packages/backend-defaults/src/entrypoints/lifecycle/lifecycleServiceFactory.ts +++ b/packages/backend-defaults/src/entrypoints/lifecycle/lifecycleServiceFactory.ts @@ -85,7 +85,11 @@ export class BackendPluginLifecycleImpl implements LifecycleService { } /** - * Allows plugins to register shutdown hooks that are run when the process is about to exit. + * Registration of plugin startup and shutdown lifecycle hooks. + * + * See {@link @backstage/code-plugin-api#LifecycleService} + * and {@link https://backstage.io/docs/backend-system/core-services/lifecycle | the service docs} + * for more information. * * @public */ diff --git a/packages/backend-defaults/src/entrypoints/logger/index.ts b/packages/backend-defaults/src/entrypoints/logger/index.ts new file mode 100644 index 0000000000..ca52bf5193 --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/logger/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 { loggerServiceFactory } from './loggerServiceFactory'; diff --git a/packages/backend-common/src/cache/types.ts b/packages/backend-defaults/src/entrypoints/logger/loggerServiceFactory.ts similarity index 50% rename from packages/backend-common/src/cache/types.ts rename to packages/backend-defaults/src/entrypoints/logger/loggerServiceFactory.ts index 83b6916843..4eff798e11 100644 --- a/packages/backend-common/src/cache/types.ts +++ b/packages/backend-defaults/src/entrypoints/logger/loggerServiceFactory.ts @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Backstage Authors + * Copyright 2022 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,26 +14,27 @@ * limitations under the License. */ -import type { - CacheService, - CacheServiceSetOptions, - CacheServiceOptions, +import { + createServiceFactory, + coreServices, } from '@backstage/backend-plugin-api'; /** + * Plugin-level logging. + * + * See {@link @backstage/code-plugin-api#LoggerService} + * and {@link https://backstage.io/docs/backend-system/core-services/logger | the service docs} + * for more information. + * * @public - * @deprecated Use `CacheService` from the `@backstage/backend-plugin-api` package instead */ -export type CacheClient = CacheService; - -/** - * @public - * @deprecated Use `CacheServiceSetOptions` from the `@backstage/backend-plugin-api` package instead - */ -export type CacheClientSetOptions = CacheServiceSetOptions; - -/** - * @public - * @deprecated Use `CacheServiceOptions` from the `@backstage/backend-plugin-api` package instead - */ -export type CacheClientOptions = CacheServiceOptions; +export const loggerServiceFactory = createServiceFactory({ + service: coreServices.logger, + deps: { + rootLogger: coreServices.rootLogger, + plugin: coreServices.pluginMetadata, + }, + factory({ rootLogger, plugin }) { + return rootLogger.child({ plugin: plugin.getId() }); + }, +}); diff --git a/packages/backend-defaults/src/entrypoints/permissions/permissionsServiceFactory.ts b/packages/backend-defaults/src/entrypoints/permissions/permissionsServiceFactory.ts index f675dd6719..873d6a4fa0 100644 --- a/packages/backend-defaults/src/entrypoints/permissions/permissionsServiceFactory.ts +++ b/packages/backend-defaults/src/entrypoints/permissions/permissionsServiceFactory.ts @@ -21,6 +21,12 @@ import { import { ServerPermissionClient } from '@backstage/plugin-permission-node'; /** + * Permission system integration for authorization of user actions. + * + * See {@link @backstage/code-plugin-api#PermissionsService} + * and {@link https://backstage.io/docs/backend-system/core-services/permissions | the service docs} + * for more information. + * * @public */ export const permissionsServiceFactory = createServiceFactory({ diff --git a/packages/backend-defaults/src/entrypoints/rootConfig/createConfigSecretEnumerator.test.ts b/packages/backend-defaults/src/entrypoints/rootConfig/createConfigSecretEnumerator.test.ts new file mode 100644 index 0000000000..1efb12ad03 --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/rootConfig/createConfigSecretEnumerator.test.ts @@ -0,0 +1,74 @@ +/* + * 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 { loadConfigSchema } from '@backstage/config-loader'; +import { createConfigSecretEnumerator } from './createConfigSecretEnumerator'; +import { mockServices } from '@backstage/backend-test-utils'; + +describe('createConfigSecretEnumerator', () => { + it('should enumerate secrets', async () => { + const logger = mockServices.logger.mock(); + + const enumerate = await createConfigSecretEnumerator({ + logger, + }); + const secrets = enumerate( + mockServices.rootConfig({ + data: { + backend: { auth: { keys: [{ secret: 'my-secret-password' }] } }, + }, + }), + ); + expect(Array.from(secrets)).toEqual(['my-secret-password']); + }, 20_000); // Bit higher timeout since we're loading all config schemas in the repo + + it('should enumerate secrets with explicit schema', async () => { + const logger = mockServices.logger.mock(); + + const enumerate = await createConfigSecretEnumerator({ + logger, + schema: await loadConfigSchema({ + serialized: { + schemas: [ + { + value: { + type: 'object', + properties: { + secret: { + visibility: 'secret', + type: 'string', + }, + }, + }, + path: '/mock', + }, + ], + backstageConfigSchemaVersion: 1, + }, + }), + }); + + const secrets = enumerate( + mockServices.rootConfig({ + data: { + secret: 'my-secret', + other: 'not-secret', + }, + }), + ); + expect(Array.from(secrets)).toEqual(['my-secret']); + }); +}); diff --git a/packages/backend-defaults/src/entrypoints/rootConfig/createConfigSecretEnumerator.ts b/packages/backend-defaults/src/entrypoints/rootConfig/createConfigSecretEnumerator.ts new file mode 100644 index 0000000000..421b07c396 --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/rootConfig/createConfigSecretEnumerator.ts @@ -0,0 +1,54 @@ +/* + * 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 { LoggerService } from '@backstage/backend-plugin-api'; +import type { Config } from '@backstage/config'; +import { ConfigSchema, loadConfigSchema } from '@backstage/config-loader'; +import { getPackages } from '@manypkg/get-packages'; + +/** @public */ +export async function createConfigSecretEnumerator(options: { + logger: LoggerService; + dir?: string; + schema?: ConfigSchema; +}): Promise<(config: Config) => Iterable> { + const { logger, dir = process.cwd() } = options; + const { packages } = await getPackages(dir); + const schema = + options.schema ?? + (await loadConfigSchema({ + dependencies: packages.map(p => p.packageJson.name), + })); + + return (config: Config) => { + const [secretsData] = schema.process( + [{ data: config.getOptional() ?? {}, context: 'schema-enumerator' }], + { + visibility: ['secret'], + ignoreSchemaErrors: true, + }, + ); + const secrets = new Set(); + JSON.parse( + JSON.stringify(secretsData.data), + (_, v) => typeof v === 'string' && secrets.add(v), + ); + logger.info( + `Found ${secrets.size} new secrets in config that will be redacted`, + ); + return secrets; + }; +} diff --git a/packages/backend-defaults/src/entrypoints/rootConfig/index.ts b/packages/backend-defaults/src/entrypoints/rootConfig/index.ts index 1775ef2efc..66f5e8e15f 100644 --- a/packages/backend-defaults/src/entrypoints/rootConfig/index.ts +++ b/packages/backend-defaults/src/entrypoints/rootConfig/index.ts @@ -14,5 +14,8 @@ * limitations under the License. */ -export { rootConfigServiceFactory } from './rootConfigServiceFactory'; -export type { RootConfigFactoryOptions } from './rootConfigServiceFactory'; +export { createConfigSecretEnumerator } from './createConfigSecretEnumerator'; +export { + rootConfigServiceFactory, + type RootConfigFactoryOptions, +} from './rootConfigServiceFactory'; diff --git a/packages/backend-defaults/src/entrypoints/rootConfig/rootConfigServiceFactory.ts b/packages/backend-defaults/src/entrypoints/rootConfig/rootConfigServiceFactory.ts index 92d1a89c0f..5752a9c634 100644 --- a/packages/backend-defaults/src/entrypoints/rootConfig/rootConfigServiceFactory.ts +++ b/packages/backend-defaults/src/entrypoints/rootConfig/rootConfigServiceFactory.ts @@ -24,6 +24,12 @@ import { } from '@backstage/config-loader'; /** + * Access to static configuration. + * + * See {@link @backstage/code-plugin-api#RootConfigService} + * and {@link https://backstage.io/docs/backend-system/core-services/root-config | the service docs} + * for more information. + * * @public */ export interface RootConfigFactoryOptions { diff --git a/packages/backend-defaults/src/entrypoints/rootHealth/index.ts b/packages/backend-defaults/src/entrypoints/rootHealth/index.ts new file mode 100644 index 0000000000..35225b39c4 --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/rootHealth/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { rootHealthServiceFactory } from './rootHealthServiceFactory'; diff --git a/packages/backend-defaults/src/entrypoints/rootHealth/rootHealthServiceFactory.test.ts b/packages/backend-defaults/src/entrypoints/rootHealth/rootHealthServiceFactory.test.ts new file mode 100644 index 0000000000..0eee5c18c6 --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/rootHealth/rootHealthServiceFactory.test.ts @@ -0,0 +1,91 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { mockServices } from '@backstage/backend-test-utils'; +import { DefaultRootHealthService } from './rootHealthServiceFactory'; + +describe('DefaultRootHealthService', () => { + describe('readiness', () => { + it(`should return a 500 response if the server hasn't started yet`, async () => { + const service = new DefaultRootHealthService({ + lifecycle: mockServices.rootLifecycle.mock(), + }); + await expect(service.getReadiness()).resolves.toEqual({ + status: 503, + payload: { + message: 'Backend has not started yet', + status: 'error', + }, + }); + }); + + it('should return 200 if the server has started', async () => { + let mockServerStartedFn = () => {}; + + const lifecycle = mockServices.rootLifecycle.mock({ + addStartupHook: jest.fn(fn => (mockServerStartedFn = fn)), + }); + + const service = new DefaultRootHealthService({ + lifecycle, + }); + + mockServerStartedFn(); + + await expect(service.getReadiness()).resolves.toEqual({ + status: 200, + payload: { status: 'ok' }, + }); + }); + + it(`should return a 500 response if the server has stopped`, async () => { + let mockServerStartedFn = () => {}; + let mockServerStoppedFn = () => {}; + + const lifecycle = mockServices.rootLifecycle.mock({ + addStartupHook: jest.fn(fn => (mockServerStartedFn = fn)), + addShutdownHook: jest.fn(fn => (mockServerStoppedFn = fn)), + }); + + const service = new DefaultRootHealthService({ + lifecycle, + }); + + mockServerStartedFn(); + mockServerStoppedFn(); + await expect(service.getReadiness()).resolves.toEqual({ + status: 503, + payload: { + message: 'Backend has not started yet', + status: 'error', + }, + }); + }); + }); + + describe('liveness', () => { + it('should return 200 if the server has started', async () => { + const service = new DefaultRootHealthService({ + lifecycle: mockServices.rootLifecycle.mock(), + }); + + await expect(service.getLiveness()).resolves.toEqual({ + status: 200, + payload: { status: 'ok' }, + }); + }); + }); +}); diff --git a/packages/backend-defaults/src/entrypoints/rootHealth/rootHealthServiceFactory.ts b/packages/backend-defaults/src/entrypoints/rootHealth/rootHealthServiceFactory.ts new file mode 100644 index 0000000000..c8b4ad5394 --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/rootHealth/rootHealthServiceFactory.ts @@ -0,0 +1,64 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + RootHealthService, + RootLifecycleService, + coreServices, + createServiceFactory, +} from '@backstage/backend-plugin-api'; + +/** @internal */ +export class DefaultRootHealthService implements RootHealthService { + #isRunning = false; + + constructor(readonly options: { lifecycle: RootLifecycleService }) { + options.lifecycle.addStartupHook(() => { + this.#isRunning = true; + }); + options.lifecycle.addShutdownHook(() => { + this.#isRunning = false; + }); + } + + async getLiveness(): Promise<{ status: number; payload?: any }> { + return { status: 200, payload: { status: 'ok' } }; + } + + async getReadiness(): Promise<{ status: number; payload?: any }> { + if (!this.#isRunning) { + return { + status: 503, + payload: { message: 'Backend has not started yet', status: 'error' }, + }; + } + + return { status: 200, payload: { status: 'ok' } }; + } +} + +/** + * @public + */ +export const rootHealthServiceFactory = createServiceFactory({ + service: coreServices.rootHealth, + deps: { + lifecycle: coreServices.rootLifecycle, + }, + async factory({ lifecycle }) { + return new DefaultRootHealthService({ lifecycle }); + }, +}); diff --git a/packages/backend-defaults/src/entrypoints/rootHttpRouter/DefaultRootHttpRouter.test.ts b/packages/backend-defaults/src/entrypoints/rootHttpRouter/DefaultRootHttpRouter.test.ts new file mode 100644 index 0000000000..fc1de9b205 --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/rootHttpRouter/DefaultRootHttpRouter.test.ts @@ -0,0 +1,124 @@ +/* + * 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 express from 'express'; +import request from 'supertest'; +import { DefaultRootHttpRouter } from './DefaultRootHttpRouter'; + +describe('DefaultRootHttpRouter', () => { + it.each([ + [['/b'], '/a'], + [['/a'], '/aa/b'], + [['/aa'], '/a/b'], + [['/a/b'], '/aa'], + [['/b/a'], '/a'], + [['/a'], '/aa'], + ])(`with existing paths %s, adds %s without conflict`, (existing, added) => { + const router = DefaultRootHttpRouter.create(); + for (const path of existing) { + router.use(path, () => {}); + } + expect(() => router.use(added, () => {})).not.toThrow(); + }); + + it.each([ + [['/a'], '/a', '/a'], + [['/a'], '/a/b', '/a'], + [['/a/b'], '/a', '/a/b'], + ])( + `find conflict when existing paths %s, adds %s`, + (existing, added, conflict) => { + const router = DefaultRootHttpRouter.create(); + for (const path of existing) { + router.use(path, () => {}); + } + expect(() => router.use(added, () => {})).toThrow( + `Path ${added} conflicts with the existing path ${conflict}`, + ); + }, + ); + + it('should not be possible to supply an empty indexPath', () => { + expect(() => DefaultRootHttpRouter.create({ indexPath: '' })).toThrow( + 'indexPath option may not be an empty string', + ); + }); + + it('will always prioritize non-index paths', async () => { + const router = DefaultRootHttpRouter.create({ indexPath: '/x' }); + const app = express(); + app.use(router.handler()); + + const routerX = express.Router(); + routerX.get('/a', (_req, res) => res.status(201).end()); + + const routerY = express.Router(); + routerY.get('/a', (_req, res) => res.status(202).end()); + + await request(app).get('/').expect(404); + await request(app).get('/a').expect(404); + await request(app).get('/x/a').expect(404); + await request(app).get('/y/a').expect(404); + + router.use('/x', routerX); + + await request(app).get('/').expect(404); + await request(app).get('/a').expect(201); + await request(app).get('/x/a').expect(201); + await request(app).get('/y/a').expect(404); + + router.use('/y', routerY); + + await request(app).get('/').expect(404); + await request(app).get('/a').expect(201); + await request(app).get('/x/a').expect(201); + await request(app).get('/y/a').expect(202); + + expect('test').toBe('test'); + }); + + it('should treat unknown /api/ routes as 404', async () => { + const router = DefaultRootHttpRouter.create(); + const app = express(); + app.use(router.handler()); + + router.use('/api/app', (_req, res) => res.status(201).end()); + router.use('/api/catalog', (_req, res) => res.status(202).end()); + + await request(app).get('/').expect(201); + await request(app).get('/api/catalog').expect(202); + await request(app).get('/unknown').expect(201); + await request(app).get('/api/unknown').expect(404); + + expect('test').toBe('test'); + }); + + it('should treat unknown /api/ routes as 404 without an index path', async () => { + const router = DefaultRootHttpRouter.create({ indexPath: false }); + const app = express(); + app.use(router.handler()); + + router.use('/api/app', (_req, res) => res.status(201).end()); + router.use('/api/catalog', (_req, res) => res.status(202).end()); + + await request(app).get('/').expect(404); + await request(app).get('/api/catalog').expect(202); + await request(app).get('/unknown').expect(404); + await request(app).get('/api/unknown').expect(404); + + expect('test').toBe('test'); + }); +}); diff --git a/packages/backend-defaults/src/entrypoints/rootHttpRouter/DefaultRootHttpRouter.ts b/packages/backend-defaults/src/entrypoints/rootHttpRouter/DefaultRootHttpRouter.ts new file mode 100644 index 0000000000..9d7d1de120 --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/rootHttpRouter/DefaultRootHttpRouter.ts @@ -0,0 +1,115 @@ +/* + * 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 { RootHttpRouterService } from '@backstage/backend-plugin-api'; +import { Handler, Router } from 'express'; +import trimEnd from 'lodash/trimEnd'; + +function normalizePath(path: string): string { + return `${trimEnd(path, '/')}/`; +} + +/** + * Options for the {@link DefaultRootHttpRouter} class. + * + * @public + */ +export interface DefaultRootHttpRouterOptions { + /** + * The path to forward all unmatched requests to. Defaults to '/api/app' if + * not given. Disables index path behavior if false is given. + */ + indexPath?: string | false; +} + +/** + * The default implementation of the {@link @backstage/backend-plugin-api#RootHttpRouterService} interface for + * {@link @backstage/backend-plugin-api#coreServices.rootHttpRouter}. + * + * @public + */ +export class DefaultRootHttpRouter implements RootHttpRouterService { + #indexPath?: string; + + #router = Router(); + #namedRoutes = Router(); + #indexRouter = Router(); + #existingPaths = new Array(); + + static create(options?: DefaultRootHttpRouterOptions) { + let indexPath; + if (options?.indexPath === false) { + indexPath = undefined; + } else if (options?.indexPath === undefined) { + indexPath = '/api/app'; + } else if (options?.indexPath === '') { + throw new Error('indexPath option may not be an empty string'); + } else { + indexPath = options.indexPath; + } + return new DefaultRootHttpRouter(indexPath); + } + + private constructor(indexPath?: string) { + this.#indexPath = indexPath; + this.#router.use(this.#namedRoutes); + + // Any request with a /api/ prefix will skip the index router, even if no named router matches + this.#router.use('/api/', (_req, _res, next) => { + next('router'); + }); + + if (this.#indexPath) { + this.#router.use(this.#indexRouter); + } + } + + use(path: string, handler: Handler) { + if (path.match(/^[/\s]*$/)) { + throw new Error(`Root router path may not be empty`); + } + const conflictingPath = this.#findConflictingPath(path); + if (conflictingPath) { + throw new Error( + `Path ${path} conflicts with the existing path ${conflictingPath}`, + ); + } + this.#existingPaths.push(path); + this.#namedRoutes.use(path, handler); + + if (this.#indexPath === path) { + this.#indexRouter.use(handler); + } + } + + handler(): Handler { + return this.#router; + } + + #findConflictingPath(newPath: string): string | undefined { + const normalizedNewPath = normalizePath(newPath); + for (const path of this.#existingPaths) { + const normalizedPath = normalizePath(path); + if (normalizedPath.startsWith(normalizedNewPath)) { + return path; + } + if (normalizedNewPath.startsWith(normalizedPath)) { + return path; + } + } + return undefined; + } +} diff --git a/packages/backend-defaults/src/entrypoints/rootHttpRouter/createHealthRouter.ts b/packages/backend-defaults/src/entrypoints/rootHttpRouter/createHealthRouter.ts new file mode 100644 index 0000000000..13691ede28 --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/rootHttpRouter/createHealthRouter.ts @@ -0,0 +1,42 @@ +import { RootHealthService } from '@backstage/backend-plugin-api'; + +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Router from 'express-promise-router'; +import { Request, Response } from 'express'; + +export function createHealthRouter(options: { health: RootHealthService }) { + const router = Router(); + + router.get( + '.backstage/health/v1/readiness', + async (_request: Request, response: Response) => { + const { status, payload } = await options.health.getReadiness(); + response.status(status).json(payload); + }, + ); + + router.get( + '.backstage/health/v1/liveness', + async (_request: Request, response: Response) => { + const { status, payload } = await options.health.getLiveness(); + response.status(status).json(payload); + }, + ); + + return router; +} diff --git a/packages/backend-app-api/src/http/MiddlewareFactory.test.ts b/packages/backend-defaults/src/entrypoints/rootHttpRouter/http/MiddlewareFactory.test.ts similarity index 100% rename from packages/backend-app-api/src/http/MiddlewareFactory.test.ts rename to packages/backend-defaults/src/entrypoints/rootHttpRouter/http/MiddlewareFactory.test.ts diff --git a/packages/backend-app-api/src/http/MiddlewareFactory.ts b/packages/backend-defaults/src/entrypoints/rootHttpRouter/http/MiddlewareFactory.ts similarity index 100% rename from packages/backend-app-api/src/http/MiddlewareFactory.ts rename to packages/backend-defaults/src/entrypoints/rootHttpRouter/http/MiddlewareFactory.ts diff --git a/packages/backend-app-api/src/http/applyInternalErrorFilter.ts b/packages/backend-defaults/src/entrypoints/rootHttpRouter/http/applyInternalErrorFilter.ts similarity index 100% rename from packages/backend-app-api/src/http/applyInternalErrorFilter.ts rename to packages/backend-defaults/src/entrypoints/rootHttpRouter/http/applyInternalErrorFilter.ts diff --git a/packages/backend-app-api/src/http/config.test.ts b/packages/backend-defaults/src/entrypoints/rootHttpRouter/http/config.test.ts similarity index 100% rename from packages/backend-app-api/src/http/config.test.ts rename to packages/backend-defaults/src/entrypoints/rootHttpRouter/http/config.test.ts diff --git a/packages/backend-app-api/src/http/config.ts b/packages/backend-defaults/src/entrypoints/rootHttpRouter/http/config.ts similarity index 100% rename from packages/backend-app-api/src/http/config.ts rename to packages/backend-defaults/src/entrypoints/rootHttpRouter/http/config.ts diff --git a/packages/backend-app-api/src/http/createHttpServer.ts b/packages/backend-defaults/src/entrypoints/rootHttpRouter/http/createHttpServer.ts similarity index 100% rename from packages/backend-app-api/src/http/createHttpServer.ts rename to packages/backend-defaults/src/entrypoints/rootHttpRouter/http/createHttpServer.ts diff --git a/packages/backend-app-api/src/http/getGeneratedCertificate.ts b/packages/backend-defaults/src/entrypoints/rootHttpRouter/http/getGeneratedCertificate.ts similarity index 100% rename from packages/backend-app-api/src/http/getGeneratedCertificate.ts rename to packages/backend-defaults/src/entrypoints/rootHttpRouter/http/getGeneratedCertificate.ts diff --git a/packages/backend-defaults/src/entrypoints/rootHttpRouter/http/index.ts b/packages/backend-defaults/src/entrypoints/rootHttpRouter/http/index.ts new file mode 100644 index 0000000000..4a9ec14cf8 --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/rootHttpRouter/http/index.ts @@ -0,0 +1,30 @@ +/* + * 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 { readHttpServerOptions } from './config'; +export { createHttpServer } from './createHttpServer'; +export { MiddlewareFactory } from './MiddlewareFactory'; +export type { + MiddlewareFactoryErrorOptions, + MiddlewareFactoryOptions, +} from './MiddlewareFactory'; +export { readCorsOptions } from './readCorsOptions'; +export { readHelmetOptions } from './readHelmetOptions'; +export type { + ExtendedHttpServer, + HttpServerCertificateOptions, + HttpServerOptions, +} from './types'; diff --git a/packages/backend-app-api/src/http/readCorsOptions.test.ts b/packages/backend-defaults/src/entrypoints/rootHttpRouter/http/readCorsOptions.test.ts similarity index 100% rename from packages/backend-app-api/src/http/readCorsOptions.test.ts rename to packages/backend-defaults/src/entrypoints/rootHttpRouter/http/readCorsOptions.test.ts diff --git a/packages/backend-app-api/src/http/readCorsOptions.ts b/packages/backend-defaults/src/entrypoints/rootHttpRouter/http/readCorsOptions.ts similarity index 100% rename from packages/backend-app-api/src/http/readCorsOptions.ts rename to packages/backend-defaults/src/entrypoints/rootHttpRouter/http/readCorsOptions.ts diff --git a/packages/backend-app-api/src/http/readHelmetOptions.test.ts b/packages/backend-defaults/src/entrypoints/rootHttpRouter/http/readHelmetOptions.test.ts similarity index 100% rename from packages/backend-app-api/src/http/readHelmetOptions.test.ts rename to packages/backend-defaults/src/entrypoints/rootHttpRouter/http/readHelmetOptions.test.ts diff --git a/packages/backend-app-api/src/http/readHelmetOptions.ts b/packages/backend-defaults/src/entrypoints/rootHttpRouter/http/readHelmetOptions.ts similarity index 100% rename from packages/backend-app-api/src/http/readHelmetOptions.ts rename to packages/backend-defaults/src/entrypoints/rootHttpRouter/http/readHelmetOptions.ts diff --git a/packages/backend-app-api/src/http/types.ts b/packages/backend-defaults/src/entrypoints/rootHttpRouter/http/types.ts similarity index 100% rename from packages/backend-app-api/src/http/types.ts rename to packages/backend-defaults/src/entrypoints/rootHttpRouter/http/types.ts diff --git a/packages/backend-defaults/src/entrypoints/rootHttpRouter/index.ts b/packages/backend-defaults/src/entrypoints/rootHttpRouter/index.ts new file mode 100644 index 0000000000..9c2d96dab2 --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/rootHttpRouter/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. + */ + +export { + DefaultRootHttpRouter, + type DefaultRootHttpRouterOptions, +} from './DefaultRootHttpRouter'; +export * from './http'; +export { + rootHttpRouterServiceFactory, + type RootHttpRouterConfigureContext, + type RootHttpRouterFactoryOptions, +} from './rootHttpRouterServiceFactory'; diff --git a/packages/backend-defaults/src/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.ts b/packages/backend-defaults/src/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.ts new file mode 100644 index 0000000000..22f5c2f310 --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.ts @@ -0,0 +1,126 @@ +/* + * 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 { + RootConfigService, + coreServices, + createServiceFactory, + LifecycleService, + LoggerService, +} from '@backstage/backend-plugin-api'; +import express, { RequestHandler, Express } from 'express'; +import type { Server } from 'node:http'; +import { + createHttpServer, + MiddlewareFactory, + readHttpServerOptions, +} from './http'; +import { DefaultRootHttpRouter } from './DefaultRootHttpRouter'; +import { createHealthRouter } from './createHealthRouter'; + +/** + * @public + */ +export interface RootHttpRouterConfigureContext { + app: Express; + server: Server; + middleware: MiddlewareFactory; + routes: RequestHandler; + config: RootConfigService; + logger: LoggerService; + lifecycle: LifecycleService; + healthRouter: RequestHandler; + applyDefaults: () => void; +} + +/** + * HTTP route registration for root services. + * + * See {@link @backstage/code-plugin-api#RootHttpRouterService} + * and {@link https://backstage.io/docs/backend-system/core-services/root-http-router | the service docs} + * for more information. + * + * @public + */ +export type RootHttpRouterFactoryOptions = { + /** + * The path to forward all unmatched requests to. Defaults to '/api/app' if + * not given. Disables index path behavior if false is given. + */ + indexPath?: string | false; + + configure?(context: RootHttpRouterConfigureContext): void; +}; + +function defaultConfigure({ applyDefaults }: RootHttpRouterConfigureContext) { + applyDefaults(); +} + +/** @public */ +export const rootHttpRouterServiceFactory = createServiceFactory( + (options?: RootHttpRouterFactoryOptions) => ({ + service: coreServices.rootHttpRouter, + deps: { + config: coreServices.rootConfig, + rootLogger: coreServices.rootLogger, + lifecycle: coreServices.rootLifecycle, + health: coreServices.rootHealth, + }, + async factory({ config, rootLogger, lifecycle, health }) { + const { indexPath, configure = defaultConfigure } = options ?? {}; + const logger = rootLogger.child({ service: 'rootHttpRouter' }); + const app = express(); + + const router = DefaultRootHttpRouter.create({ indexPath }); + const middleware = MiddlewareFactory.create({ config, logger }); + const routes = router.handler(); + + const healthRouter = createHealthRouter({ health }); + const server = await createHttpServer( + app, + readHttpServerOptions(config.getOptionalConfig('backend')), + { logger }, + ); + + configure({ + app, + server, + routes, + middleware, + config, + logger, + lifecycle, + healthRouter, + applyDefaults() { + app.use(middleware.helmet()); + app.use(middleware.cors()); + app.use(middleware.compression()); + app.use(middleware.logging()); + app.use(healthRouter); + app.use(routes); + app.use(middleware.notFound()); + app.use(middleware.error()); + }, + }); + + lifecycle.addShutdownHook(() => server.stop()); + + await server.start(); + + return router; + }, + }), +); diff --git a/packages/backend-defaults/src/entrypoints/rootLifecycle/rootLifecycleServiceFactory.test.ts b/packages/backend-defaults/src/entrypoints/rootLifecycle/rootLifecycleServiceFactory.test.ts index 91cb9031ae..5992e38d50 100644 --- a/packages/backend-defaults/src/entrypoints/rootLifecycle/rootLifecycleServiceFactory.test.ts +++ b/packages/backend-defaults/src/entrypoints/rootLifecycle/rootLifecycleServiceFactory.test.ts @@ -14,12 +14,12 @@ * limitations under the License. */ -import { getVoidLogger } from '@backstage/backend-common'; import { BackendLifecycleImpl } from './rootLifecycleServiceFactory'; +import { mockServices } from '@backstage/backend-test-utils'; describe('lifecycleService', () => { it('should execute registered shutdown hook', async () => { - const service = new BackendLifecycleImpl(getVoidLogger()); + const service = new BackendLifecycleImpl(mockServices.logger.mock()); const hook = jest.fn(); service.addShutdownHook(() => hook()); // should not execute the hook more than once. @@ -30,7 +30,7 @@ describe('lifecycleService', () => { }); it('should not throw errors', async () => { - const service = new BackendLifecycleImpl(getVoidLogger()); + const service = new BackendLifecycleImpl(mockServices.logger.mock()); service.addShutdownHook(() => { throw new Error('oh no'); }); @@ -38,7 +38,7 @@ describe('lifecycleService', () => { }); it('should not throw async errors', async () => { - const service = new BackendLifecycleImpl(getVoidLogger()); + const service = new BackendLifecycleImpl(mockServices.logger.mock()); service.addShutdownHook(async () => { throw new Error('oh no'); }); @@ -46,7 +46,7 @@ describe('lifecycleService', () => { }); it('should reject hooks after trigger', async () => { - const service = new BackendLifecycleImpl(getVoidLogger()); + const service = new BackendLifecycleImpl(mockServices.logger.mock()); await service.startup(); expect(() => { service.addStartupHook(() => {}); diff --git a/packages/backend-defaults/src/entrypoints/rootLifecycle/rootLifecycleServiceFactory.ts b/packages/backend-defaults/src/entrypoints/rootLifecycle/rootLifecycleServiceFactory.ts index 197f99b97a..e724c2f5cb 100644 --- a/packages/backend-defaults/src/entrypoints/rootLifecycle/rootLifecycleServiceFactory.ts +++ b/packages/backend-defaults/src/entrypoints/rootLifecycle/rootLifecycleServiceFactory.ts @@ -105,7 +105,11 @@ export class BackendLifecycleImpl implements RootLifecycleService { } /** - * Allows plugins to register shutdown hooks that are run when the process is about to exit. + * Registration of backend startup and shutdown lifecycle hooks. + * + * See {@link @backstage/code-plugin-api#RootLifecycleService} + * and {@link https://backstage.io/docs/backend-system/core-services/root-lifecycle | the service docs} + * for more information. * * @public */ diff --git a/packages/backend-app-api/src/logging/WinstonLogger.test.ts b/packages/backend-defaults/src/entrypoints/rootLogger/WinstonLogger.test.ts similarity index 100% rename from packages/backend-app-api/src/logging/WinstonLogger.test.ts rename to packages/backend-defaults/src/entrypoints/rootLogger/WinstonLogger.test.ts diff --git a/packages/backend-defaults/src/entrypoints/rootLogger/WinstonLogger.ts b/packages/backend-defaults/src/entrypoints/rootLogger/WinstonLogger.ts new file mode 100644 index 0000000000..38d05f6511 --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/rootLogger/WinstonLogger.ts @@ -0,0 +1,192 @@ +/* + * 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 { + LoggerService, + RootLoggerService, +} from '@backstage/backend-plugin-api'; +import { JsonObject } from '@backstage/types'; +import { Format, TransformableInfo } from 'logform'; +import { + Logger, + format, + createLogger, + transports, + transport as Transport, +} from 'winston'; +import { MESSAGE } from 'triple-beam'; +import { escapeRegExp } from '../../lib/escapeRegExp'; + +/** + * @public + */ +export interface WinstonLoggerOptions { + meta?: JsonObject; + level?: string; + format?: Format; + transports?: Transport[]; +} + +/** + * A {@link @backstage/backend-plugin-api#LoggerService} implementation based on winston. + * + * @public + */ +export class WinstonLogger implements RootLoggerService { + #winston: Logger; + #addRedactions?: (redactions: Iterable) => void; + + /** + * Creates a {@link WinstonLogger} instance. + */ + static create(options: WinstonLoggerOptions): WinstonLogger { + const redacter = WinstonLogger.redacter(); + const defaultFormatter = + process.env.NODE_ENV === 'production' + ? format.json() + : WinstonLogger.colorFormat(); + + let logger = createLogger({ + level: process.env.LOG_LEVEL || options.level || 'info', + format: format.combine( + options.format ?? defaultFormatter, + redacter.format, + ), + transports: options.transports ?? new transports.Console(), + }); + + if (options.meta) { + logger = logger.child(options.meta); + } + + return new WinstonLogger(logger, redacter.add); + } + + /** + * Creates a winston log formatter for redacting secrets. + */ + static redacter(): { + format: Format; + add: (redactions: Iterable) => void; + } { + const redactionSet = new Set(); + + let redactionPattern: RegExp | undefined = undefined; + + return { + format: format((obj: TransformableInfo) => { + if (!redactionPattern || !obj) { + return obj; + } + + obj[MESSAGE] = obj[MESSAGE]?.replace?.(redactionPattern, '***'); + + return obj; + })(), + add(newRedactions) { + let added = 0; + for (const redactionToTrim of newRedactions) { + // Trimming the string ensures that we don't accdentally get extra + // newlines or other whitespace interfering with the redaction; this + // can happen for example when using string literals in yaml + const redaction = redactionToTrim.trim(); + // Exclude secrets that are empty or just one character in length. These + // typically mean that you are running local dev or tests, or using the + // --lax flag which sets things to just 'x'. + if (redaction.length <= 1) { + continue; + } + if (!redactionSet.has(redaction)) { + redactionSet.add(redaction); + added += 1; + } + } + if (added > 0) { + const redactions = Array.from(redactionSet) + .map(r => escapeRegExp(r)) + .join('|'); + redactionPattern = new RegExp(`(${redactions})`, 'g'); + } + }, + }; + } + + /** + * Creates a pretty printed winston log formatter. + */ + static colorFormat(): Format { + const colorizer = format.colorize(); + + return format.combine( + format.timestamp(), + format.colorize({ + colors: { + timestamp: 'dim', + prefix: 'blue', + field: 'cyan', + debug: 'grey', + }, + }), + format.printf((info: TransformableInfo) => { + const { timestamp, level, message, plugin, service, ...fields } = info; + const prefix = plugin || service; + const timestampColor = colorizer.colorize('timestamp', timestamp); + const prefixColor = colorizer.colorize('prefix', prefix); + + const extraFields = Object.entries(fields) + .map( + ([key, value]) => + `${colorizer.colorize('field', `${key}`)}=${value}`, + ) + .join(' '); + + return `${timestampColor} ${prefixColor} ${level} ${message} ${extraFields}`; + }), + ); + } + + private constructor( + winston: Logger, + addRedactions?: (redactions: Iterable) => void, + ) { + this.#winston = winston; + this.#addRedactions = addRedactions; + } + + error(message: string, meta?: JsonObject): void { + this.#winston.error(message, meta); + } + + warn(message: string, meta?: JsonObject): void { + this.#winston.warn(message, meta); + } + + info(message: string, meta?: JsonObject): void { + this.#winston.info(message, meta); + } + + debug(message: string, meta?: JsonObject): void { + this.#winston.debug(message, meta); + } + + child(meta: JsonObject): LoggerService { + return new WinstonLogger(this.#winston.child(meta)); + } + + addRedactions(redactions: Iterable) { + this.#addRedactions?.(redactions); + } +} diff --git a/packages/backend-defaults/src/entrypoints/rootLogger/index.ts b/packages/backend-defaults/src/entrypoints/rootLogger/index.ts new file mode 100644 index 0000000000..96ed402520 --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/rootLogger/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { rootLoggerServiceFactory } from './rootLoggerServiceFactory'; +export { WinstonLogger, type WinstonLoggerOptions } from './WinstonLogger'; diff --git a/packages/backend-defaults/src/entrypoints/rootLogger/rootLoggerServiceFactory.ts b/packages/backend-defaults/src/entrypoints/rootLogger/rootLoggerServiceFactory.ts new file mode 100644 index 0000000000..8454cf07d3 --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/rootLogger/rootLoggerServiceFactory.ts @@ -0,0 +1,58 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + createServiceFactory, + coreServices, +} from '@backstage/backend-plugin-api'; +import { transports, format } from 'winston'; +import { WinstonLogger } from '../rootLogger/WinstonLogger'; +import { createConfigSecretEnumerator } from '../rootConfig/createConfigSecretEnumerator'; + +/** + * Root-level logging. + * + * See {@link @backstage/code-plugin-api#RootLoggerService} + * and {@link https://backstage.io/docs/backend-system/core-services/root-logger | the service docs} + * for more information. + * + * @public + */ +export const rootLoggerServiceFactory = createServiceFactory({ + service: coreServices.rootLogger, + deps: { + config: coreServices.rootConfig, + }, + async factory({ config }) { + const logger = WinstonLogger.create({ + meta: { + service: 'backstage', + }, + level: process.env.LOG_LEVEL || 'info', + format: + process.env.NODE_ENV === 'production' + ? format.json() + : WinstonLogger.colorFormat(), + transports: [new transports.Console()], + }); + + const secretEnumerator = await createConfigSecretEnumerator({ logger }); + logger.addRedactions(secretEnumerator(config)); + config.subscribe?.(() => logger.addRedactions(secretEnumerator(config))); + + return logger; + }, +}); diff --git a/packages/backend-defaults/src/entrypoints/scheduler/database/migrateBackendTasks.ts b/packages/backend-defaults/src/entrypoints/scheduler/database/migrateBackendTasks.ts index 959e6097f4..ab8b7a8e73 100644 --- a/packages/backend-defaults/src/entrypoints/scheduler/database/migrateBackendTasks.ts +++ b/packages/backend-defaults/src/entrypoints/scheduler/database/migrateBackendTasks.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { resolvePackagePath } from '@backstage/backend-common'; +import { resolvePackagePath } from '@backstage/backend-plugin-api'; import { Knex } from 'knex'; import { DB_MIGRATIONS_TABLE } from './tables'; diff --git a/packages/backend-defaults/src/entrypoints/scheduler/lib/LocalTaskWorker.test.ts b/packages/backend-defaults/src/entrypoints/scheduler/lib/LocalTaskWorker.test.ts index 4fd4949478..d4d3d16067 100644 --- a/packages/backend-defaults/src/entrypoints/scheduler/lib/LocalTaskWorker.test.ts +++ b/packages/backend-defaults/src/entrypoints/scheduler/lib/LocalTaskWorker.test.ts @@ -14,11 +14,11 @@ * limitations under the License. */ -import { getVoidLogger } from '@backstage/backend-common'; import { LocalTaskWorker } from './LocalTaskWorker'; +import { mockServices } from '@backstage/backend-test-utils'; describe('LocalTaskWorker', () => { - const logger = getVoidLogger(); + const logger = mockServices.logger.mock(); it('runs the happy path (with iso duration) and handles cancellation', async () => { const fn = jest.fn(); diff --git a/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.test.ts b/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.test.ts index 57faa6faf8..c5c4c8708a 100644 --- a/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.test.ts +++ b/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.test.ts @@ -14,8 +14,11 @@ * limitations under the License. */ -import { getVoidLogger } from '@backstage/backend-common'; -import { TestDatabaseId, TestDatabases } from '@backstage/backend-test-utils'; +import { + TestDatabaseId, + TestDatabases, + mockServices, +} from '@backstage/backend-test-utils'; import { ConflictError, NotFoundError } from '@backstage/errors'; import { Duration } from 'luxon'; import { migrateBackendTasks } from '../database/migrateBackendTasks'; @@ -53,7 +56,7 @@ describe('PluginTaskManagerImpl', () => { await migrateBackendTasks(knex); const manager = new PluginTaskSchedulerImpl( async () => knex, - getVoidLogger(), + mockServices.logger.mock(), ); return { knex, manager }; } diff --git a/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.ts b/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.ts index 62b36e024c..40aa9d521c 100644 --- a/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.ts +++ b/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.ts @@ -152,7 +152,7 @@ export class PluginTaskSchedulerImpl implements SchedulerService { export function parseDuration( frequency: SchedulerServiceTaskScheduleDefinition['frequency'], ): string { - if ('cron' in frequency) { + if (typeof frequency === 'object' && 'cron' in frequency) { return frequency.cron; } diff --git a/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerJanitor.test.ts b/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerJanitor.test.ts index 82133a9e54..388f882afc 100644 --- a/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerJanitor.test.ts +++ b/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerJanitor.test.ts @@ -14,8 +14,7 @@ * limitations under the License. */ -import { getVoidLogger } from '@backstage/backend-common'; -import { TestDatabases } from '@backstage/backend-test-utils'; +import { TestDatabases, mockServices } from '@backstage/backend-test-utils'; import { Knex } from 'knex'; import { Duration } from 'luxon'; import waitForExpect from 'wait-for-expect'; @@ -36,7 +35,7 @@ const getTask = async (knex: Knex): Promise => { }; describe('PluginTaskSchedulerJanitor', () => { - const logger = getVoidLogger(); + const logger = mockServices.logger.mock(); const databases = TestDatabases.create({ ids: [ /* 'MYSQL_8' not supported yet */ diff --git a/packages/backend-defaults/src/entrypoints/scheduler/lib/TaskWorker.test.ts b/packages/backend-defaults/src/entrypoints/scheduler/lib/TaskWorker.test.ts index 20d9b63859..1cafe00670 100644 --- a/packages/backend-defaults/src/entrypoints/scheduler/lib/TaskWorker.test.ts +++ b/packages/backend-defaults/src/entrypoints/scheduler/lib/TaskWorker.test.ts @@ -14,8 +14,7 @@ * limitations under the License. */ -import { getVoidLogger } from '@backstage/backend-common'; -import { TestDatabases } from '@backstage/backend-test-utils'; +import { TestDatabases, mockServices } from '@backstage/backend-test-utils'; import { DateTime, Duration } from 'luxon'; import waitForExpect from 'wait-for-expect'; import { migrateBackendTasks } from '../database/migrateBackendTasks'; @@ -27,7 +26,7 @@ import { TaskSettingsV2 } from './types'; jest.setTimeout(60_000); describe('TaskWorker', () => { - const logger = getVoidLogger(); + const logger = mockServices.logger.mock(); const databases = TestDatabases.create(); const testScopedSignal = createTestScopedSignal(); diff --git a/packages/backend-defaults/src/entrypoints/scheduler/schedulerServiceFactory.ts b/packages/backend-defaults/src/entrypoints/scheduler/schedulerServiceFactory.ts index 1105c86332..effa5c5925 100644 --- a/packages/backend-defaults/src/entrypoints/scheduler/schedulerServiceFactory.ts +++ b/packages/backend-defaults/src/entrypoints/scheduler/schedulerServiceFactory.ts @@ -21,7 +21,11 @@ import { import { DefaultSchedulerService } from './lib/DefaultSchedulerService'; /** - * The default service factory for {@link @backstage/backend-plugin-api#coreServices.scheduler}. + * Scheduling of distributed background tasks. + * + * See {@link @backstage/code-plugin-api#SchedulerService} + * and {@link https://backstage.io/docs/backend-system/core-services/scheduler | the service docs} + * for more information. * * @public */ diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/AwsCodeCommitUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/AwsCodeCommitUrlReader.ts index f204d1390d..7f02f1468f 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/AwsCodeCommitUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/AwsCodeCommitUrlReader.ts @@ -17,11 +17,11 @@ import { ReaderFactory, ReadTreeResponseFactory } from './types'; import { UrlReaderService, - UrlReaderReadTreeOptions, - UrlReaderReadTreeResponse, - UrlReaderReadUrlOptions, - UrlReaderReadUrlResponse, - UrlReaderSearchResponse, + UrlReaderServiceReadTreeOptions, + UrlReaderServiceReadTreeResponse, + UrlReaderServiceReadUrlOptions, + UrlReaderServiceReadUrlResponse, + UrlReaderServiceSearchResponse, } from '@backstage/backend-plugin-api'; import { AwsCredentialsManager, @@ -221,8 +221,8 @@ export class AwsCodeCommitUrlReader implements UrlReaderService { async readUrl( url: string, - options?: UrlReaderReadUrlOptions, - ): Promise { + options?: UrlReaderServiceReadUrlOptions, + ): Promise { // etag and lastModifiedAfter are not supported by the CodeCommit API try { const { path, repositoryName, region, commitSpecifier } = parseUrl( @@ -325,8 +325,8 @@ export class AwsCodeCommitUrlReader implements UrlReaderService { async readTree( url: string, - options?: UrlReaderReadTreeOptions, - ): Promise { + options?: UrlReaderServiceReadTreeOptions, + ): Promise { // url: https://eu-west-1.console.aws.amazon.com/codesuite/codecommit/repositories/test-stijn-delete-techdocs/browse?region=eu-west-1 try { const { path, repositoryName, region, commitSpecifier } = parseUrl(url); @@ -379,7 +379,7 @@ export class AwsCodeCommitUrlReader implements UrlReaderService { } } - async search(): Promise { + async search(): Promise { throw new Error('AwsCodeCommitReader does not implement search'); } diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/AwsS3UrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/AwsS3UrlReader.ts index b98b285f99..27f60f5b77 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/AwsS3UrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/AwsS3UrlReader.ts @@ -16,11 +16,11 @@ import { UrlReaderService, - UrlReaderReadTreeOptions, - UrlReaderReadTreeResponse, - UrlReaderReadUrlOptions, - UrlReaderReadUrlResponse, - UrlReaderSearchResponse, + UrlReaderServiceReadTreeOptions, + UrlReaderServiceReadTreeResponse, + UrlReaderServiceReadUrlOptions, + UrlReaderServiceReadUrlResponse, + UrlReaderServiceSearchResponse, } from '@backstage/backend-plugin-api'; import { ReaderFactory, ReadTreeResponseFactory } from './types'; import { @@ -252,8 +252,8 @@ export class AwsS3UrlReader implements UrlReaderService { async readUrl( url: string, - options?: UrlReaderReadUrlOptions, - ): Promise { + options?: UrlReaderServiceReadUrlOptions, + ): Promise { const { etag, lastModifiedAfter } = options ?? {}; try { @@ -299,8 +299,8 @@ export class AwsS3UrlReader implements UrlReaderService { async readTree( url: string, - options?: UrlReaderReadTreeOptions, - ): Promise { + options?: UrlReaderServiceReadTreeOptions, + ): Promise { try { const { path, bucket, region } = parseUrl(url, this.integration.config); const s3Client = await this.buildS3Client( @@ -356,7 +356,7 @@ export class AwsS3UrlReader implements UrlReaderService { } } - async search(): Promise { + async search(): Promise { throw new Error('AwsS3Reader does not implement search'); } diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/AzureUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/AzureUrlReader.ts index b6945f11ea..50513fcdcc 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/AzureUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/AzureUrlReader.ts @@ -16,12 +16,12 @@ import { UrlReaderService, - UrlReaderReadTreeOptions, - UrlReaderReadTreeResponse, - UrlReaderReadUrlOptions, - UrlReaderReadUrlResponse, - UrlReaderSearchOptions, - UrlReaderSearchResponse, + UrlReaderServiceReadTreeOptions, + UrlReaderServiceReadTreeResponse, + UrlReaderServiceReadUrlOptions, + UrlReaderServiceReadUrlResponse, + UrlReaderServiceSearchOptions, + UrlReaderServiceSearchResponse, } from '@backstage/backend-plugin-api'; import { getAzureCommitsUrl, @@ -74,8 +74,8 @@ export class AzureUrlReader implements UrlReaderService { async readUrl( url: string, - options?: UrlReaderReadUrlOptions, - ): Promise { + options?: UrlReaderServiceReadUrlOptions, + ): Promise { // TODO: etag is not implemented yet. const { signal } = options ?? {}; @@ -113,8 +113,8 @@ export class AzureUrlReader implements UrlReaderService { async readTree( url: string, - options?: UrlReaderReadTreeOptions, - ): Promise { + options?: UrlReaderServiceReadTreeOptions, + ): Promise { const { etag, filter, signal } = options ?? {}; // TODO: Support filepath based reading tree feature like other providers @@ -181,8 +181,8 @@ export class AzureUrlReader implements UrlReaderService { async search( url: string, - options?: UrlReaderSearchOptions, - ): Promise { + options?: UrlReaderServiceSearchOptions, + ): Promise { const treeUrl = new URL(url); const path = treeUrl.searchParams.get('path'); diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketCloudUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketCloudUrlReader.ts index 5235215758..b7b733867e 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketCloudUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketCloudUrlReader.ts @@ -16,12 +16,12 @@ import { UrlReaderService, - UrlReaderReadTreeOptions, - UrlReaderReadTreeResponse, - UrlReaderReadUrlOptions, - UrlReaderReadUrlResponse, - UrlReaderSearchOptions, - UrlReaderSearchResponse, + UrlReaderServiceReadTreeOptions, + UrlReaderServiceReadTreeResponse, + UrlReaderServiceReadUrlOptions, + UrlReaderServiceReadUrlResponse, + UrlReaderServiceSearchOptions, + UrlReaderServiceSearchResponse, } from '@backstage/backend-plugin-api'; import { NotFoundError, NotModifiedError } from '@backstage/errors'; import { @@ -78,8 +78,8 @@ export class BitbucketCloudUrlReader implements UrlReaderService { async readUrl( url: string, - options?: UrlReaderReadUrlOptions, - ): Promise { + options?: UrlReaderServiceReadUrlOptions, + ): Promise { const { etag, lastModifiedAfter, signal } = options ?? {}; const bitbucketUrl = getBitbucketCloudFileFetchUrl( url, @@ -133,8 +133,8 @@ export class BitbucketCloudUrlReader implements UrlReaderService { async readTree( url: string, - options?: UrlReaderReadTreeOptions, - ): Promise { + options?: UrlReaderServiceReadTreeOptions, + ): Promise { const { filepath } = parseGitUrl(url); const lastCommitShortHash = await this.getLastCommitShortHash(url); @@ -168,8 +168,8 @@ export class BitbucketCloudUrlReader implements UrlReaderService { async search( url: string, - options?: UrlReaderSearchOptions, - ): Promise { + options?: UrlReaderServiceSearchOptions, + ): Promise { const { filepath } = parseGitUrl(url); const matcher = new Minimatch(filepath); diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketServerUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketServerUrlReader.ts index d539b006ed..332e300cb8 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketServerUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketServerUrlReader.ts @@ -16,12 +16,12 @@ import { UrlReaderService, - UrlReaderReadTreeOptions, - UrlReaderReadTreeResponse, - UrlReaderReadUrlOptions, - UrlReaderReadUrlResponse, - UrlReaderSearchOptions, - UrlReaderSearchResponse, + UrlReaderServiceReadTreeOptions, + UrlReaderServiceReadTreeResponse, + UrlReaderServiceReadUrlOptions, + UrlReaderServiceReadUrlResponse, + UrlReaderServiceSearchOptions, + UrlReaderServiceSearchResponse, } from '@backstage/backend-plugin-api'; import { NotFoundError, NotModifiedError } from '@backstage/errors'; import { @@ -69,8 +69,8 @@ export class BitbucketServerUrlReader implements UrlReaderService { async readUrl( url: string, - options?: UrlReaderReadUrlOptions, - ): Promise { + options?: UrlReaderServiceReadUrlOptions, + ): Promise { const { etag, lastModifiedAfter, signal } = options ?? {}; const bitbucketUrl = getBitbucketServerFileFetchUrl( url, @@ -124,8 +124,8 @@ export class BitbucketServerUrlReader implements UrlReaderService { async readTree( url: string, - options?: UrlReaderReadTreeOptions, - ): Promise { + options?: UrlReaderServiceReadTreeOptions, + ): Promise { const { filepath } = parseGitUrl(url); const lastCommitShortHash = await this.getLastCommitShortHash(url); @@ -159,8 +159,8 @@ export class BitbucketServerUrlReader implements UrlReaderService { async search( url: string, - options?: UrlReaderSearchOptions, - ): Promise { + options?: UrlReaderServiceSearchOptions, + ): Promise { const { filepath } = parseGitUrl(url); const matcher = new Minimatch(filepath); diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.ts index 7f831800d3..55d676ed91 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.ts @@ -16,12 +16,12 @@ import { UrlReaderService, - UrlReaderReadTreeOptions, - UrlReaderReadTreeResponse, - UrlReaderReadUrlOptions, - UrlReaderReadUrlResponse, - UrlReaderSearchOptions, - UrlReaderSearchResponse, + UrlReaderServiceReadTreeOptions, + UrlReaderServiceReadTreeResponse, + UrlReaderServiceReadUrlOptions, + UrlReaderServiceReadUrlResponse, + UrlReaderServiceSearchOptions, + UrlReaderServiceSearchResponse, } from '@backstage/backend-plugin-api'; import { NotFoundError, NotModifiedError } from '@backstage/errors'; import { @@ -94,8 +94,8 @@ export class BitbucketUrlReader implements UrlReaderService { async readUrl( url: string, - options?: UrlReaderReadUrlOptions, - ): Promise { + options?: UrlReaderServiceReadUrlOptions, + ): Promise { const { etag, lastModifiedAfter, signal } = options ?? {}; const bitbucketUrl = getBitbucketFileFetchUrl(url, this.integration.config); const requestOptions = getBitbucketRequestOptions(this.integration.config); @@ -144,8 +144,8 @@ export class BitbucketUrlReader implements UrlReaderService { async readTree( url: string, - options?: UrlReaderReadTreeOptions, - ): Promise { + options?: UrlReaderServiceReadTreeOptions, + ): Promise { const { filepath } = parseGitUrl(url); const lastCommitShortHash = await this.getLastCommitShortHash(url); @@ -179,8 +179,8 @@ export class BitbucketUrlReader implements UrlReaderService { async search( url: string, - options?: UrlReaderSearchOptions, - ): Promise { + options?: UrlReaderServiceSearchOptions, + ): Promise { const { filepath } = parseGitUrl(url); const matcher = new Minimatch(filepath); diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/FetchUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/FetchUrlReader.ts index d62eaedc1a..55041cf036 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/FetchUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/FetchUrlReader.ts @@ -16,10 +16,10 @@ import { UrlReaderService, - UrlReaderReadTreeResponse, - UrlReaderReadUrlOptions, - UrlReaderReadUrlResponse, - UrlReaderSearchResponse, + UrlReaderServiceReadTreeResponse, + UrlReaderServiceReadUrlOptions, + UrlReaderServiceReadUrlResponse, + UrlReaderServiceSearchResponse, } from '@backstage/backend-plugin-api'; import { NotFoundError, NotModifiedError } from '@backstage/errors'; import fetch, { Response } from 'node-fetch'; @@ -121,8 +121,8 @@ export class FetchUrlReader implements UrlReaderService { async readUrl( url: string, - options?: UrlReaderReadUrlOptions, - ): Promise { + options?: UrlReaderServiceReadUrlOptions, + ): Promise { let response: Response; try { response = await fetch(url, { @@ -165,11 +165,11 @@ export class FetchUrlReader implements UrlReaderService { throw new Error(message); } - async readTree(): Promise { + async readTree(): Promise { throw new Error('FetchUrlReader does not implement readTree'); } - async search(): Promise { + async search(): Promise { throw new Error('FetchUrlReader does not implement search'); } diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/GerritUrlReader.test.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/GerritUrlReader.test.ts index ca4a2707f3..94627e074f 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/GerritUrlReader.test.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/GerritUrlReader.test.ts @@ -32,10 +32,7 @@ import fs from 'fs-extra'; import path from 'path'; import { UrlReaderPredicateTuple } from './types'; import { DefaultReadTreeResponseFactory } from './tree'; -import { - GITILES_BASE_URL_DEPRECATION_MESSSAGE, - GerritUrlReader, -} from './GerritUrlReader'; +import { GerritUrlReader } from './GerritUrlReader'; import getRawBody from 'raw-body'; const mockDir = createMockDirectory({ mockOsTmpDir: true }); @@ -61,11 +58,11 @@ const gerritProcessor = new GerritUrlReader( readGerritIntegrationConfig( new ConfigReader({ host: 'gerrit.com', + gitilesBaseUrl: 'https://gerrit.com/gitiles', }), ), ), { treeResponseFactory }, - '/tmp', ); // Gerrit processor with a gitilesBaseUrl configured. @@ -80,7 +77,6 @@ const gerritProcessorWithGitiles = new GerritUrlReader( ), ), { treeResponseFactory }, - '/tmp', ); const createReader = (config: JsonObject): UrlReaderPredicateTuple[] => { @@ -112,7 +108,12 @@ describe.skip('GerritUrlReader', () => { it('creates a reader.', () => { const readers = createReader({ integrations: { - gerrit: [{ host: 'gerrit.com' }], + gerrit: [ + { + host: 'gerrit.com', + gitilesBaseUrl: 'https://gerrit.com/gitiles', + }, + ], }, }); expect(readers).toHaveLength(1); @@ -126,33 +127,12 @@ describe.skip('GerritUrlReader', () => { }); }); - describe('handle optional gitilesBaseUrl deprecation', () => { - it('should throw if gitilesBaseUrl is not set.', () => { - process.env = env; - expect(() => - createReader({ - integrations: { - gerrit: [{ host: 'gerrit.com' }], - }, - }), - ).toThrow(GITILES_BASE_URL_DEPRECATION_MESSSAGE); - }); - it('should not throw if gitilesBaseUrl requirement is overridden.', () => { - process.env = { ...env, DISABLE_GERRIT_GITILES_REQUIREMENT: '1' }; - expect(() => - createReader({ - integrations: { - gerrit: [{ host: 'gerrit.com' }], - }, - }), - ).not.toThrow(); - }); - }); - describe('predicates without Gitiles', () => { const readers = createReader({ integrations: { - gerrit: [{ host: 'gerrit.com' }], + gerrit: [ + { host: 'gerrit.com', gitilesBaseUrl: 'https://gerrit.com/gitiles' }, + ], }, }); const predicate = readers[0].predicate; @@ -354,29 +334,6 @@ describe.skip('GerritUrlReader', () => { expect(cloneMock).not.toHaveBeenCalled(); }); - it('reads the wanted files correctly using git clone.', async () => { - worker.use( - rest.get(branchAPIUrl, (_, res, ctx) => { - return res(ctx.status(200), ctx.body(branchAPIresponse)); - }), - ); - - const response = await gerritProcessor.readTree(treeUrl); - - expect(response.etag).toBe(etag); - - const files = await response.files(); - expect(files.length).toBe(2); - - const docsYaml = await files[0].content(); - expect(docsYaml.toString()).toBe(mkdocsContent); - - const mdFile = await files[1].content(); - expect(mdFile.toString()).toBe(mdContent); - - expect(cloneMock).toHaveBeenCalled(); - }); - it('throws NotModifiedError for matching etags.', async () => { worker.use( rest.get(branchAPIUrl, (_, res, ctx) => { @@ -432,25 +389,5 @@ describe.skip('GerritUrlReader', () => { expect(cloneMock).not.toHaveBeenCalled(); }); - - it('should returns wanted files with a subpath using git clone', async () => { - worker.use( - rest.get(branchAPIUrl, (_, res, ctx) => { - return res(ctx.status(200), ctx.body(branchAPIresponse)); - }), - ); - - const response = await gerritProcessor.readTree(`${treeUrl}/docs`); - - expect(response.etag).toBe(etag); - - const files = await response.files(); - expect(files.length).toBe(1); - - const mdFile = await files[0].content(); - expect(mdFile.toString()).toBe(mdContent); - - expect(cloneMock).toHaveBeenCalled(); - }); }); }); diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/GerritUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/GerritUrlReader.ts index 2274182e02..2ef9116208 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/GerritUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/GerritUrlReader.ts @@ -16,27 +16,20 @@ import { UrlReaderService, - UrlReaderReadTreeOptions, - UrlReaderReadTreeResponse, - UrlReaderReadUrlOptions, - UrlReaderReadUrlResponse, - UrlReaderSearchResponse, + UrlReaderServiceReadTreeOptions, + UrlReaderServiceReadTreeResponse, + UrlReaderServiceReadUrlOptions, + UrlReaderServiceReadUrlResponse, + UrlReaderServiceSearchResponse, } from '@backstage/backend-plugin-api'; import { Base64Decode } from 'base64-stream'; -import concatStream from 'concat-stream'; -import fs from 'fs-extra'; import fetch, { Response } from 'node-fetch'; -import os from 'os'; -import { join as joinPath } from 'path'; -import { Readable, pipeline as pipelineCb } from 'stream'; -import tar from 'tar'; -import { promisify } from 'util'; +import { Readable } from 'stream'; import { GerritIntegration, ScmIntegrations, buildGerritGitilesArchiveUrl, getGerritBranchApiUrl, - getGerritCloneRepoUrl, getGerritFileContentsApiUrl, getGerritRequestOptions, parseGerritGitilesUrl, @@ -44,18 +37,6 @@ import { } from '@backstage/integration'; import { NotFoundError, NotModifiedError } from '@backstage/errors'; import { ReadTreeResponseFactory, ReaderFactory } from './types'; -import { Git } from './git'; - -const pipeline = promisify(pipelineCb); - -export const GITILES_BASE_URL_DEPRECATION_MESSSAGE = `A gitilesBaseUrl must be provided \ -for the gerrit integration to work. You can disable this check by setting \ -DISABLE_GERRIT_GITILES_REQUIREMENT=1 but this will be removed in a future release. If you \ -are not able to use the gitiles gerrit plugin, please open an issue towards \ -https://github.com/backstage/backstage`; - -const createTemporaryDirectory = async (workDir: string): Promise => - await fs.mkdtemp(joinPath(workDir, '/gerrit-clone-')); /** * Implements a {@link @backstage/backend-plugin-api#UrlReaderService} for files in Gerrit. @@ -83,20 +64,8 @@ export class GerritUrlReader implements UrlReaderService { if (!integrations.gerrit) { return []; } - const workDir = - config.getOptionalString('backend.workingDirectory') ?? os.tmpdir(); return integrations.gerrit.list().map(integration => { - if ( - integration.config.gitilesBaseUrl === integration.config.baseUrl && - process.env.DISABLE_GERRIT_GITILES_REQUIREMENT === undefined - ) { - throw new Error(GITILES_BASE_URL_DEPRECATION_MESSSAGE); - } - const reader = new GerritUrlReader( - integration, - { treeResponseFactory }, - workDir, - ); + const reader = new GerritUrlReader(integration, { treeResponseFactory }); const predicate = (url: URL) => { const gitilesUrl = new URL(integration.config.gitilesBaseUrl!); // If gitilesUrl is not specified it will default to @@ -110,7 +79,6 @@ export class GerritUrlReader implements UrlReaderService { constructor( private readonly integration: GerritIntegration, private readonly deps: { treeResponseFactory: ReadTreeResponseFactory }, - private readonly workDir: string, ) {} async read(url: string): Promise { @@ -120,8 +88,8 @@ export class GerritUrlReader implements UrlReaderService { async readUrl( url: string, - options?: UrlReaderReadUrlOptions, - ): Promise { + options?: UrlReaderServiceReadUrlOptions, + ): Promise { const apiUrl = getGerritFileContentsApiUrl(this.integration.config, url); let response: Response; try { @@ -165,8 +133,8 @@ export class GerritUrlReader implements UrlReaderService { async readTree( url: string, - options?: UrlReaderReadTreeOptions, - ): Promise { + options?: UrlReaderServiceReadTreeOptions, + ): Promise { const apiUrl = getGerritBranchApiUrl(this.integration.config, url); let response: Response; try { @@ -194,15 +162,10 @@ export class GerritUrlReader implements UrlReaderService { throw new NotModifiedError(); } - if ( - this.integration.config.gitilesBaseUrl !== this.integration.config.baseUrl - ) { - return this.readTreeFromGitiles(url, branchInfo.revision, options); - } - return this.readTreeFromGitClone(url, branchInfo.revision, options); + return this.readTreeFromGitiles(url, branchInfo.revision, options); } - async search(): Promise { + async search(): Promise { throw new Error('GerritReader does not implement search'); } @@ -211,53 +174,10 @@ export class GerritUrlReader implements UrlReaderService { return `gerrit{host=${host},authed=${Boolean(password)}}`; } - private async readTreeFromGitClone( - url: string, - revision: string, - options?: UrlReaderReadTreeOptions, - ) { - const { filePath } = parseGerritGitilesUrl(this.integration.config, url); - - const git = Git.fromAuth({ - username: this.integration.config.username, - password: this.integration.config.password, - }); - const tempDir = await createTemporaryDirectory(this.workDir); - const cloneUrl = getGerritCloneRepoUrl(this.integration.config, url); - try { - // The "fromTarArchive" function will strip the top level directory so - // an additional directory level is created when we clone. - await git.clone({ - url: cloneUrl, - dir: joinPath(tempDir, 'repo'), - ref: revision, - depth: 1, - }); - - const data = await new Promise(async resolve => { - await pipeline( - tar.create({ cwd: tempDir }, ['']), - concatStream(resolve), - ); - }); - const tarArchive = Readable.from(data); - return await this.deps.treeResponseFactory.fromTarArchive({ - stream: tarArchive, - subpath: filePath === '/' ? undefined : filePath, - etag: revision, - filter: options?.filter, - }); - } catch (error) { - throw new Error(`Could not clone ${cloneUrl}: ${error}`); - } finally { - await fs.rm(tempDir, { recursive: true, force: true }); - } - } - private async readTreeFromGitiles( url: string, revision: string, - options?: UrlReaderReadTreeOptions, + options?: UrlReaderServiceReadTreeOptions, ) { const { branch, filePath, project } = parseGerritGitilesUrl( this.integration.config, diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/GiteaUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/GiteaUrlReader.ts index da1b30ab6b..d8471c43f3 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/GiteaUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/GiteaUrlReader.ts @@ -16,11 +16,11 @@ import { UrlReaderService, - UrlReaderReadTreeOptions, - UrlReaderReadTreeResponse, - UrlReaderReadUrlOptions, - UrlReaderReadUrlResponse, - UrlReaderSearchResponse, + UrlReaderServiceReadTreeOptions, + UrlReaderServiceReadTreeResponse, + UrlReaderServiceReadUrlOptions, + UrlReaderServiceReadUrlResponse, + UrlReaderServiceSearchResponse, } from '@backstage/backend-plugin-api'; import { getGiteaFileContentsUrl, @@ -74,8 +74,8 @@ export class GiteaUrlReader implements UrlReaderService { async readUrl( url: string, - options?: UrlReaderReadUrlOptions, - ): Promise { + options?: UrlReaderServiceReadUrlOptions, + ): Promise { let response: Response; const blobUrl = getGiteaFileContentsUrl(this.integration.config, url); @@ -126,8 +126,8 @@ export class GiteaUrlReader implements UrlReaderService { async readTree( url: string, - options?: UrlReaderReadTreeOptions, - ): Promise { + options?: UrlReaderServiceReadTreeOptions, + ): Promise { const lastCommitHash = await this.getLastCommitHash(url); if (options?.etag && options.etag === lastCommitHash) { throw new NotModifiedError(); @@ -156,7 +156,7 @@ export class GiteaUrlReader implements UrlReaderService { }); } - search(): Promise { + search(): Promise { throw new Error('GiteaUrlReader search not implemented.'); } diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/GithubUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/GithubUrlReader.ts index 60e9b210cd..913e382f92 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/GithubUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/GithubUrlReader.ts @@ -16,13 +16,13 @@ import { UrlReaderService, - UrlReaderReadTreeOptions, - UrlReaderReadTreeResponse, - UrlReaderReadUrlOptions, - UrlReaderReadUrlResponse, - UrlReaderSearchOptions, - UrlReaderSearchResponse, - UrlReaderSearchResponseFile, + UrlReaderServiceReadTreeOptions, + UrlReaderServiceReadTreeResponse, + UrlReaderServiceReadUrlOptions, + UrlReaderServiceReadUrlResponse, + UrlReaderServiceSearchOptions, + UrlReaderServiceSearchResponse, + UrlReaderServiceSearchResponseFile, } from '@backstage/backend-plugin-api'; import { getGithubFileFetchUrl, @@ -112,8 +112,8 @@ export class GithubUrlReader implements UrlReaderService { async readUrl( url: string, - options?: UrlReaderReadUrlOptions, - ): Promise { + options?: UrlReaderServiceReadUrlOptions, + ): Promise { const credentials = await this.getCredentials(url, options); const ghUrl = getGithubFileFetchUrl( @@ -148,8 +148,8 @@ export class GithubUrlReader implements UrlReaderService { async readTree( url: string, - options?: UrlReaderReadTreeOptions, - ): Promise { + options?: UrlReaderServiceReadTreeOptions, + ): Promise { const repoDetails = await this.getRepoDetails(url); const commitSha = repoDetails.commitSha; @@ -177,8 +177,8 @@ export class GithubUrlReader implements UrlReaderService { async search( url: string, - options?: UrlReaderSearchOptions, - ): Promise { + options?: UrlReaderServiceSearchOptions, + ): Promise { const repoDetails = await this.getRepoDetails(url); const commitSha = repoDetails.commitSha; @@ -211,8 +211,8 @@ export class GithubUrlReader implements UrlReaderService { sha: string, subpath: string, init: RequestInit, - options?: UrlReaderReadTreeOptions, - ): Promise { + options?: UrlReaderServiceReadTreeOptions, + ): Promise { // archive_url looks like "https://api.github.com/repos/owner/repo/{archive_format}{/ref}" const archive = await this.fetchResponse( archiveUrl @@ -238,7 +238,7 @@ export class GithubUrlReader implements UrlReaderService { sha: string, query: string, init: RequestInit, - ): Promise { + ): Promise { function pathToUrl(path: string): string { // TODO(freben): Use the integration package facility for this instead // pathname starts as /backstage/backstage/blob/master/ diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/GitlabUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/GitlabUrlReader.ts index b45a61a40e..615eeb20a2 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/GitlabUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/GitlabUrlReader.ts @@ -16,12 +16,12 @@ import { UrlReaderService, - UrlReaderReadTreeOptions, - UrlReaderReadTreeResponse, - UrlReaderReadUrlOptions, - UrlReaderReadUrlResponse, - UrlReaderSearchOptions, - UrlReaderSearchResponse, + UrlReaderServiceReadTreeOptions, + UrlReaderServiceReadTreeResponse, + UrlReaderServiceReadUrlOptions, + UrlReaderServiceReadUrlResponse, + UrlReaderServiceSearchOptions, + UrlReaderServiceSearchResponse, } from '@backstage/backend-plugin-api'; import { getGitLabFileFetchUrl, @@ -69,8 +69,8 @@ export class GitlabUrlReader implements UrlReaderService { async readUrl( url: string, - options?: UrlReaderReadUrlOptions, - ): Promise { + options?: UrlReaderServiceReadUrlOptions, + ): Promise { const { etag, lastModifiedAfter, signal } = options ?? {}; const builtUrl = await this.getGitlabFetchUrl(url); @@ -118,8 +118,8 @@ export class GitlabUrlReader implements UrlReaderService { async readTree( url: string, - options?: UrlReaderReadTreeOptions, - ): Promise { + options?: UrlReaderServiceReadTreeOptions, + ): Promise { const { etag, signal } = options ?? {}; const { ref, full_name, filepath } = parseGitUrl(url); @@ -237,8 +237,8 @@ export class GitlabUrlReader implements UrlReaderService { async search( url: string, - options?: UrlReaderSearchOptions, - ): Promise { + options?: UrlReaderServiceSearchOptions, + ): Promise { const { filepath } = parseGitUrl(url); const staticPart = this.getStaticPart(filepath); const matcher = new Minimatch(filepath); diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/GoogleGcsUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/GoogleGcsUrlReader.ts index 843eee9c21..10440dba20 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/GoogleGcsUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/GoogleGcsUrlReader.ts @@ -17,10 +17,10 @@ import * as GoogleCloud from '@google-cloud/storage'; import { UrlReaderService, - UrlReaderReadTreeResponse, - UrlReaderReadUrlOptions, - UrlReaderReadUrlResponse, - UrlReaderSearchResponse, + UrlReaderServiceReadTreeResponse, + UrlReaderServiceReadUrlOptions, + UrlReaderServiceReadUrlResponse, + UrlReaderServiceSearchResponse, } from '@backstage/backend-plugin-api'; import { ReaderFactory } from './types'; import getRawBody from 'raw-body'; @@ -106,18 +106,18 @@ export class GoogleGcsUrlReader implements UrlReaderService { async readUrl( url: string, - _options?: UrlReaderReadUrlOptions, - ): Promise { + _options?: UrlReaderServiceReadUrlOptions, + ): Promise { // TODO etag is not implemented yet. const stream = this.readStreamFromUrl(url); return ReadUrlResponseFactory.fromReadable(stream); } - async readTree(): Promise { + async readTree(): Promise { throw new Error('GcsUrlReader does not implement readTree'); } - async search(url: string): Promise { + async search(url: string): Promise { const { bucket, key: pattern } = parseURL(url); if (!pattern.endsWith('*') || pattern.indexOf('*') !== pattern.length - 1) { diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/HarnessUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/HarnessUrlReader.ts index 23b5284b43..622d7f3379 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/HarnessUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/HarnessUrlReader.ts @@ -16,11 +16,11 @@ import { UrlReaderService, - UrlReaderReadTreeResponse, - UrlReaderReadUrlOptions, - UrlReaderReadUrlResponse, - UrlReaderSearchResponse, - UrlReaderReadTreeOptions, + UrlReaderServiceReadTreeResponse, + UrlReaderServiceReadUrlOptions, + UrlReaderServiceReadUrlResponse, + UrlReaderServiceSearchResponse, + UrlReaderServiceReadTreeOptions, } from '@backstage/backend-plugin-api'; import { getHarnessRequestOptions, @@ -75,8 +75,8 @@ export class HarnessUrlReader implements UrlReaderService { async readUrl( url: string, - options?: UrlReaderReadUrlOptions, - ): Promise { + options?: UrlReaderServiceReadUrlOptions, + ): Promise { let response: Response; const blobUrl = getHarnessFileContentsUrl(this.integration.config, url); @@ -123,8 +123,8 @@ export class HarnessUrlReader implements UrlReaderService { async readTree( url: string, - options?: UrlReaderReadTreeOptions, - ): Promise { + options?: UrlReaderServiceReadTreeOptions, + ): Promise { const lastCommitHash = await this.getLastCommitHash(url); if (options?.etag && options.etag === lastCommitHash) { @@ -154,7 +154,7 @@ export class HarnessUrlReader implements UrlReaderService { }); } - search(): Promise { + search(): Promise { throw new Error('HarnessUrlReader search not implemented.'); } diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/ReadUrlResponseFactory.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/ReadUrlResponseFactory.ts index 805008c34e..ecc1bd6101 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/ReadUrlResponseFactory.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/ReadUrlResponseFactory.ts @@ -15,7 +15,7 @@ */ import { ConflictError } from '@backstage/errors'; -import { UrlReaderReadUrlResponse } from '@backstage/backend-plugin-api'; +import { UrlReaderServiceReadUrlResponse } from '@backstage/backend-plugin-api'; import getRawBody from 'raw-body'; import { Readable } from 'stream'; import { ReadUrlResponseFactoryFromStreamOptions } from './types'; @@ -33,7 +33,7 @@ export class ReadUrlResponseFactory { static async fromReadable( stream: Readable, options?: ReadUrlResponseFactoryFromStreamOptions, - ): Promise { + ): Promise { // Reference to eventual buffer enables callers to call buffer() multiple // times without consequence. let buffer: Promise; @@ -69,7 +69,7 @@ export class ReadUrlResponseFactory { static async fromNodeJSReadable( oldStyleStream: NodeJS.ReadableStream, options?: ReadUrlResponseFactoryFromStreamOptions, - ): Promise { + ): Promise { const readable = Readable.from(oldStyleStream); return ReadUrlResponseFactory.fromReadable(readable, options); } diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/UrlReaderPredicateMux.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/UrlReaderPredicateMux.ts index b6db60af0a..fb57bb0f06 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/UrlReaderPredicateMux.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/UrlReaderPredicateMux.ts @@ -15,12 +15,12 @@ */ import { - UrlReaderReadTreeOptions, - UrlReaderReadTreeResponse, - UrlReaderReadUrlOptions, - UrlReaderReadUrlResponse, - UrlReaderSearchOptions, - UrlReaderSearchResponse, + UrlReaderServiceReadTreeOptions, + UrlReaderServiceReadTreeResponse, + UrlReaderServiceReadUrlOptions, + UrlReaderServiceReadUrlResponse, + UrlReaderServiceSearchOptions, + UrlReaderServiceSearchResponse, UrlReaderService, } from '@backstage/backend-plugin-api'; import { NotAllowedError } from '@backstage/errors'; @@ -47,8 +47,8 @@ export class UrlReaderPredicateMux implements UrlReaderService { async readUrl( url: string, - options?: UrlReaderReadUrlOptions, - ): Promise { + options?: UrlReaderServiceReadUrlOptions, + ): Promise { const parsed = new URL(url); for (const { predicate, reader } of this.readers) { @@ -62,8 +62,8 @@ export class UrlReaderPredicateMux implements UrlReaderService { async readTree( url: string, - options?: UrlReaderReadTreeOptions, - ): Promise { + options?: UrlReaderServiceReadTreeOptions, + ): Promise { const parsed = new URL(url); for (const { predicate, reader } of this.readers) { @@ -77,8 +77,8 @@ export class UrlReaderPredicateMux implements UrlReaderService { async search( url: string, - options?: UrlReaderSearchOptions, - ): Promise { + options?: UrlReaderServiceSearchOptions, + ): Promise { const parsed = new URL(url); for (const { predicate, reader } of this.readers) { diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/tree/ReadTreeResponseFactory.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/tree/ReadTreeResponseFactory.ts index e61ce3242e..1973b2158f 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/tree/ReadTreeResponseFactory.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/tree/ReadTreeResponseFactory.ts @@ -24,7 +24,7 @@ import { import { TarArchiveResponse } from './TarArchiveResponse'; import { ZipArchiveResponse } from './ZipArchiveResponse'; import { ReadableArrayResponse } from './ReadableArrayResponse'; -import { UrlReaderReadTreeResponse } from '@backstage/backend-plugin-api'; +import { UrlReaderServiceReadTreeResponse } from '@backstage/backend-plugin-api'; export class DefaultReadTreeResponseFactory implements ReadTreeResponseFactory { static create(options: { config: Config }): DefaultReadTreeResponseFactory { @@ -40,7 +40,7 @@ export class DefaultReadTreeResponseFactory implements ReadTreeResponseFactory { options: ReadTreeResponseFactoryOptions & { stripFirstDirectory?: boolean; }, - ): Promise { + ): Promise { return new TarArchiveResponse( options.stream, options.subpath ?? '', @@ -53,7 +53,7 @@ export class DefaultReadTreeResponseFactory implements ReadTreeResponseFactory { async fromZipArchive( options: ReadTreeResponseFactoryOptions, - ): Promise { + ): Promise { return new ZipArchiveResponse( options.stream, options.subpath ?? '', @@ -65,7 +65,7 @@ export class DefaultReadTreeResponseFactory implements ReadTreeResponseFactory { async fromReadableArray( options: FromReadableArrayOptions, - ): Promise { + ): Promise { return new ReadableArrayResponse(options, this.workDir, ''); } } diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/tree/ReadableArrayResponse.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/tree/ReadableArrayResponse.ts index 4e1b24f47f..6b39672ddd 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/tree/ReadableArrayResponse.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/tree/ReadableArrayResponse.ts @@ -15,9 +15,9 @@ */ import { - UrlReaderReadTreeResponse, - UrlReaderReadTreeResponseDirOptions, - UrlReaderReadTreeResponseFile, + UrlReaderServiceReadTreeResponse, + UrlReaderServiceReadTreeResponseDirOptions, + UrlReaderServiceReadTreeResponseFile, } from '@backstage/backend-plugin-api'; import concatStream from 'concat-stream'; import platformPath, { dirname } from 'path'; @@ -33,7 +33,7 @@ const pipeline = promisify(pipelineCb); /** * Wraps a array of Readable objects into a tree response reader. */ -export class ReadableArrayResponse implements UrlReaderReadTreeResponse { +export class ReadableArrayResponse implements UrlReaderServiceReadTreeResponse { private read = false; constructor( @@ -52,10 +52,10 @@ export class ReadableArrayResponse implements UrlReaderReadTreeResponse { this.read = true; } - async files(): Promise { + async files(): Promise { this.onlyOnce(); - const files = Array(); + const files = Array(); for (let i = 0; i < this.stream.length; i++) { if (!this.stream[i].path.endsWith('/')) { @@ -86,7 +86,9 @@ export class ReadableArrayResponse implements UrlReaderReadTreeResponse { } } - async dir(options?: UrlReaderReadTreeResponseDirOptions): Promise { + async dir( + options?: UrlReaderServiceReadTreeResponseDirOptions, + ): Promise { this.onlyOnce(); const dir = diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/tree/TarArchiveResponse.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/tree/TarArchiveResponse.ts index 59b750eb1e..9fb1d3fe7e 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/tree/TarArchiveResponse.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/tree/TarArchiveResponse.ts @@ -15,9 +15,9 @@ */ import { - UrlReaderReadTreeResponse, - UrlReaderReadTreeResponseDirOptions, - UrlReaderReadTreeResponseFile, + UrlReaderServiceReadTreeResponse, + UrlReaderServiceReadTreeResponseDirOptions, + UrlReaderServiceReadTreeResponseFile, } from '@backstage/backend-plugin-api'; import concatStream from 'concat-stream'; import fs from 'fs-extra'; @@ -35,7 +35,7 @@ const pipeline = promisify(pipelineCb); /** * Wraps a tar archive stream into a tree response reader. */ -export class TarArchiveResponse implements UrlReaderReadTreeResponse { +export class TarArchiveResponse implements UrlReaderServiceReadTreeResponse { private read = false; constructor( @@ -68,10 +68,10 @@ export class TarArchiveResponse implements UrlReaderReadTreeResponse { this.read = true; } - async files(): Promise { + async files(): Promise { this.onlyOnce(); - const files = Array(); + const files = Array(); const parser = new TarParseStream(); parser.on('entry', (entry: ReadEntry & Readable) => { @@ -142,7 +142,9 @@ export class TarArchiveResponse implements UrlReaderReadTreeResponse { } } - async dir(options?: UrlReaderReadTreeResponseDirOptions): Promise { + async dir( + options?: UrlReaderServiceReadTreeResponseDirOptions, + ): Promise { this.onlyOnce(); const dir = diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/tree/ZipArchiveResponse.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/tree/ZipArchiveResponse.ts index 3d3b615ee7..5c0b6f77bc 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/tree/ZipArchiveResponse.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/tree/ZipArchiveResponse.ts @@ -15,9 +15,9 @@ */ import { - UrlReaderReadTreeResponse, - UrlReaderReadTreeResponseDirOptions, - UrlReaderReadTreeResponseFile, + UrlReaderServiceReadTreeResponse, + UrlReaderServiceReadTreeResponseDirOptions, + UrlReaderServiceReadTreeResponseFile, } from '@backstage/backend-plugin-api'; import archiver from 'archiver'; import yauzl, { Entry } from 'yauzl'; @@ -30,7 +30,7 @@ import { resolveSafeChildPath } from '@backstage/backend-plugin-api'; /** * Wraps a zip archive stream into a tree response reader. */ -export class ZipArchiveResponse implements UrlReaderReadTreeResponse { +export class ZipArchiveResponse implements UrlReaderServiceReadTreeResponse { private read = false; constructor( @@ -141,9 +141,9 @@ export class ZipArchiveResponse implements UrlReaderReadTreeResponse { }); } - async files(): Promise { + async files(): Promise { this.onlyOnce(); - const files = Array(); + const files = Array(); const temporary = await this.streamToTemporaryFile(this.stream); await this.forEveryZipEntry(temporary.fileName, async (entry, content) => { @@ -184,7 +184,9 @@ export class ZipArchiveResponse implements UrlReaderReadTreeResponse { return archive; } - async dir(options?: UrlReaderReadTreeResponseDirOptions): Promise { + async dir( + options?: UrlReaderServiceReadTreeResponseDirOptions, + ): Promise { this.onlyOnce(); const dir = options?.targetDir ?? diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/types.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/types.ts index 254fe1dcec..510b12545f 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/types.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/types.ts @@ -18,7 +18,7 @@ import { Readable } from 'stream'; import { Config } from '@backstage/config'; import { UrlReaderService, - UrlReaderReadTreeResponse, + UrlReaderServiceReadTreeResponse, LoggerService, } from '@backstage/backend-plugin-api'; @@ -110,11 +110,11 @@ export interface ReadTreeResponseFactory { */ stripFirstDirectory?: boolean; }, - ): Promise; + ): Promise; fromZipArchive( options: ReadTreeResponseFactoryOptions, - ): Promise; + ): Promise; fromReadableArray( options: FromReadableArrayOptions, - ): Promise; + ): Promise; } diff --git a/packages/backend-defaults/src/entrypoints/urlReader/urlReaderServiceFactory.ts b/packages/backend-defaults/src/entrypoints/urlReader/urlReaderServiceFactory.ts index dae8d692cb..810882edf8 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/urlReaderServiceFactory.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/urlReaderServiceFactory.ts @@ -20,7 +20,15 @@ import { createServiceFactory, } from '@backstage/backend-plugin-api'; -/** @public */ +/** + * Reading content from external systems. + * + * See {@link @backstage/code-plugin-api#UrlReaderService} + * and {@link https://backstage.io/docs/backend-system/core-services/url-reader | the service docs} + * for more information. + * + * @public + */ export const urlReaderServiceFactory = createServiceFactory({ service: coreServices.urlReader, deps: { diff --git a/packages/backend-defaults/src/entrypoints/userInfo/DefaultUserInfoService.test.ts b/packages/backend-defaults/src/entrypoints/userInfo/DefaultUserInfoService.test.ts new file mode 100644 index 0000000000..b63b24fb18 --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/userInfo/DefaultUserInfoService.test.ts @@ -0,0 +1,169 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { BackstageUserPrincipal } from '@backstage/backend-plugin-api'; +import { + mockServices, + setupRequestMockHandlers, +} from '@backstage/backend-test-utils'; +import { JsonObject } from '@backstage/types'; +import { SignJWT, base64url, importJWK } from 'jose'; +import { rest } from 'msw'; +import { setupServer } from 'msw/node'; +import { InternalBackstageCredentials } from '../auth/types'; +import { DefaultUserInfoService } from './DefaultUserInfoService'; + +describe('DefaultUserInfoService', () => { + const server = setupServer(); + setupRequestMockHandlers(server); + + const mockPublicKey = { + kty: 'EC', + x: 'GHlwg744e8JekzukPTdtix6R868D6fcWy0ooOx-NEZI', + y: 'Lyujcm0M6X9_yQi3l1eH09z0brU8K9cwrLml_fRFKro', + crv: 'P-256', + kid: 'mock', + alg: 'ES256', + }; + const mockPrivateKey = { + ...mockPublicKey, + d: 'KEn_mDqXYbZdRHb-JnCrW53LDOv5x4NL1FnlKcqBsFI', + }; + + function encodeData(data: JsonObject) { + return base64url.encode(JSON.stringify(data)); + } + + async function createToken(options: { + header: JsonObject; + payload: JsonObject; + signature?: string; + }) { + if (options.signature) { + const header = encodeData(options.header); + const payload = encodeData(options.payload); + + return `${header}.${payload}.${options.signature}`; + } + + return await new SignJWT(options.payload) + .setProtectedHeader({ ...options.header, alg: 'ES256' }) + .sign(await importJWK(mockPrivateKey)); + } + + const discovery = mockServices.discovery.mock({ + getBaseUrl: async pluginId => `https://example.com/api/${pluginId}`, + }); + + it('makes the expected call when no ent in the token', async () => { + const token = await createToken({ + header: { + typ: 'vnd.backstage.user', + alg: 'ES256', + kid: mockPublicKey.kid, + }, + payload: { + sub: 'user:default/alice', + }, + }); + const credentials = { + $$type: '@backstage/BackstageCredentials', + version: 'v1', + token: token, + principal: { + type: 'user', + userEntityRef: 'user:default/alice', + }, + } as InternalBackstageCredentials; + + server.use( + rest.get('https://example.com/api/auth/v1/userinfo', (req, res, ctx) => { + expect(req.headers.get('authorization')).toBe(`Bearer ${token}`); + return res(ctx.json({ claims: { ent: ['group:default/my-team'] } })); + }), + ); + + const service = new DefaultUserInfoService({ discovery }); + await expect(service.getUserInfo(credentials)).resolves.toEqual({ + userEntityRef: 'user:default/alice', + ownershipEntityRefs: ['group:default/my-team'], + }); + }); + + it('uses the ent from the token when present', async () => { + const token = await createToken({ + header: { + typ: 'vnd.backstage.user', + alg: 'ES256', + kid: mockPublicKey.kid, + }, + payload: { + sub: 'user:default/alice', + ent: ['group:default/my-team'], + }, + }); + const credentials = { + $$type: '@backstage/BackstageCredentials', + version: 'v1', + token: token, + principal: { + type: 'user', + userEntityRef: 'user:default/alice', + }, + } as InternalBackstageCredentials; + + const service = new DefaultUserInfoService({ discovery }); + await expect(service.getUserInfo(credentials)).resolves.toEqual({ + userEntityRef: 'user:default/alice', + ownershipEntityRefs: ['group:default/my-team'], + }); + }); + + it('passes on server errors', async () => { + const token = await createToken({ + header: { + typ: 'vnd.backstage.user', + alg: 'ES256', + kid: mockPublicKey.kid, + }, + payload: { + sub: 'user:default/alice', + }, + }); + const credentials = { + $$type: '@backstage/BackstageCredentials', + version: 'v1', + token: token, + principal: { + type: 'user', + userEntityRef: 'user:default/alice', + }, + } as InternalBackstageCredentials; + + server.use( + rest.get('https://example.com/api/auth/v1/userinfo', (_req, res, ctx) => { + return res(ctx.status(404)); + }), + ); + + const service = new DefaultUserInfoService({ discovery }); + await expect( + service.getUserInfo(credentials), + ).rejects.toMatchInlineSnapshot( + `[ResponseError: Request failed with 404 Not Found]`, + ); + }); +}); diff --git a/packages/backend-defaults/src/entrypoints/userInfo/DefaultUserInfoService.ts b/packages/backend-defaults/src/entrypoints/userInfo/DefaultUserInfoService.ts new file mode 100644 index 0000000000..83bbba89b7 --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/userInfo/DefaultUserInfoService.ts @@ -0,0 +1,90 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + UserInfoService, + BackstageUserInfo, + DiscoveryService, + BackstageCredentials, +} from '@backstage/backend-plugin-api'; +import { ResponseError } from '@backstage/errors'; +import { decodeJwt } from 'jose'; +import fetch from 'node-fetch'; +import { toInternalBackstageCredentials } from '../auth/helpers'; + +export type Options = { + discovery: DiscoveryService; +}; + +export class DefaultUserInfoService implements UserInfoService { + private readonly discovery: DiscoveryService; + + constructor(options: Options) { + this.discovery = options.discovery; + } + + async getUserInfo( + credentials: BackstageCredentials, + ): Promise { + const internalCredentials = toInternalBackstageCredentials(credentials); + if (internalCredentials.principal.type !== 'user') { + throw new Error('Only user credentials are supported'); + } + if (!internalCredentials.token) { + throw new Error('User credentials is unexpectedly missing token'); + } + const { sub: userEntityRef, ent: tokenEnt } = decodeJwt( + internalCredentials.token, + ); + + if (typeof userEntityRef !== 'string') { + throw new Error('User entity ref must be a string'); + } + + let ownershipEntityRefs = tokenEnt; + + if (!ownershipEntityRefs) { + const userInfoResp = await fetch( + `${await this.discovery.getBaseUrl('auth')}/v1/userinfo`, + { + headers: { + Authorization: `Bearer ${internalCredentials.token}`, + }, + }, + ); + + if (!userInfoResp.ok) { + throw await ResponseError.fromResponse(userInfoResp); + } + + const { + claims: { ent }, + } = await userInfoResp.json(); + ownershipEntityRefs = ent; + } + + if (!ownershipEntityRefs) { + throw new Error('Ownership entity refs can not be determined'); + } else if ( + !Array.isArray(ownershipEntityRefs) || + ownershipEntityRefs.some(ref => typeof ref !== 'string') + ) { + throw new Error('Ownership entity refs must be an array of strings'); + } + + return { userEntityRef, ownershipEntityRefs }; + } +} diff --git a/packages/backend-defaults/src/entrypoints/userInfo/index.ts b/packages/backend-defaults/src/entrypoints/userInfo/index.ts new file mode 100644 index 0000000000..13b42f053c --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/userInfo/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { userInfoServiceFactory } from './userInfoServiceFactory'; diff --git a/packages/backend-defaults/src/entrypoints/userInfo/userInfoServiceFactory.ts b/packages/backend-defaults/src/entrypoints/userInfo/userInfoServiceFactory.ts new file mode 100644 index 0000000000..fe8c398bca --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/userInfo/userInfoServiceFactory.ts @@ -0,0 +1,40 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + coreServices, + createServiceFactory, +} from '@backstage/backend-plugin-api'; +import { DefaultUserInfoService } from './DefaultUserInfoService'; + +/** + * Authenticated user information retrieval. + * + * See {@link @backstage/code-plugin-api#UserInfoService} + * and {@link https://backstage.io/docs/backend-system/core-services/user-info | the service docs} + * for more information. + * + * @public + */ +export const userInfoServiceFactory = createServiceFactory({ + service: coreServices.userInfo, + deps: { + discovery: coreServices.discovery, + }, + async factory({ discovery }) { + return new DefaultUserInfoService({ discovery }); + }, +}); diff --git a/packages/backend-defaults/src/index.ts b/packages/backend-defaults/src/index.ts index d3e36cf0fb..b00c865524 100644 --- a/packages/backend-defaults/src/index.ts +++ b/packages/backend-defaults/src/index.ts @@ -20,9 +20,4 @@ * @packageDocumentation */ -// This import is here as a workaround for a cyclic dependency bug where -// backend-common must be loaded before backend-app-api -// TODO(Rugvip): Remove this once backend-common is no longer used by backend-app-api -import '@backstage/backend-common'; - export { createBackend } from './CreateBackend'; diff --git a/packages/backend-app-api/src/lib/escapeRegExp.test.ts b/packages/backend-defaults/src/lib/escapeRegExp.test.ts similarity index 100% rename from packages/backend-app-api/src/lib/escapeRegExp.test.ts rename to packages/backend-defaults/src/lib/escapeRegExp.test.ts diff --git a/packages/backend-app-api/src/lib/escapeRegExp.ts b/packages/backend-defaults/src/lib/escapeRegExp.ts similarity index 100% rename from packages/backend-app-api/src/lib/escapeRegExp.ts rename to packages/backend-defaults/src/lib/escapeRegExp.ts diff --git a/packages/backend-common/src/urls.test.ts b/packages/backend-defaults/src/lib/urls.test.ts similarity index 100% rename from packages/backend-common/src/urls.test.ts rename to packages/backend-defaults/src/lib/urls.test.ts diff --git a/packages/backend-common/src/urls.ts b/packages/backend-defaults/src/lib/urls.ts similarity index 100% rename from packages/backend-common/src/urls.ts rename to packages/backend-defaults/src/lib/urls.ts diff --git a/packages/backend-dynamic-feature-service/CHANGELOG.md b/packages/backend-dynamic-feature-service/CHANGELOG.md index 007951a732..4ec9489674 100644 --- a/packages/backend-dynamic-feature-service/CHANGELOG.md +++ b/packages/backend-dynamic-feature-service/CHANGELOG.md @@ -1,5 +1,84 @@ # @backstage/backend-dynamic-feature-service +## 0.2.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/plugin-scaffolder-node@0.4.7-next.0 + - @backstage/backend-app-api@0.7.9-next.0 + - @backstage/plugin-app-node@0.1.21-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/plugin-catalog-backend@1.23.2-next.0 + - @backstage/plugin-events-backend@0.3.8-next.0 + - @backstage/plugin-events-node@0.3.7-next.0 + - @backstage/plugin-permission-node@0.7.32-next.0 + - @backstage/plugin-search-backend-node@1.2.26-next.0 + - @backstage/cli-common@0.1.14 + - @backstage/cli-node@0.2.6 + - @backstage/config@1.2.0 + - @backstage/config-loader@1.8.1 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.14 + - @backstage/plugin-search-common@1.2.12 + +## 0.2.11 + +### Patch Changes + +- 78a0b08: Internal refactor to handle `BackendFeature` contract change. +- Updated dependencies + - @backstage/cli-node@0.2.6 + - @backstage/backend-app-api@0.7.6 + - @backstage/backend-common@0.23.0 + - @backstage/backend-plugin-api@0.6.19 + - @backstage/backend-tasks@0.5.24 + - @backstage/plugin-auth-node@0.4.14 + - @backstage/plugin-catalog-backend@1.23.0 + - @backstage/plugin-events-backend@0.3.6 + - @backstage/plugin-search-backend-node@1.2.24 + - @backstage/plugin-events-node@0.3.5 + - @backstage/plugin-permission-node@0.7.30 + - @backstage/plugin-permission-common@0.7.14 + - @backstage/plugin-scaffolder-node@0.4.5 + - @backstage/plugin-search-common@1.2.12 + - @backstage/plugin-app-node@0.1.19 + - @backstage/cli-common@0.1.14 + - @backstage/config-loader@1.8.1 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + +## 0.2.11-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/cli-node@0.2.6-next.2 + - @backstage/backend-plugin-api@0.6.19-next.3 + - @backstage/plugin-auth-node@0.4.14-next.3 + - @backstage/plugin-search-backend-node@1.2.24-next.3 + - @backstage/plugin-permission-common@0.7.14-next.0 + - @backstage/plugin-catalog-backend@1.23.0-next.3 + - @backstage/plugin-permission-node@0.7.30-next.3 + - @backstage/plugin-scaffolder-node@0.4.5-next.3 + - @backstage/plugin-events-backend@0.3.6-next.3 + - @backstage/plugin-search-common@1.2.12-next.0 + - @backstage/plugin-events-node@0.3.5-next.2 + - @backstage/plugin-app-node@0.1.19-next.2 + - @backstage/cli-common@0.1.14-next.0 + - @backstage/backend-tasks@0.5.24-next.3 + - @backstage/backend-common@0.23.0-next.3 + - @backstage/backend-app-api@0.7.6-next.3 + - @backstage/config-loader@1.8.1-next.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + ## 0.2.11-next.2 ### Patch Changes diff --git a/packages/backend-dynamic-feature-service/api-report.md b/packages/backend-dynamic-feature-service/api-report.md index 57b2228975..20db7db71b 100644 --- a/packages/backend-dynamic-feature-service/api-report.md +++ b/packages/backend-dynamic-feature-service/api-report.md @@ -4,6 +4,7 @@ ```ts import { BackendFeature } from '@backstage/backend-plugin-api'; +import { BackendFeatureCompat } from '@backstage/backend-plugin-api'; import { BackstagePackageJson } from '@backstage/cli-node'; import { CatalogBuilder } from '@backstage/plugin-catalog-backend'; import { Config } from '@backstage/config'; @@ -119,7 +120,7 @@ export const dynamicPluginsFeatureDiscoveryServiceFactory: () => ServiceFactory< >; // @public (undocumented) -export const dynamicPluginsFrontendSchemas: () => BackendFeature; +export const dynamicPluginsFrontendSchemas: BackendFeatureCompat; // @public (undocumented) export const dynamicPluginsRootLoggerServiceFactory: () => ServiceFactory< diff --git a/packages/backend-dynamic-feature-service/package.json b/packages/backend-dynamic-feature-service/package.json index 54a76df87a..60ff4d2d4e 100644 --- a/packages/backend-dynamic-feature-service/package.json +++ b/packages/backend-dynamic-feature-service/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-dynamic-feature-service", "description": "Backstage dynamic feature service", - "version": "0.2.11-next.2", + "version": "0.2.14-next.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-dynamic-feature-service/src/manager/plugin-manager.test.ts b/packages/backend-dynamic-feature-service/src/manager/plugin-manager.test.ts index 340991b11f..8531624509 100644 --- a/packages/backend-dynamic-feature-service/src/manager/plugin-manager.test.ts +++ b/packages/backend-dynamic-feature-service/src/manager/plugin-manager.test.ts @@ -154,9 +154,9 @@ describe('backend-dynamic-feature-service', () => { const installer: NewBackendPluginInstaller = ( plugins[0] as BackendDynamicPlugin ).installer as NewBackendPluginInstaller; - expect(installer.install()).toEqual< - BackendFeature | BackendFeature[] - >({ $$type: '@backstage/BackendFeature' }); + expect((installer.install() as BackendFeature).$$type).toEqual( + '@backstage/BackendFeature', + ); }, }, { @@ -199,9 +199,9 @@ describe('backend-dynamic-feature-service', () => { const installer: NewBackendPluginInstaller = ( plugins[0] as BackendDynamicPlugin ).installer as NewBackendPluginInstaller; - expect(installer.install()).toEqual< - BackendFeature | BackendFeature[] - >({ $$type: '@backstage/BackendFeature' }); + expect((installer.install() as BackendFeature).$$type).toEqual( + '@backstage/BackendFeature', + ); }, }, { diff --git a/packages/backend-legacy/CHANGELOG.md b/packages/backend-legacy/CHANGELOG.md index 33d3a78ffd..9535ba1211 100644 --- a/packages/backend-legacy/CHANGELOG.md +++ b/packages/backend-legacy/CHANGELOG.md @@ -1,5 +1,131 @@ # example-backend-legacy +## 0.2.100-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/plugin-scaffolder-backend-module-gitlab@0.4.3-next.0 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.38-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/plugin-scaffolder-backend@1.23.0-next.0 + - @backstage/plugin-app-backend@0.3.70-next.0 + - @backstage/plugin-auth-backend@0.22.8-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/plugin-catalog-backend@1.23.2-next.0 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.19-next.0 + - @backstage/plugin-catalog-backend-module-unprocessed@0.4.8-next.0 + - @backstage/plugin-catalog-node@1.12.3-next.0 + - @backstage/plugin-devtools-backend@0.3.7-next.0 + - @backstage/plugin-events-backend@0.3.8-next.0 + - @backstage/plugin-events-node@0.3.7-next.0 + - @backstage/plugin-kubernetes-backend@0.18.2-next.0 + - @backstage/plugin-permission-backend@0.5.45-next.0 + - @backstage/plugin-permission-node@0.7.32-next.0 + - @backstage/plugin-proxy-backend@0.5.2-next.0 + - @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.22-next.0 + - @backstage/plugin-search-backend@1.5.13-next.0 + - @backstage/plugin-search-backend-module-catalog@0.1.27-next.0 + - @backstage/plugin-search-backend-module-elasticsearch@1.5.2-next.0 + - @backstage/plugin-search-backend-module-explore@0.1.27-next.0 + - @backstage/plugin-search-backend-module-pg@0.5.31-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.1.26-next.0 + - @backstage/plugin-search-backend-node@1.2.26-next.0 + - @backstage/plugin-signals-backend@0.1.7-next.0 + - @backstage/plugin-signals-node@0.1.7-next.0 + - @backstage/plugin-techdocs-backend@1.10.8-next.0 + - example-app@0.2.99-next.0 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/plugin-permission-common@0.7.14 + +## 0.2.99 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.23.0 + - @backstage/backend-tasks@0.5.24 + - @backstage/plugin-auth-node@0.4.14 + - @backstage/plugin-auth-backend@0.22.6 + - @backstage/plugin-techdocs-backend@1.10.6 + - @backstage/plugin-devtools-backend@0.3.5 + - @backstage/plugin-catalog-backend@1.23.0 + - @backstage/plugin-search-backend@1.5.10 + - @backstage/plugin-proxy-backend@0.5.0 + - @backstage/plugin-app-backend@0.3.68 + - @backstage/integration@1.12.0 + - @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.20 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.17 + - @backstage/plugin-search-backend-module-elasticsearch@1.5.0 + - @backstage/plugin-catalog-backend-module-unprocessed@0.4.6 + - @backstage/plugin-scaffolder-backend-module-gitlab@0.4.1 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.36 + - @backstage/plugin-search-backend-module-techdocs@0.1.24 + - @backstage/plugin-search-backend-module-catalog@0.1.25 + - @backstage/plugin-search-backend-module-explore@0.1.25 + - @backstage/plugin-search-backend-module-pg@0.5.28 + - @backstage/plugin-kubernetes-backend@0.18.0 + - @backstage/plugin-permission-backend@0.5.43 + - @backstage/plugin-scaffolder-backend@1.22.9 + - @backstage/plugin-signals-backend@0.1.5 + - @backstage/plugin-events-backend@0.3.6 + - @backstage/plugin-catalog-node@1.12.1 + - @backstage/plugin-search-backend-node@1.2.24 + - @backstage/plugin-events-node@0.3.5 + - @backstage/plugin-permission-node@0.7.30 + - @backstage/plugin-permission-common@0.7.14 + - @backstage/plugin-signals-node@0.1.5 + - example-app@0.2.98 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + +## 0.2.99-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.14-next.3 + - @backstage/integration@1.12.0-next.1 + - @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.20-next.3 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.17-next.3 + - @backstage/plugin-search-backend-module-elasticsearch@1.4.2-next.3 + - @backstage/plugin-catalog-backend-module-unprocessed@0.4.6-next.3 + - @backstage/plugin-scaffolder-backend-module-gitlab@0.4.1-next.3 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.36-next.3 + - @backstage/plugin-search-backend-module-techdocs@0.1.24-next.3 + - @backstage/plugin-search-backend-module-catalog@0.1.25-next.3 + - @backstage/plugin-search-backend-module-explore@0.1.25-next.3 + - @backstage/plugin-search-backend-module-pg@0.5.28-next.3 + - @backstage/plugin-search-backend-node@1.2.24-next.3 + - @backstage/plugin-kubernetes-backend@0.18.0-next.3 + - @backstage/plugin-permission-backend@0.5.43-next.3 + - @backstage/plugin-scaffolder-backend@1.22.8-next.3 + - @backstage/plugin-permission-common@0.7.14-next.0 + - @backstage/plugin-devtools-backend@0.3.5-next.3 + - @backstage/plugin-techdocs-backend@1.10.6-next.3 + - @backstage/plugin-catalog-backend@1.23.0-next.3 + - @backstage/plugin-permission-node@0.7.30-next.3 + - @backstage/plugin-signals-backend@0.1.5-next.3 + - @backstage/plugin-events-backend@0.3.6-next.3 + - @backstage/plugin-search-backend@1.5.10-next.3 + - @backstage/plugin-proxy-backend@0.5.0-next.3 + - @backstage/plugin-auth-backend@0.22.6-next.3 + - @backstage/plugin-catalog-node@1.12.1-next.2 + - @backstage/plugin-signals-node@0.1.5-next.3 + - @backstage/plugin-app-backend@0.3.68-next.3 + - @backstage/plugin-events-node@0.3.5-next.2 + - @backstage/backend-tasks@0.5.24-next.3 + - @backstage/backend-common@0.23.0-next.3 + - example-app@0.2.98-next.3 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + ## 0.2.99-next.2 ### Patch Changes diff --git a/packages/backend-legacy/package.json b/packages/backend-legacy/package.json index 819a33ea5d..c8b019848f 100644 --- a/packages/backend-legacy/package.json +++ b/packages/backend-legacy/package.json @@ -1,6 +1,6 @@ { "name": "example-backend-legacy", - "version": "0.2.99-next.2", + "version": "0.2.100-next.0", "backstage": { "role": "backend" }, diff --git a/packages/backend-legacy/src/plugins/techdocs.ts b/packages/backend-legacy/src/plugins/techdocs.ts index 6e369f8f0f..21048d4bb9 100644 --- a/packages/backend-legacy/src/plugins/techdocs.ts +++ b/packages/backend-legacy/src/plugins/techdocs.ts @@ -14,14 +14,12 @@ * limitations under the License. */ -import { DockerContainerRunner } from '@backstage/backend-common'; import { createRouter, Generators, Preparers, Publisher, } from '@backstage/plugin-techdocs-backend'; -import Docker from 'dockerode'; import { Router } from 'express'; import { PluginEnvironment } from '../types'; @@ -34,14 +32,9 @@ export default async function createPlugin( reader: env.reader, }); - // Docker client (conditionally) used by the generators, based on techdocs.generators config. - const dockerClient = new Docker(); - const containerRunner = new DockerContainerRunner({ dockerClient }); - // Generators are used for generating documentation sites. const generators = await Generators.fromConfig(env.config, { logger: env.logger, - containerRunner, }); // Publisher is used for diff --git a/packages/backend-openapi-utils/CHANGELOG.md b/packages/backend-openapi-utils/CHANGELOG.md index c6cf035fcf..0040eddc57 100644 --- a/packages/backend-openapi-utils/CHANGELOG.md +++ b/packages/backend-openapi-utils/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/backend-openapi-utils +## 0.1.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/errors@1.2.4 + +## 0.1.12 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.19 + - @backstage/errors@1.2.4 + +## 0.1.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.19-next.3 + - @backstage/errors@1.2.4 + ## 0.1.12-next.1 ### Patch Changes diff --git a/packages/backend-openapi-utils/package.json b/packages/backend-openapi-utils/package.json index c50c9ec1f8..4b2551eb13 100644 --- a/packages/backend-openapi-utils/package.json +++ b/packages/backend-openapi-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-openapi-utils", "description": "OpenAPI typescript support.", - "version": "0.1.12-next.1", + "version": "0.1.14-next.0", "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 347f923808..b36d7a996d 100644 --- a/packages/backend-plugin-api/CHANGELOG.md +++ b/packages/backend-plugin-api/CHANGELOG.md @@ -1,5 +1,91 @@ # @backstage/backend-plugin-api +## 0.6.21-next.0 + +### Patch Changes + +- 53ced70: Added a new Root Health Service which adds new endpoints for health checks. +- 083eaf9: Fix bug where ISO durations could no longer be used for schedules +- Updated dependencies + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/cli-common@0.1.14 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.14 + +## 0.6.19 + +### Patch Changes + +- 78a0b08: **DEPRECATION**: You should no longer do a function call on backend features when adding them to backends. The support for doing that is deprecated, and you should remove all trailing `()` parentheses after plugins and modules where you add them to your backend or test backends (e.g. when using `startTestBackend`). + + The background for this is that `createBackendPlugin` and `createBackendModule` function now effectively return a `BackendFeature` rather than a `() => BackendFeature`. This is part of the cleanup efforts for New Backend System 1.0. In the short run this is non-breaking because the feature type has been given a callback signature that returns itself. But we strongly recommend that you remove all now-redundant calls made to feature objects, because that callback signature will be removed in a future release. + + Service factories are still callbacks at this point. + + Example change: + + ```diff + await startTestBackend({ + features: [ + eventsServiceFactory(), // service - stays unchanged + - catalogModuleBitbucketCloudEntityProvider(), // module - remove parentheses + + catalogModuleBitbucketCloudEntityProvider, + ``` + +- 9bdc3e8: In tests, return `null` rather than throwing an error when trying to get the `ExtensionPoint.T` property, so that tests asserting the property are not easily broken. +- 9e63318: Added an optional `accessRestrictions` to external access service tokens and service principals in general, such that you can limit their access to certain plugins or permissions. +- 3aa3fc7: Marked the `TokenManagerService` and `IdentityService` types as deprecated +- b2ee7f3: Deprecated all of the `UrlReader` related type names and replaced them with prefixed versions. Please update your imports. + + - `ReadTreeOptions` was renamed to `UrlReaderServiceReadTreeOptions` + - `ReadTreeResponse` was renamed to `UrlReaderServiceReadTreeResponse` + - `ReadTreeResponseDirOptions` was renamed to `UrlReaderServiceReadTreeResponseDirOptions` + - `ReadTreeResponseFile` was renamed to `UrlReaderServiceReadTreeResponseFile` + - `ReadUrlResponse` was renamed to `UrlReaderServiceReadUrlResponse` + - `ReadUrlOptions` was renamed to `UrlReaderServiceReadUrlOptions` + - `SearchOptions` was renamed to `UrlReaderServiceSearchOptions` + - `SearchResponse` was renamed to `UrlReaderServiceSearchResponse` + - `SearchResponseFile` was renamed to `UrlReaderServiceSearchResponseFile` + +- 9539a0b: Improved `coreServices` doc comments +- 6551b3d: Moved the declaration of the `SchedulerService` here, along with prefixed versions of all of the types it depends on, from `@backstage/backend-tasks` +- 0665b7e: Renamed `BackendPluginConfig`, `BackendModuleConfig`, and `ExtensionPointConfig` respectively to `CreateBackendPluginOptions`, `CreateBackendModuleOptions`, and `CreateExtensionPointOptions` to standardize frontend and backend factories signatures. +- 1779188: Start using the `isDatabaseConflictError` helper from the `@backstage/backend-plugin-api` package in order to avoid dependency with the soon to deprecate `@backstage/backend-common` package. +- Updated dependencies + - @backstage/plugin-auth-node@0.4.14 + - @backstage/plugin-permission-common@0.7.14 + - @backstage/cli-common@0.1.14 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + +## 0.6.19-next.3 + +### Patch Changes + +- 9bdc3e8: In tests, return `null` rather than throwing an error when trying to get the `ExtensionPoint.T` property, so that tests asserting the property are not easily broken. +- b2ee7f3: Deprecated all of the `UrlReader` related type names and replaced them with prefixed versions. Please update your imports. + + - `ReadTreeOptions` was renamed to `UrlReaderServiceReadTreeOptions` + - `ReadTreeResponse` was renamed to `UrlReaderServiceReadTreeResponse` + - `ReadTreeResponseDirOptions` was renamed to `UrlReaderServiceReadTreeResponseDirOptions` + - `ReadTreeResponseFile` was renamed to `UrlReaderServiceReadTreeResponseFile` + - `ReadUrlResponse` was renamed to `UrlReaderServiceReadUrlResponse` + - `ReadUrlOptions` was renamed to `UrlReaderServiceReadUrlOptions` + - `SearchOptions` was renamed to `UrlReaderServiceSearchOptions` + - `SearchResponse` was renamed to `UrlReaderServiceSearchResponse` + - `SearchResponseFile` was renamed to `UrlReaderServiceSearchResponseFile` + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.14-next.3 + - @backstage/plugin-permission-common@0.7.14-next.0 + - @backstage/cli-common@0.1.14-next.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + ## 0.6.19-next.2 ### Patch Changes diff --git a/packages/backend-plugin-api/api-report.md b/packages/backend-plugin-api/api-report.md index 5ba4e758ca..e9762f652e 100644 --- a/packages/backend-plugin-api/api-report.md +++ b/packages/backend-plugin-api/api-report.md @@ -63,6 +63,12 @@ export interface BackendFeature { $$type: '@backstage/BackendFeature'; } +// @public @deprecated (undocumented) +export interface BackendFeatureCompat extends BackendFeature { + // @deprecated (undocumented) + (): this; +} + // @public @deprecated (undocumented) export type BackendModuleConfig = CreateBackendModuleOptions; @@ -188,6 +194,7 @@ export namespace coreServices { const rootConfig: ServiceRef; const database: ServiceRef; const discovery: ServiceRef; + const rootHealth: ServiceRef; const httpAuth: ServiceRef; const httpRouter: ServiceRef; const lifecycle: ServiceRef; @@ -208,7 +215,7 @@ export namespace coreServices { // @public export function createBackendModule( options: CreateBackendModuleOptions, -): () => BackendFeature; +): BackendFeatureCompat; // @public export interface CreateBackendModuleOptions { @@ -221,7 +228,7 @@ export interface CreateBackendModuleOptions { // @public export function createBackendPlugin( options: CreateBackendPluginOptions, -): () => BackendFeature; +): BackendFeatureCompat; // @public export interface CreateBackendPluginOptions { @@ -467,22 +474,23 @@ export function readSchedulerServiceTaskScheduleDefinitionFromConfig( ): SchedulerServiceTaskScheduleDefinition; // @public @deprecated (undocumented) -export type ReadTreeOptions = UrlReaderReadTreeOptions; +export type ReadTreeOptions = UrlReaderServiceReadTreeOptions; // @public @deprecated (undocumented) -export type ReadTreeResponse = UrlReaderReadTreeResponse; +export type ReadTreeResponse = UrlReaderServiceReadTreeResponse; // @public @deprecated (undocumented) -export type ReadTreeResponseDirOptions = UrlReaderReadTreeResponseDirOptions; +export type ReadTreeResponseDirOptions = + UrlReaderServiceReadTreeResponseDirOptions; // @public @deprecated (undocumented) -export type ReadTreeResponseFile = UrlReaderReadTreeResponseFile; +export type ReadTreeResponseFile = UrlReaderServiceReadTreeResponseFile; // @public @deprecated (undocumented) -export type ReadUrlOptions = UrlReaderReadUrlOptions; +export type ReadUrlOptions = UrlReaderServiceReadUrlOptions; // @public @deprecated (undocumented) -export type ReadUrlResponse = UrlReaderReadUrlResponse; +export type ReadUrlResponse = UrlReaderServiceReadUrlResponse; // @public export function resolvePackagePath(name: string, ...paths: string[]): string; @@ -493,6 +501,18 @@ export function resolveSafeChildPath(base: string, path: string): string; // @public export interface RootConfigService extends Config {} +// @public (undocumented) +export interface RootHealthService { + getLiveness(): Promise<{ + status: number; + payload?: JsonValue; + }>; + getReadiness(): Promise<{ + status: number; + payload?: JsonValue; + }>; +} + // @public export interface RootHttpRouterService { use(path: string, handler: Handler): void; @@ -587,13 +607,13 @@ export interface SchedulerServiceTaskScheduleDefinitionConfig { } // @public @deprecated (undocumented) -export type SearchOptions = UrlReaderSearchOptions; +export type SearchOptions = UrlReaderServiceSearchOptions; // @public @deprecated (undocumented) -export type SearchResponse = UrlReaderSearchResponse; +export type SearchResponse = UrlReaderServiceSearchResponse; // @public @deprecated (undocumented) -export type SearchResponseFile = UrlReaderSearchResponseFile; +export type SearchResponseFile = UrlReaderServiceSearchResponseFile; // @public (undocumented) export interface ServiceFactory< @@ -639,7 +659,23 @@ export interface TokenManagerService { } // @public -export type UrlReaderReadTreeOptions = { +export interface UrlReaderService { + readTree( + url: string, + options?: UrlReaderServiceReadTreeOptions, + ): Promise; + readUrl( + url: string, + options?: UrlReaderServiceReadUrlOptions, + ): Promise; + search( + url: string, + options?: UrlReaderServiceSearchOptions, + ): Promise; +} + +// @public +export type UrlReaderServiceReadTreeOptions = { filter?( path: string, info?: { @@ -652,27 +688,27 @@ export type UrlReaderReadTreeOptions = { }; // @public -export type UrlReaderReadTreeResponse = { - files(): Promise; +export type UrlReaderServiceReadTreeResponse = { + files(): Promise; archive(): Promise; - dir(options?: UrlReaderReadTreeResponseDirOptions): Promise; + dir(options?: UrlReaderServiceReadTreeResponseDirOptions): Promise; etag: string; }; // @public -export type UrlReaderReadTreeResponseDirOptions = { +export type UrlReaderServiceReadTreeResponseDirOptions = { targetDir?: string; }; // @public -export type UrlReaderReadTreeResponseFile = { +export type UrlReaderServiceReadTreeResponseFile = { path: string; content(): Promise; lastModifiedAt?: Date; }; // @public -export type UrlReaderReadUrlOptions = { +export type UrlReaderServiceReadUrlOptions = { etag?: string; lastModifiedAfter?: Date; signal?: AbortSignal; @@ -680,7 +716,7 @@ export type UrlReaderReadUrlOptions = { }; // @public -export type UrlReaderReadUrlResponse = { +export type UrlReaderServiceReadUrlResponse = { buffer(): Promise; stream?(): Readable; etag?: string; @@ -688,41 +724,25 @@ export type UrlReaderReadUrlResponse = { }; // @public -export type UrlReaderSearchOptions = { +export type UrlReaderServiceSearchOptions = { etag?: string; signal?: AbortSignal; token?: string; }; // @public -export type UrlReaderSearchResponse = { - files: UrlReaderSearchResponseFile[]; +export type UrlReaderServiceSearchResponse = { + files: UrlReaderServiceSearchResponseFile[]; etag: string; }; // @public -export type UrlReaderSearchResponseFile = { +export type UrlReaderServiceSearchResponseFile = { url: string; content(): Promise; lastModifiedAt?: Date; }; -// @public -export interface UrlReaderService { - readTree( - url: string, - options?: UrlReaderReadTreeOptions, - ): Promise; - readUrl( - url: string, - options?: UrlReaderReadUrlOptions, - ): Promise; - search( - url: string, - options?: UrlReaderSearchOptions, - ): Promise; -} - // @public export interface UserInfoService { getUserInfo(credentials: BackstageCredentials): Promise; diff --git a/packages/backend-plugin-api/package.json b/packages/backend-plugin-api/package.json index da33828aae..dbb59f7991 100644 --- a/packages/backend-plugin-api/package.json +++ b/packages/backend-plugin-api/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/backend-plugin-api", - "version": "0.6.19-next.2", + "version": "0.6.21-next.0", "description": "Core API used by Backstage backend plugins", "backstage": { "role": "node-library" diff --git a/packages/backend-plugin-api/src/index.ts b/packages/backend-plugin-api/src/index.ts index c2e2a13a89..e6e57db1dc 100644 --- a/packages/backend-plugin-api/src/index.ts +++ b/packages/backend-plugin-api/src/index.ts @@ -21,6 +21,6 @@ */ export * from './services'; -export type { BackendFeature } from './types'; +export type { BackendFeature, BackendFeatureCompat } from './types'; export * from './paths'; export * from './wiring'; diff --git a/packages/backend-plugin-api/src/services/definitions/RootHealthService.ts b/packages/backend-plugin-api/src/services/definitions/RootHealthService.ts new file mode 100644 index 0000000000..e6c56e8654 --- /dev/null +++ b/packages/backend-plugin-api/src/services/definitions/RootHealthService.ts @@ -0,0 +1,31 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { JsonValue } from '@backstage/types'; + +/** + * @public + */ +export interface RootHealthService { + /** + * Get the liveness status of the backend. + */ + getLiveness(): Promise<{ status: number; payload?: JsonValue }>; + /** + * Get the readiness status of the backend. + */ + getReadiness(): Promise<{ status: number; payload?: JsonValue }>; +} diff --git a/packages/backend-plugin-api/src/services/definitions/SchedulerService.test.ts b/packages/backend-plugin-api/src/services/definitions/SchedulerService.test.ts index 7b20487af4..875e24786f 100644 --- a/packages/backend-plugin-api/src/services/definitions/SchedulerService.test.ts +++ b/packages/backend-plugin-api/src/services/definitions/SchedulerService.test.ts @@ -16,7 +16,6 @@ import { ConfigReader } from '@backstage/config'; import { HumanDuration } from '@backstage/types'; -import { Duration } from 'luxon'; import { readSchedulerServiceTaskScheduleDefinitionFromConfig } from './SchedulerService'; describe('readSchedulerServiceTaskScheduleDefinitionFromConfig', () => { @@ -35,7 +34,7 @@ describe('readSchedulerServiceTaskScheduleDefinitionFromConfig', () => { const result = readSchedulerServiceTaskScheduleDefinitionFromConfig(config); expect((result.frequency as { cron: string }).cron).toBe('0 30 * * * *'); - expect(result.timeout).toEqual(Duration.fromISO('PT3M')); + expect(result.timeout).toEqual({ minutes: 3 }); expect((result.initialDelay as HumanDuration).minutes).toEqual(20); expect(result.scope).toBe('global'); }); @@ -51,7 +50,7 @@ describe('readSchedulerServiceTaskScheduleDefinitionFromConfig', () => { const result = readSchedulerServiceTaskScheduleDefinitionFromConfig(config); expect((result.frequency as { cron: string }).cron).toBe('0 30 * * * *'); - expect(result.timeout).toEqual(Duration.fromISO('PT3M')); + expect(result.timeout).toEqual({ minutes: 3 }); expect(result.initialDelay).toBeUndefined(); expect(result.scope).toBeUndefined(); }); diff --git a/packages/backend-plugin-api/src/services/definitions/SchedulerService.ts b/packages/backend-plugin-api/src/services/definitions/SchedulerService.ts index 91edf27ad6..a7ec79a336 100644 --- a/packages/backend-plugin-api/src/services/definitions/SchedulerService.ts +++ b/packages/backend-plugin-api/src/services/definitions/SchedulerService.ts @@ -348,14 +348,14 @@ export interface SchedulerService { getScheduledTasks(): Promise; } -function readDuration(config: Config, key: string): Duration | HumanDuration { +function readDuration(config: Config, key: string): HumanDuration { if (typeof config.get(key) === 'string') { const value = config.getString(key); const duration = Duration.fromISO(value); if (!duration.isValid) { throw new Error(`Invalid duration: ${value}`); } - return duration; + return duration.toObject(); } return readDurationFromConfig(config, { key }); @@ -364,7 +364,7 @@ function readDuration(config: Config, key: string): Duration | HumanDuration { function readCronOrDuration( config: Config, key: string, -): { cron: string } | Duration | HumanDuration { +): { cron: string } | HumanDuration { const value = config.get(key); if (typeof value === 'object' && (value as { cron?: string }).cron) { return value as { cron: string }; diff --git a/packages/backend-plugin-api/src/services/definitions/UrlReaderService.ts b/packages/backend-plugin-api/src/services/definitions/UrlReaderService.ts index 085b0b6844..25b787107e 100644 --- a/packages/backend-plugin-api/src/services/definitions/UrlReaderService.ts +++ b/packages/backend-plugin-api/src/services/definitions/UrlReaderService.ts @@ -29,24 +29,24 @@ export interface UrlReaderService { */ readUrl( url: string, - options?: UrlReaderReadUrlOptions, - ): Promise; + options?: UrlReaderServiceReadUrlOptions, + ): Promise; /** * Reads a full or partial file tree. */ readTree( url: string, - options?: UrlReaderReadTreeOptions, - ): Promise; + options?: UrlReaderServiceReadTreeOptions, + ): Promise; /** * Searches for a file in a tree using a glob pattern. */ search( url: string, - options?: UrlReaderSearchOptions, - ): Promise; + options?: UrlReaderServiceSearchOptions, + ): Promise; } /** @@ -54,7 +54,7 @@ export interface UrlReaderService { * * @public */ -export type UrlReaderReadUrlOptions = { +export type UrlReaderServiceReadUrlOptions = { /** * An ETag which can be provided to check whether a * {@link UrlReaderService.readUrl} response has changed from a previous execution. @@ -122,7 +122,7 @@ export type UrlReaderReadUrlOptions = { * * @public */ -export type UrlReaderReadUrlResponse = { +export type UrlReaderServiceReadUrlResponse = { /** * Returns the data that was read from the remote URL. */ @@ -157,7 +157,7 @@ export type UrlReaderReadUrlResponse = { * * @public */ -export type UrlReaderReadTreeOptions = { +export type UrlReaderServiceReadTreeOptions = { /** * A filter that can be used to select which files should be included. * @@ -217,11 +217,11 @@ export type UrlReaderReadTreeOptions = { }; /** - * Options that control {@link UrlReaderReadTreeResponse.dir} execution. + * Options that control {@link UrlReaderServiceReadTreeResponse.dir} execution. * * @public */ -export type UrlReaderReadTreeResponseDirOptions = { +export type UrlReaderServiceReadTreeResponseDirOptions = { /** * The directory to write files to. * @@ -237,12 +237,12 @@ export type UrlReaderReadTreeResponseDirOptions = { * * @public */ -export type UrlReaderReadTreeResponse = { +export type UrlReaderServiceReadTreeResponse = { /** * Returns an array of all the files inside the tree, and corresponding * functions to read their content. */ - files(): Promise; + files(): Promise; /** * Returns the tree contents as a binary archive, using a stream. @@ -255,7 +255,7 @@ export type UrlReaderReadTreeResponse = { * * **NOTE**: It is the responsibility of the caller to remove the directory after use. */ - dir(options?: UrlReaderReadTreeResponseDirOptions): Promise; + dir(options?: UrlReaderServiceReadTreeResponseDirOptions): Promise; /** * Etag returned by content provider. @@ -272,7 +272,7 @@ export type UrlReaderReadTreeResponse = { * * @public */ -export type UrlReaderReadTreeResponseFile = { +export type UrlReaderServiceReadTreeResponseFile = { /** * The filepath of the data. */ @@ -294,7 +294,7 @@ export type UrlReaderReadTreeResponseFile = { * * @public */ -export type UrlReaderSearchOptions = { +export type UrlReaderServiceSearchOptions = { /** * An etag can be provided to check whether the search response has changed from a previous execution. * @@ -335,11 +335,11 @@ export type UrlReaderSearchOptions = { * * @public */ -export type UrlReaderSearchResponse = { +export type UrlReaderServiceSearchResponse = { /** * The files that matched the search query. */ - files: UrlReaderSearchResponseFile[]; + files: UrlReaderServiceSearchResponseFile[]; /** * A unique identifier of the current remote tree, usually the commit SHA or etag from the target. @@ -352,7 +352,7 @@ export type UrlReaderSearchResponse = { * * @public */ -export type UrlReaderSearchResponseFile = { +export type UrlReaderServiceSearchResponseFile = { /** * The full URL to the file. */ @@ -371,46 +371,47 @@ export type UrlReaderSearchResponseFile = { /** * @public - * @deprecated Use `UrlReaderReadTreeOptions` instead + * @deprecated Use `UrlReaderServiceReadTreeOptions` instead */ -export type ReadTreeOptions = UrlReaderReadTreeOptions; +export type ReadTreeOptions = UrlReaderServiceReadTreeOptions; /** * @public - * @deprecated Use `UrlReaderReadTreeResponse` instead + * @deprecated Use `UrlReaderServiceReadTreeResponse` instead */ -export type ReadTreeResponse = UrlReaderReadTreeResponse; +export type ReadTreeResponse = UrlReaderServiceReadTreeResponse; /** * @public - * @deprecated Use `UrlReaderReadTreeResponseDirOptions` instead + * @deprecated Use `UrlReaderServiceReadTreeResponseDirOptions` instead */ -export type ReadTreeResponseDirOptions = UrlReaderReadTreeResponseDirOptions; +export type ReadTreeResponseDirOptions = + UrlReaderServiceReadTreeResponseDirOptions; /** * @public - * @deprecated Use `UrlReaderReadTreeResponseFile` instead + * @deprecated Use `UrlReaderServiceReadTreeResponseFile` instead */ -export type ReadTreeResponseFile = UrlReaderReadTreeResponseFile; +export type ReadTreeResponseFile = UrlReaderServiceReadTreeResponseFile; /** * @public - * @deprecated Use `UrlReaderReadUrlResponse` instead + * @deprecated Use `UrlReaderServiceReadUrlResponse` instead */ -export type ReadUrlResponse = UrlReaderReadUrlResponse; +export type ReadUrlResponse = UrlReaderServiceReadUrlResponse; /** * @public - * @deprecated Use `UrlReaderReadUrlOptions` instead + * @deprecated Use `UrlReaderServiceReadUrlOptions` instead */ -export type ReadUrlOptions = UrlReaderReadUrlOptions; +export type ReadUrlOptions = UrlReaderServiceReadUrlOptions; /** * @public - * @deprecated Use `UrlReaderSearchOptions` instead + * @deprecated Use `UrlReaderServiceSearchOptions` instead */ -export type SearchOptions = UrlReaderSearchOptions; +export type SearchOptions = UrlReaderServiceSearchOptions; /** * @public - * @deprecated Use `UrlReaderSearchResponse` instead + * @deprecated Use `UrlReaderServiceSearchResponse` instead */ -export type SearchResponse = UrlReaderSearchResponse; +export type SearchResponse = UrlReaderServiceSearchResponse; /** * @public - * @deprecated Use `UrlReaderSearchResponseFile` instead + * @deprecated Use `UrlReaderServiceSearchResponseFile` instead */ -export type SearchResponseFile = UrlReaderSearchResponseFile; +export type SearchResponseFile = UrlReaderServiceSearchResponseFile; diff --git a/packages/backend-plugin-api/src/services/definitions/coreServices.ts b/packages/backend-plugin-api/src/services/definitions/coreServices.ts index 4e02611f80..33d1da2903 100644 --- a/packages/backend-plugin-api/src/services/definitions/coreServices.ts +++ b/packages/backend-plugin-api/src/services/definitions/coreServices.ts @@ -23,7 +23,11 @@ import { createServiceRef } from '../system'; */ export namespace coreServices { /** - * The service reference for the plugin scoped {@link AuthService}. + * Handles token authentication and credentials management. + * + * See {@link AuthService} + * and {@link https://backstage.io/docs/backend-system/core-services/auth | the service docs} + * for more information. * * @public */ @@ -32,7 +36,11 @@ export namespace coreServices { }); /** - * The service reference for the plugin scoped {@link UserInfoService}. + * Authenticated user information retrieval. + * + * See {@link UserInfoService} + * and {@link https://backstage.io/docs/backend-system/core-services/user-info | the service docs} + * for more information. * * @public */ @@ -43,7 +51,11 @@ export namespace coreServices { }); /** - * The service reference for the plugin scoped {@link CacheService}. + * Key-value store for caching data. + * + * See {@link CacheService} + * and {@link https://backstage.io/docs/backend-system/core-services/cache | the service docs} + * for more information. * * @public */ @@ -52,7 +64,11 @@ export namespace coreServices { }); /** - * The service reference for the root scoped {@link RootConfigService}. + * Access to static configuration. + * + * See {@link RootConfigService} + * and {@link https://backstage.io/docs/backend-system/core-services/root-config | the service docs} + * for more information. * * @public */ @@ -61,7 +77,11 @@ export namespace coreServices { >({ id: 'core.rootConfig', scope: 'root' }); /** - * The service reference for the plugin scoped {@link DatabaseService}. + * Database access and management via `knex`. + * + * See {@link DatabaseService} + * and {@link https://backstage.io/docs/backend-system/core-services/database | the service docs} + * for more information. * * @public */ @@ -70,7 +90,11 @@ export namespace coreServices { >({ id: 'core.database' }); /** - * The service reference for the plugin scoped {@link DiscoveryService}. + * Service discovery for inter-plugin communication. + * + * See {@link DiscoveryService} + * and {@link https://backstage.io/docs/backend-system/core-services/discovery | the service docs} + * for more information. * * @public */ @@ -79,7 +103,18 @@ export namespace coreServices { >({ id: 'core.discovery' }); /** - * The service reference for the plugin scoped {@link HttpAuthService}. + * The service reference for the plugin scoped {@link RootHealthService}. + */ + export const rootHealth = createServiceRef< + import('./RootHealthService').RootHealthService + >({ id: 'core.rootHealth', scope: 'root' }); + + /** + * Authentication of HTTP requests. + * + * See {@link HttpAuthService} + * and {@link https://backstage.io/docs/backend-system/core-services/http-auth | the service docs} + * for more information. * * @public */ @@ -88,7 +123,11 @@ export namespace coreServices { >({ id: 'core.httpAuth' }); /** - * The service reference for the plugin scoped {@link HttpRouterService}. + * HTTP route registration for plugins. + * + * See {@link HttpRouterService} + * and {@link https://backstage.io/docs/backend-system/core-services/http-router | the service docs} + * for more information. * * @public */ @@ -97,7 +136,11 @@ export namespace coreServices { >({ id: 'core.httpRouter' }); /** - * The service reference for the plugin scoped {@link LifecycleService}. + * Registration of plugin startup and shutdown lifecycle hooks. + * + * See {@link LifecycleService} + * and {@link https://backstage.io/docs/backend-system/core-services/lifecycle | the service docs} + * for more information. * * @public */ @@ -106,7 +149,11 @@ export namespace coreServices { >({ id: 'core.lifecycle' }); /** - * The service reference for the plugin scoped {@link LoggerService}. + * Plugin-level logging. + * + * See {@link LoggerService} + * and {@link https://backstage.io/docs/backend-system/core-services/logger | the service docs} + * for more information. * * @public */ @@ -115,7 +162,11 @@ export namespace coreServices { >({ id: 'core.logger' }); /** - * The service reference for the plugin scoped {@link PermissionsService}. + * Permission system integration for authorization of user actions. + * + * See {@link PermissionsService} + * and {@link https://backstage.io/docs/backend-system/core-services/permissions | the service docs} + * for more information. * * @public */ @@ -124,7 +175,11 @@ export namespace coreServices { >({ id: 'core.permissions' }); /** - * The service reference for the plugin scoped {@link PluginMetadataService}. + * Built-in service for accessing metadata about the current plugin. + * + * See {@link PluginMetadataService} + * and {@link https://backstage.io/docs/backend-system/core-services/plugin-metadata | the service docs} + * for more information. * * @public */ @@ -133,7 +188,11 @@ export namespace coreServices { >({ id: 'core.pluginMetadata' }); /** - * The service reference for the root scoped {@link RootHttpRouterService}. + * HTTP route registration for root services. + * + * See {@link RootHttpRouterService} + * and {@link https://backstage.io/docs/backend-system/core-services/root-http-router | the service docs} + * for more information. * * @public */ @@ -142,7 +201,11 @@ export namespace coreServices { >({ id: 'core.rootHttpRouter', scope: 'root' }); /** - * The service reference for the root scoped {@link RootLifecycleService}. + * Registration of backend startup and shutdown lifecycle hooks. + * + * See {@link RootLifecycleService} + * and {@link https://backstage.io/docs/backend-system/core-services/root-lifecycle | the service docs} + * for more information. * * @public */ @@ -151,7 +214,11 @@ export namespace coreServices { >({ id: 'core.rootLifecycle', scope: 'root' }); /** - * The service reference for the root scoped {@link RootLoggerService}. + * Root-level logging. + * + * See {@link RootLoggerService} + * and {@link https://backstage.io/docs/backend-system/core-services/root-logger | the service docs} + * for more information. * * @public */ @@ -160,7 +227,11 @@ export namespace coreServices { >({ id: 'core.rootLogger', scope: 'root' }); /** - * The service reference for the plugin scoped {@link SchedulerService}. + * Scheduling of distributed background tasks. + * + * See {@link SchedulerService} + * and {@link https://backstage.io/docs/backend-system/core-services/scheduler | the service docs} + * for more information. * * @public */ @@ -169,7 +240,11 @@ export namespace coreServices { >({ id: 'core.scheduler' }); /** - * The service reference for the plugin scoped {@link TokenManagerService}. + * Deprecated service authentication service, use the `auth` service instead. + * + * See {@link TokenManagerService} + * and {@link https://backstage.io/docs/backend-system/core-services/token-manager | the service docs} + * for more information. * * @public * @deprecated Please migrate to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead @@ -179,7 +254,11 @@ export namespace coreServices { >({ id: 'core.tokenManager' }); /** - * The service reference for the plugin scoped {@link UrlReaderService}. + * Reading content from external systems. + * + * See {@link UrlReaderService} + * and {@link https://backstage.io/docs/backend-system/core-services/url-reader | the service docs} + * for more information. * * @public */ @@ -188,7 +267,11 @@ export namespace coreServices { >({ id: 'core.urlReader' }); /** - * The service reference for the plugin scoped {@link IdentityService}. + * Deprecated user authentication service, use the `auth` service instead. + * + * See {@link IdentityService} + * and {@link https://backstage.io/docs/backend-system/core-services/identity | the service docs} + * for more information. * * @public * @deprecated Please migrate to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead diff --git a/packages/backend-plugin-api/src/services/definitions/index.ts b/packages/backend-plugin-api/src/services/definitions/index.ts index 13175b96ae..5e30d444fd 100644 --- a/packages/backend-plugin-api/src/services/definitions/index.ts +++ b/packages/backend-plugin-api/src/services/definitions/index.ts @@ -32,6 +32,7 @@ export type { export type { RootConfigService } from './RootConfigService'; export type { DatabaseService } from './DatabaseService'; export type { DiscoveryService } from './DiscoveryService'; +export type { RootHealthService } from './RootHealthService'; export type { HttpRouterService, HttpRouterServiceAuthPolicy, @@ -74,15 +75,15 @@ export type { SearchOptions, SearchResponse, SearchResponseFile, - UrlReaderReadTreeOptions, - UrlReaderReadTreeResponse, - UrlReaderReadTreeResponseDirOptions, - UrlReaderReadTreeResponseFile, - UrlReaderReadUrlResponse, - UrlReaderReadUrlOptions, - UrlReaderSearchOptions, - UrlReaderSearchResponse, - UrlReaderSearchResponseFile, + UrlReaderServiceReadTreeOptions, + UrlReaderServiceReadTreeResponse, + UrlReaderServiceReadTreeResponseDirOptions, + UrlReaderServiceReadTreeResponseFile, + UrlReaderServiceReadUrlResponse, + UrlReaderServiceReadUrlOptions, + UrlReaderServiceSearchOptions, + UrlReaderServiceSearchResponse, + UrlReaderServiceSearchResponseFile, UrlReaderService, } from './UrlReaderService'; export type { BackstageUserInfo, UserInfoService } from './UserInfoService'; diff --git a/packages/backend-plugin-api/src/types.ts b/packages/backend-plugin-api/src/types.ts index 59f1106fab..31684b6a38 100644 --- a/packages/backend-plugin-api/src/types.ts +++ b/packages/backend-plugin-api/src/types.ts @@ -27,3 +27,14 @@ export interface BackendFeature { // NOTE: This type is opaque in order to simplify future API evolution. $$type: '@backstage/BackendFeature'; } + +/** + * @public + * @deprecated This type exists only as a helper for old code that relied on `createBackendFeature` and `createBackendPlugin` to return `() => BackendFeature` instead of `BackendFeature`. You should remove the `()` parentheses at the end of your usages. This type will be removed in a future release. + */ +export interface BackendFeatureCompat extends BackendFeature { + /** + * @deprecated You do not need to use this call signature; use the type directly instead by removing the `()` parentheses at the end. This call signature will be removed in a future release. + */ + (): this; +} diff --git a/packages/backend-plugin-api/src/wiring/factories.test.ts b/packages/backend-plugin-api/src/wiring/factories.test.ts index 9f11c9b40b..6d5c1f39cd 100644 --- a/packages/backend-plugin-api/src/wiring/factories.test.ts +++ b/packages/backend-plugin-api/src/wiring/factories.test.ts @@ -33,19 +33,25 @@ describe('createExtensionPoint', () => { describe('createBackendPlugin', () => { it('should create a BackendPlugin', () => { - const plugin = createBackendPlugin({ + const result = createBackendPlugin({ pluginId: 'x', register(r) { r.registerInit({ deps: {}, async init() {} }); }, }); - expect(plugin).toBeDefined(); - expect(plugin()).toEqual({ - $$type: '@backstage/BackendFeature', - version: 'v1', - getRegistrations: expect.any(Function), - }); - expect((plugin() as InternalBackendFeature).getRegistrations()).toEqual([ + + // legacy form + const legacy = result() as unknown as InternalBackendFeature; + expect(legacy.$$type).toEqual('@backstage/BackendFeature'); + expect(legacy.version).toEqual('v1'); + expect(legacy.getRegistrations).toEqual(expect.any(Function)); + + // new form + const plugin = result as unknown as InternalBackendFeature; + expect(plugin.$$type).toEqual('@backstage/BackendFeature'); + expect(plugin.version).toEqual('v1'); + expect(plugin.getRegistrations).toEqual(expect.any(Function)); + expect(plugin.getRegistrations()).toEqual([ { type: 'plugin', pluginId: 'x', @@ -56,6 +62,7 @@ describe('createBackendPlugin', () => { }, }, ]); + // @ts-expect-error expect(plugin({ a: 'a' })).toBeDefined(); }); @@ -63,21 +70,26 @@ describe('createBackendPlugin', () => { describe('createBackendModule', () => { it('should create a BackendModule', () => { - const mod = createBackendModule({ + const result = createBackendModule({ pluginId: 'x', moduleId: 'y', register(r) { r.registerInit({ deps: {}, async init() {} }); }, }); - expect(mod).toBeDefined(); - expect(mod()).toBeDefined(); - expect(mod()).toEqual({ - $$type: '@backstage/BackendFeature', - version: 'v1', - getRegistrations: expect.any(Function), - }); - expect((mod() as InternalBackendFeature).getRegistrations()).toEqual([ + + // legacy form + const legacy = result() as unknown as InternalBackendFeature; + expect(legacy.$$type).toEqual('@backstage/BackendFeature'); + expect(legacy.version).toEqual('v1'); + expect(legacy.getRegistrations).toEqual(expect.any(Function)); + + // new form + const module = result as unknown as InternalBackendFeature; + expect(module.$$type).toEqual('@backstage/BackendFeature'); + expect(module.version).toEqual('v1'); + expect(module.getRegistrations).toEqual(expect.any(Function)); + expect(module.getRegistrations()).toEqual([ { type: 'module', pluginId: 'x', @@ -89,7 +101,8 @@ describe('createBackendModule', () => { }, }, ]); + // @ts-expect-error - expect(mod({ a: 'a' })).toBeDefined(); + expect(module({ a: 'a' })).toBeDefined(); }); }); diff --git a/packages/backend-plugin-api/src/wiring/factories.ts b/packages/backend-plugin-api/src/wiring/factories.ts index 5442bab897..81e2247152 100644 --- a/packages/backend-plugin-api/src/wiring/factories.ts +++ b/packages/backend-plugin-api/src/wiring/factories.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { BackendFeature, BackendFeatureFactory } from '../types'; +import { BackendFeatureCompat } from '../types'; import { BackendModuleRegistrationPoints, BackendPluginRegistrationPoints, @@ -90,63 +90,57 @@ export interface CreateBackendPluginOptions { */ export function createBackendPlugin( options: CreateBackendPluginOptions, -): () => BackendFeature { - const factory: BackendFeatureFactory = () => { - let registrations: InternalBackendPluginRegistration[]; +): BackendFeatureCompat { + function getRegistrations() { + const extensionPoints: InternalBackendPluginRegistration['extensionPoints'] = + []; + let init: InternalBackendPluginRegistration['init'] | undefined = undefined; - return { - $$type: '@backstage/BackendFeature', - version: 'v1', - getRegistrations() { - if (registrations) { - return registrations; + options.register({ + registerExtensionPoint(ext, impl) { + if (init) { + throw new Error('registerExtensionPoint called after registerInit'); } - const extensionPoints: InternalBackendPluginRegistration['extensionPoints'] = - []; - let init: InternalBackendPluginRegistration['init'] | undefined = - undefined; - - options.register({ - registerExtensionPoint(ext, impl) { - if (init) { - throw new Error( - 'registerExtensionPoint called after registerInit', - ); - } - extensionPoints.push([ext, impl]); - }, - registerInit(regInit) { - if (init) { - throw new Error('registerInit must only be called once'); - } - init = { - deps: regInit.deps, - func: regInit.init, - }; - }, - }); - - if (!init) { - throw new Error( - `registerInit was not called by register in ${options.pluginId}`, - ); - } - - registrations = [ - { - type: 'plugin', - pluginId: options.pluginId, - extensionPoints, - init, - }, - ]; - return registrations; + extensionPoints.push([ext, impl]); }, - }; - }; - factory.$$type = '@backstage/BackendFeatureFactory'; + registerInit(regInit) { + if (init) { + throw new Error('registerInit must only be called once'); + } + init = { + deps: regInit.deps, + func: regInit.init, + }; + }, + }); - return factory; + if (!init) { + throw new Error( + `registerInit was not called by register in ${options.pluginId}`, + ); + } + + return [ + { + type: 'plugin', + pluginId: options.pluginId, + extensionPoints, + init, + }, + ]; + } + + function backendFeatureCompatWrapper() { + return backendFeatureCompatWrapper; + } + + Object.assign(backendFeatureCompatWrapper, { + $$type: '@backstage/BackendFeature' as const, + version: 'v1', + getRegistrations, + }); + + return backendFeatureCompatWrapper as BackendFeatureCompat; } /** @@ -180,62 +174,56 @@ export interface CreateBackendModuleOptions { */ export function createBackendModule( options: CreateBackendModuleOptions, -): () => BackendFeature { - const factory: BackendFeatureFactory = () => { - let registrations: InternalBackendModuleRegistration[]; +): BackendFeatureCompat { + function getRegistrations() { + const extensionPoints: InternalBackendPluginRegistration['extensionPoints'] = + []; + let init: InternalBackendModuleRegistration['init'] | undefined = undefined; - return { - $$type: '@backstage/BackendFeature', - version: 'v1', - getRegistrations() { - if (registrations) { - return registrations; + options.register({ + registerExtensionPoint(ext, impl) { + if (init) { + throw new Error('registerExtensionPoint called after registerInit'); } - const extensionPoints: InternalBackendPluginRegistration['extensionPoints'] = - []; - let init: InternalBackendModuleRegistration['init'] | undefined = - undefined; - - options.register({ - registerExtensionPoint(ext, impl) { - if (init) { - throw new Error( - 'registerExtensionPoint called after registerInit', - ); - } - extensionPoints.push([ext, impl]); - }, - registerInit(regInit) { - if (init) { - throw new Error('registerInit must only be called once'); - } - init = { - deps: regInit.deps, - func: regInit.init, - }; - }, - }); - - if (!init) { - throw new Error( - `registerInit was not called by register in ${options.moduleId} module for ${options.pluginId}`, - ); - } - - registrations = [ - { - type: 'module', - pluginId: options.pluginId, - moduleId: options.moduleId, - extensionPoints, - init, - }, - ]; - return registrations; + extensionPoints.push([ext, impl]); }, - }; - }; - factory.$$type = '@backstage/BackendFeatureFactory'; + registerInit(regInit) { + if (init) { + throw new Error('registerInit must only be called once'); + } + init = { + deps: regInit.deps, + func: regInit.init, + }; + }, + }); - return factory; + if (!init) { + throw new Error( + `registerInit was not called by register in ${options.moduleId} module for ${options.pluginId}`, + ); + } + + return [ + { + type: 'module', + pluginId: options.pluginId, + moduleId: options.moduleId, + extensionPoints, + init, + }, + ]; + } + + function backendFeatureCompatWrapper() { + return backendFeatureCompatWrapper; + } + + Object.assign(backendFeatureCompatWrapper, { + $$type: '@backstage/BackendFeature' as const, + version: 'v1', + getRegistrations, + }); + + return backendFeatureCompatWrapper as BackendFeatureCompat; } diff --git a/packages/backend-tasks/CHANGELOG.md b/packages/backend-tasks/CHANGELOG.md index cdc54dcec4..008ae3cb11 100644 --- a/packages/backend-tasks/CHANGELOG.md +++ b/packages/backend-tasks/CHANGELOG.md @@ -1,5 +1,44 @@ # @backstage/backend-tasks +## 0.5.26-next.0 + +### Patch Changes + +- 083eaf9: Fix bug where ISO durations could no longer be used for schedules +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + +## 0.5.24 + +### Patch Changes + +- 736bc3c: Marked all exports as deprecated and pointed at `@backstage/backend-plugin-api` and `@backstage/backend-defaults` +- ed473cd: Updated the `TaskScheduleDefinitionConfig` deprecated comment to point to `SchedulerServiceTaskScheduleDefinitionConfig` +- 6a576dc: Deprecate the legacy `TaskScheduler.fromConfig` method and stop using the `getVoidlogger` in tests files to reduce the dependency on the soon-to-deprecate `backstage-common` package. +- 1897169: More detailed deprecation messages +- Updated dependencies + - @backstage/backend-common@0.23.0 + - @backstage/backend-plugin-api@0.6.19 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + +## 0.5.24-next.3 + +### Patch Changes + +- 1897169: More detailed deprecation messages +- Updated dependencies + - @backstage/backend-plugin-api@0.6.19-next.3 + - @backstage/backend-common@0.23.0-next.3 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + ## 0.5.24-next.2 ### Patch Changes diff --git a/packages/backend-tasks/package.json b/packages/backend-tasks/package.json index 029b73a013..2033be826c 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.24-next.2", + "version": "0.5.26-next.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-tasks/src/tasks/readTaskScheduleDefinitionFromConfig.test.ts b/packages/backend-tasks/src/tasks/readTaskScheduleDefinitionFromConfig.test.ts index c52d59b016..adeb134611 100644 --- a/packages/backend-tasks/src/tasks/readTaskScheduleDefinitionFromConfig.test.ts +++ b/packages/backend-tasks/src/tasks/readTaskScheduleDefinitionFromConfig.test.ts @@ -16,7 +16,6 @@ import { ConfigReader } from '@backstage/config'; import { HumanDuration } from '@backstage/types'; -import { Duration } from 'luxon'; import { readTaskScheduleDefinitionFromConfig } from './readTaskScheduleDefinitionFromConfig'; describe('readTaskScheduleDefinitionFromConfig', () => { @@ -35,7 +34,7 @@ describe('readTaskScheduleDefinitionFromConfig', () => { const result = readTaskScheduleDefinitionFromConfig(config); expect((result.frequency as { cron: string }).cron).toBe('0 30 * * * *'); - expect(result.timeout).toEqual(Duration.fromISO('PT3M')); + expect(result.timeout).toEqual({ minutes: 3 }); expect((result.initialDelay as HumanDuration).minutes).toEqual(20); expect(result.scope).toBe('global'); }); @@ -51,7 +50,7 @@ describe('readTaskScheduleDefinitionFromConfig', () => { const result = readTaskScheduleDefinitionFromConfig(config); expect((result.frequency as { cron: string }).cron).toBe('0 30 * * * *'); - expect(result.timeout).toEqual(Duration.fromISO('PT3M')); + expect(result.timeout).toEqual({ minutes: 3 }); expect(result.initialDelay).toBeUndefined(); expect(result.scope).toBeUndefined(); }); diff --git a/packages/backend-tasks/src/tasks/readTaskScheduleDefinitionFromConfig.ts b/packages/backend-tasks/src/tasks/readTaskScheduleDefinitionFromConfig.ts index 5a173f246b..e94d06d5c3 100644 --- a/packages/backend-tasks/src/tasks/readTaskScheduleDefinitionFromConfig.ts +++ b/packages/backend-tasks/src/tasks/readTaskScheduleDefinitionFromConfig.ts @@ -19,14 +19,14 @@ import { HumanDuration } from '@backstage/types'; import { TaskScheduleDefinition } from './types'; import { Duration } from 'luxon'; -function readDuration(config: Config, key: string): Duration | HumanDuration { +function readDuration(config: Config, key: string): HumanDuration { if (typeof config.get(key) === 'string') { const value = config.getString(key); const duration = Duration.fromISO(value); if (!duration.isValid) { throw new Error(`Invalid duration: ${value}`); } - return duration; + return duration.toObject(); } return readDurationFromConfig(config, { key }); diff --git a/packages/backend-test-utils/CHANGELOG.md b/packages/backend-test-utils/CHANGELOG.md index a15cb095bd..435d1f8abc 100644 --- a/packages/backend-test-utils/CHANGELOG.md +++ b/packages/backend-test-utils/CHANGELOG.md @@ -1,5 +1,58 @@ # @backstage/backend-test-utils +## 0.4.3-next.0 + +### Patch Changes + +- fce7887: Added mock for the Root Health Service in `mockServices`. +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-defaults@0.3.3-next.0 + - @backstage/backend-app-api@0.7.9-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/plugin-events-node@0.3.7-next.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + +## 0.4.0 + +### Minor Changes + +- 805cbe7: Added `TestCaches` that functions just like `TestDatabases` + +### Patch Changes + +- 78a0b08: Internal refactor to handle `BackendFeature` contract change. +- 9e63318: Made it possible to give access restrictions to `mockCredentials.service` +- 006b3e8: The type `MockDirectoryOptions` was renamed to `CreateMockDirectoryOptions` so that it's clear these options are exclusive to the mock directory factory. +- 0634fdc: Refactored `TestDatabases` to no longer depend on `backend-common` +- 6a576dc: Fix the logger service mock to prevent returning `undefined` from the `child` method. +- 6c11f6e: Use imports from backend-defaults instead of the deprecated ones from backend-app-api +- Updated dependencies + - @backstage/backend-app-api@0.7.6 + - @backstage/backend-plugin-api@0.6.19 + - @backstage/plugin-auth-node@0.4.14 + - @backstage/backend-defaults@0.3.0 + - @backstage/plugin-events-node@0.3.5 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + +## 0.4.0-next.3 + +### Patch Changes + +- 006b3e8: The type `MockDirectoryOptions` was renamed to `CreateMockDirectoryOptions` so that it's clear these options are exclusive to the mock directory factory. +- Updated dependencies + - @backstage/backend-plugin-api@0.6.19-next.3 + - @backstage/plugin-auth-node@0.4.14-next.3 + - @backstage/plugin-events-node@0.3.5-next.2 + - @backstage/backend-app-api@0.7.6-next.3 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + ## 0.4.0-next.2 ### Patch Changes diff --git a/packages/backend-test-utils/api-report.md b/packages/backend-test-utils/api-report.md index cc30dc8f56..a2fb4b7674 100644 --- a/packages/backend-test-utils/api-report.md +++ b/packages/backend-test-utils/api-report.md @@ -22,7 +22,7 @@ import { EventsService } from '@backstage/plugin-events-node'; import { ExtendedHttpServer } from '@backstage/backend-app-api'; import { ExtensionPoint } from '@backstage/backend-plugin-api'; import { HttpAuthService } from '@backstage/backend-plugin-api'; -import { HttpRouterFactoryOptions } from '@backstage/backend-app-api'; +import { HttpRouterFactoryOptions } from '@backstage/backend-defaults/httpRouter'; import { HttpRouterService } from '@backstage/backend-plugin-api'; import { IdentityService } from '@backstage/backend-plugin-api'; import { JsonObject } from '@backstage/types'; @@ -32,7 +32,8 @@ import { LifecycleService } from '@backstage/backend-plugin-api'; import { LoggerService } from '@backstage/backend-plugin-api'; import { PermissionsService } from '@backstage/backend-plugin-api'; import { RootConfigService } from '@backstage/backend-plugin-api'; -import { RootHttpRouterFactoryOptions } from '@backstage/backend-app-api'; +import { RootHealthService } from '@backstage/backend-plugin-api'; +import { RootHttpRouterFactoryOptions } from '@backstage/backend-defaults/rootHttpRouter'; import { RootHttpRouterService } from '@backstage/backend-plugin-api'; import { RootLifecycleService } from '@backstage/backend-plugin-api'; import { RootLoggerService } from '@backstage/backend-plugin-api'; @@ -280,6 +281,15 @@ export namespace mockServices { ) => ServiceFactory; } // (undocumented) + export namespace rootHealth { + const // (undocumented) + factory: () => ServiceFactory; + const // (undocumented) + mock: ( + partialImpl?: Partial | undefined, + ) => ServiceMock; + } + // (undocumented) export namespace rootHttpRouter { const // (undocumented) factory: ( diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index 9dc8868f64..47f2c9c628 100644 --- a/packages/backend-test-utils/package.json +++ b/packages/backend-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/backend-test-utils", - "version": "0.4.0-next.2", + "version": "0.4.3-next.0", "description": "Test helpers library for Backstage backends", "backstage": { "role": "node-library" @@ -46,6 +46,7 @@ }, "dependencies": { "@backstage/backend-app-api": "workspace:^", + "@backstage/backend-defaults": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", diff --git a/packages/backend-test-utils/src/next/services/mockServices.ts b/packages/backend-test-utils/src/next/services/mockServices.ts index 57621a9209..d56179d958 100644 --- a/packages/backend-test-utils/src/next/services/mockServices.ts +++ b/packages/backend-test-utils/src/next/services/mockServices.ts @@ -14,48 +14,49 @@ * limitations under the License. */ +import { cacheServiceFactory } from '@backstage/backend-defaults/cache'; +import { databaseServiceFactory } from '@backstage/backend-defaults/database'; import { - RootConfigService, - coreServices, - createServiceFactory, + HostDiscovery, + discoveryServiceFactory, +} from '@backstage/backend-defaults/discovery'; +import { httpRouterServiceFactory } from '@backstage/backend-defaults/httpRouter'; +import { lifecycleServiceFactory } from '@backstage/backend-defaults/lifecycle'; +import { loggerServiceFactory } from '@backstage/backend-defaults/logger'; +import { permissionsServiceFactory } from '@backstage/backend-defaults/permissions'; +import { rootHealthServiceFactory } from '@backstage/backend-defaults/rootHealth'; +import { rootHttpRouterServiceFactory } from '@backstage/backend-defaults/rootHttpRouter'; +import { rootLifecycleServiceFactory } from '@backstage/backend-defaults/rootLifecycle'; +import { schedulerServiceFactory } from '@backstage/backend-defaults/scheduler'; +import { urlReaderServiceFactory } from '@backstage/backend-defaults/urlReader'; +import { + AuthService, + BackstageCredentials, + BackstageUserInfo, + DiscoveryService, + HttpAuthService, IdentityService, LoggerService, + RootConfigService, ServiceFactory, ServiceRef, TokenManagerService, - AuthService, - DiscoveryService, - HttpAuthService, - BackstageCredentials, - BackstageUserInfo, UserInfoService, + coreServices, + createServiceFactory, } from '@backstage/backend-plugin-api'; -import { - cacheServiceFactory, - databaseServiceFactory, - httpRouterServiceFactory, - lifecycleServiceFactory, - loggerServiceFactory, - permissionsServiceFactory, - rootHttpRouterServiceFactory, - rootLifecycleServiceFactory, - schedulerServiceFactory, - urlReaderServiceFactory, - discoveryServiceFactory, - HostDiscovery, -} from '@backstage/backend-app-api'; import { ConfigReader } from '@backstage/config'; -import { JsonObject } from '@backstage/types'; -import { MockIdentityService } from './MockIdentityService'; -import { MockRootLoggerService } from './MockRootLoggerService'; -import { MockAuthService } from './MockAuthService'; -import { MockHttpAuthService } from './MockHttpAuthService'; -import { mockCredentials } from './mockCredentials'; -import { MockUserInfoService } from './MockUserInfoService'; import { eventsServiceFactory, eventsServiceRef, } from '@backstage/plugin-events-node'; +import { JsonObject } from '@backstage/types'; +import { MockAuthService } from './MockAuthService'; +import { MockHttpAuthService } from './MockHttpAuthService'; +import { MockIdentityService } from './MockIdentityService'; +import { MockRootLoggerService } from './MockRootLoggerService'; +import { MockUserInfoService } from './MockUserInfoService'; +import { mockCredentials } from './mockCredentials'; /** @internal */ function createLoggerMock() { @@ -344,6 +345,14 @@ export namespace mockServices { })); } + export namespace rootHealth { + export const factory = rootHealthServiceFactory; + export const mock = simpleMock(coreServices.rootHealth, () => ({ + getLiveness: jest.fn(), + getReadiness: jest.fn(), + })); + } + export namespace httpRouter { export const factory = httpRouterServiceFactory; export const mock = simpleMock(coreServices.httpRouter, () => ({ diff --git a/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts b/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts index a4b74b5ffa..ecba34290d 100644 --- a/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts +++ b/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts @@ -144,7 +144,7 @@ describe('TestBackend', () => { }); await startTestBackend({ - features: [testModule(), sf()], + features: [testModule, sf()], }); expect(testFn).toHaveBeenCalledWith('winning'); @@ -169,7 +169,7 @@ describe('TestBackend', () => { }); const backend = await startTestBackend({ - features: [testModule()], + features: [testModule], }); expect(shutdownSpy).not.toHaveBeenCalled(); @@ -212,7 +212,7 @@ describe('TestBackend', () => { }); await startTestBackend({ - features: [testPlugin()], + features: [testPlugin], }); }); @@ -233,7 +233,7 @@ describe('TestBackend', () => { }, }); - const { server } = await startTestBackend({ features: [testPlugin()] }); + const { server } = await startTestBackend({ features: [testPlugin] }); const res = await request(server) .get('/api/test/ping-me') diff --git a/packages/backend-test-utils/src/next/wiring/TestBackend.ts b/packages/backend-test-utils/src/next/wiring/TestBackend.ts index e43353991f..f23883ba3e 100644 --- a/packages/backend-test-utils/src/next/wiring/TestBackend.ts +++ b/packages/backend-test-utils/src/next/wiring/TestBackend.ts @@ -133,7 +133,7 @@ function createExtensionPointTestModules( ref: ExtensionPoint, impl: unknown, ][], -): Array<() => BackendFeature> { +): Array { if (!extensionPointTuples) { return []; } diff --git a/packages/backend/CHANGELOG.md b/packages/backend/CHANGELOG.md index 49c67189fe..6e4257b62d 100644 --- a/packages/backend/CHANGELOG.md +++ b/packages/backend/CHANGELOG.md @@ -1,5 +1,116 @@ # example-backend +## 0.0.28-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-defaults@0.3.3-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/plugin-scaffolder-backend@1.23.0-next.0 + - @backstage/plugin-scaffolder-backend-module-github@0.4.0-next.0 + - @backstage/plugin-notifications-backend@0.3.2-next.0 + - @backstage/plugin-app-backend@0.3.70-next.0 + - @backstage/plugin-auth-backend@0.22.8-next.0 + - @backstage/plugin-auth-backend-module-github-provider@0.1.18-next.0 + - @backstage/plugin-auth-backend-module-guest-provider@0.1.7-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/plugin-catalog-backend@1.23.2-next.0 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.2.4-next.0 + - @backstage/plugin-catalog-backend-module-openapi@0.1.39-next.0 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.19-next.0 + - @backstage/plugin-catalog-backend-module-unprocessed@0.4.8-next.0 + - @backstage/plugin-devtools-backend@0.3.7-next.0 + - @backstage/plugin-kubernetes-backend@0.18.2-next.0 + - @backstage/plugin-permission-backend@0.5.45-next.0 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.1.18-next.0 + - @backstage/plugin-permission-node@0.7.32-next.0 + - @backstage/plugin-proxy-backend@0.5.2-next.0 + - @backstage/plugin-search-backend@1.5.13-next.0 + - @backstage/plugin-search-backend-module-catalog@0.1.27-next.0 + - @backstage/plugin-search-backend-module-explore@0.1.27-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.1.26-next.0 + - @backstage/plugin-search-backend-node@1.2.26-next.0 + - @backstage/plugin-signals-backend@0.1.7-next.0 + - @backstage/plugin-techdocs-backend@1.10.8-next.0 + - @backstage/catalog-model@1.5.0 + - @backstage/plugin-permission-common@0.7.14 + +## 0.0.27 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.19 + - @backstage/backend-tasks@0.5.24 + - @backstage/plugin-auth-node@0.4.14 + - @backstage/plugin-auth-backend@0.22.6 + - @backstage/plugin-techdocs-backend@1.10.6 + - @backstage/plugin-scaffolder-backend-module-github@0.3.0 + - @backstage/plugin-devtools-backend@0.3.5 + - @backstage/plugin-catalog-backend@1.23.0 + - @backstage/plugin-search-backend@1.5.10 + - @backstage/plugin-proxy-backend@0.5.0 + - @backstage/plugin-app-backend@0.3.68 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.17 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.1.16 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.2.2 + - @backstage/plugin-auth-backend-module-github-provider@0.1.16 + - @backstage/plugin-auth-backend-module-guest-provider@0.1.5 + - @backstage/plugin-catalog-backend-module-unprocessed@0.4.6 + - @backstage/plugin-catalog-backend-module-openapi@0.1.37 + - @backstage/plugin-search-backend-module-techdocs@0.1.24 + - @backstage/plugin-search-backend-module-catalog@0.1.25 + - @backstage/plugin-search-backend-module-explore@0.1.25 + - @backstage/plugin-notifications-backend@0.3.0 + - @backstage/plugin-kubernetes-backend@0.18.0 + - @backstage/plugin-permission-backend@0.5.43 + - @backstage/plugin-scaffolder-backend@1.22.9 + - @backstage/plugin-signals-backend@0.1.5 + - @backstage/backend-defaults@0.3.0 + - @backstage/plugin-search-backend-node@1.2.24 + - @backstage/plugin-permission-node@0.7.30 + - @backstage/plugin-permission-common@0.7.14 + - @backstage/catalog-model@1.5.0 + +## 0.0.27-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.19-next.3 + - @backstage/plugin-auth-node@0.4.14-next.3 + - @backstage/backend-defaults@0.3.0-next.3 + - @backstage/plugin-auth-backend-module-github-provider@0.1.16-next.2 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.17-next.3 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.1.16-next.2 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.2.2-next.2 + - @backstage/plugin-auth-backend-module-guest-provider@0.1.5-next.3 + - @backstage/plugin-catalog-backend-module-unprocessed@0.4.6-next.3 + - @backstage/plugin-scaffolder-backend-module-github@0.3.0-next.3 + - @backstage/plugin-catalog-backend-module-openapi@0.1.37-next.3 + - @backstage/plugin-search-backend-module-techdocs@0.1.24-next.3 + - @backstage/plugin-search-backend-module-catalog@0.1.25-next.3 + - @backstage/plugin-search-backend-module-explore@0.1.25-next.3 + - @backstage/plugin-notifications-backend@0.3.0-next.3 + - @backstage/plugin-search-backend-node@1.2.24-next.3 + - @backstage/plugin-kubernetes-backend@0.18.0-next.3 + - @backstage/plugin-permission-backend@0.5.43-next.3 + - @backstage/plugin-scaffolder-backend@1.22.8-next.3 + - @backstage/plugin-permission-common@0.7.14-next.0 + - @backstage/plugin-devtools-backend@0.3.5-next.3 + - @backstage/plugin-techdocs-backend@1.10.6-next.3 + - @backstage/plugin-catalog-backend@1.23.0-next.3 + - @backstage/plugin-permission-node@0.7.30-next.3 + - @backstage/plugin-signals-backend@0.1.5-next.3 + - @backstage/plugin-search-backend@1.5.10-next.3 + - @backstage/plugin-proxy-backend@0.5.0-next.3 + - @backstage/plugin-auth-backend@0.22.6-next.3 + - @backstage/plugin-app-backend@0.3.68-next.3 + - @backstage/backend-tasks@0.5.24-next.3 + - @backstage/catalog-model@1.5.0 + ## 0.0.27-next.2 ### Patch Changes diff --git a/packages/backend/package.json b/packages/backend/package.json index ba22ddae1e..f81701a77d 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,6 @@ { "name": "example-backend", - "version": "0.0.27-next.2", + "version": "0.0.28-next.0", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index a4acd19cf2..1174b7bf6d 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -21,7 +21,6 @@ const backend = createBackend(); backend.add(import('@backstage/plugin-auth-backend')); backend.add(import('./authModuleGithubProvider')); backend.add(import('@backstage/plugin-auth-backend-module-guest-provider')); - backend.add(import('@backstage/plugin-app-backend/alpha')); backend.add(import('@backstage/plugin-catalog-backend-module-unprocessed')); backend.add( diff --git a/packages/cli-common/CHANGELOG.md b/packages/cli-common/CHANGELOG.md index 70e98da8dd..29ffc4984c 100644 --- a/packages/cli-common/CHANGELOG.md +++ b/packages/cli-common/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/cli-common +## 0.1.14 + +### Patch Changes + +- 142abb0: The monorepo root check in `findPaths` will now accept a shorthand `workspaces` config in `package.json`, no longer requiring `workspaces.packages`. + +## 0.1.14-next.0 + +### Patch Changes + +- 142abb0: The monorepo root check in `findPaths` will now accept a shorthand `workspaces` config in `package.json`, no longer requiring `workspaces.packages`. + ## 0.1.13 ### Patch Changes diff --git a/packages/cli-common/package.json b/packages/cli-common/package.json index be91af578c..c316f15322 100644 --- a/packages/cli-common/package.json +++ b/packages/cli-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/cli-common", - "version": "0.1.13", + "version": "0.1.14", "description": "Common functionality used by cli, backend, and create-app", "backstage": { "role": "node-library" diff --git a/packages/cli-node/CHANGELOG.md b/packages/cli-node/CHANGELOG.md index bc75eb9612..dcf9073277 100644 --- a/packages/cli-node/CHANGELOG.md +++ b/packages/cli-node/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/cli-node +## 0.2.6 + +### Patch Changes + +- a1ae9cc: Updated doc link. +- c328131: Added new plugin metadata fields to `BackstagePackageJson` type. +- 93be042: Upgraded @yarnpkg/parsers to stable 3.0 +- Updated dependencies + - @backstage/cli-common@0.1.14 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + +## 0.2.6-next.2 + +### Patch Changes + +- c328131: Added new plugin metadata fields to `BackstagePackageJson` type. +- Updated dependencies + - @backstage/cli-common@0.1.14-next.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + ## 0.2.6-next.1 ### Patch Changes diff --git a/packages/cli-node/api-report.md b/packages/cli-node/api-report.md index a16b4c91a4..9f7e525048 100644 --- a/packages/cli-node/api-report.md +++ b/packages/cli-node/api-report.md @@ -18,7 +18,7 @@ export interface BackstagePackageJson { backstage?: { role?: PackageRole; moved?: string; - pluginId?: string; + pluginId?: string | null; pluginPackage?: string; pluginPackages?: string[]; }; diff --git a/packages/cli-node/package.json b/packages/cli-node/package.json index a76d35dc6c..56cf50a096 100644 --- a/packages/cli-node/package.json +++ b/packages/cli-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/cli-node", - "version": "0.2.6-next.1", + "version": "0.2.6", "description": "Node.js library for Backstage CLIs", "backstage": { "role": "node-library" diff --git a/packages/cli-node/src/monorepo/PackageGraph.ts b/packages/cli-node/src/monorepo/PackageGraph.ts index afa5eed888..c8877803d5 100644 --- a/packages/cli-node/src/monorepo/PackageGraph.ts +++ b/packages/cli-node/src/monorepo/PackageGraph.ts @@ -48,9 +48,9 @@ export interface BackstagePackageJson { moved?: string; /** - * The ID of the plugin if this is a plugin package. Must always be set for plugin and module packages, and may be set for library packages. + * The ID of the plugin if this is a plugin package. Must always be set for plugin and module packages, and may be set for library packages. A `null` value means that the package is explicitly not a plugin package. */ - pluginId?: string; + pluginId?: string | null; /** * The parent plugin package of a module. Must always and only be set for module packages. diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index b8e2c19747..0e65266410 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,72 @@ # @backstage/cli +## 0.26.10-next.0 + +### Patch Changes + +- e2e320c: - remove unused dependencies `winston` and `yn` from the template of backend plugins; + - update `msw` to version `2.3.1` in the template of backend plugins; + starting with v1 and switching later to v2 is tedious and not straight forward; it's easier to start with v2; +- 0540c5a: Updated the scaffolding output message for `plugin-common` in `backstage-cli`. Now, when executing `backstage-cli new` to create a new `plugin-common` package, the output message accurately reflects the action by displaying `Creating common plugin package...` instead of the previous, less accurate `Creating backend plugin...`. +- 7652db4: Only bootstrap global-agent if it's actually being used +- f0c0039: Fix issue with CLI that was preventing upgrading from 1.28 +- d228862: Update default backend plugin created by the cli to use non-deprecated error handling middleware +- da90cce: Updated dependency `esbuild` to `^0.21.0`. +- a60d73b: Fix a few minor issues with the backend template that were causing failing linting checks in the main repo. +- 0510d98: Subpath export `package.json` should be of a unique name to avoid typescript resolution issues +- Updated dependencies + - @backstage/integration@1.13.0-next.0 + - @backstage/catalog-model@1.5.0 + - @backstage/cli-common@0.1.14 + - @backstage/cli-node@0.2.6 + - @backstage/config@1.2.0 + - @backstage/config-loader@1.8.1 + - @backstage/errors@1.2.4 + - @backstage/eslint-plugin@0.1.8 + - @backstage/release-manifests@0.0.11 + - @backstage/types@1.1.1 + +## 0.26.7 + +### Patch Changes + +- 788eca7: Fix readme for new plugins created using cli +- 90c5268: Add `peerDependencies` to `devDependencies` in `package.json.hbs` templates. +- c00f7ee: Fix issue with `esm` loaded dependencies being different from the `cjs` import for Vite dependencies +- b0f66e9: Updated dependency `vite-plugin-node-polyfills` to `^0.22.0`. +- c328131: Added a new `--publish` flag to the `repo fix` command. This command will validate and if possible generate the metadata required for publishing packages with the Backstage CLI. In addition, a check has been added that the `backstage.pluginId` and `backstage.pluginPackage(s)` fields are present when packing a package for publishing. +- 5afbe1d: Export default module for `scaffolder-action` cli template +- 009da47: Fix `versions:check --fix` when `yarn.lock` has multiple joint versions in the same section +- 9ee948a: Bump `esbuild` target for package builds to `ES2022`. +- Updated dependencies + - @backstage/cli-node@0.2.6 + - @backstage/integration@1.12.0 + - @backstage/cli-common@0.1.14 + - @backstage/config-loader@1.8.1 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/eslint-plugin@0.1.8 + - @backstage/release-manifests@0.0.11 + - @backstage/types@1.1.1 + +## 0.26.7-next.3 + +### Patch Changes + +- c328131: Added a new `--publish` flag to the `repo fix` command. This command will validate and if possible generate the metadata required for publishing packages with the Backstage CLI. In addition, a check has been added that the `backstage.pluginId` and `backstage.pluginPackage(s)` fields are present when packing a package for publishing. +- Updated dependencies + - @backstage/cli-node@0.2.6-next.2 + - @backstage/integration@1.12.0-next.1 + - @backstage/cli-common@0.1.14-next.0 + - @backstage/config-loader@1.8.1-next.0 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/eslint-plugin@0.1.8 + - @backstage/release-manifests@0.0.11 + - @backstage/types@1.1.1 + ## 0.26.7-next.2 ### Patch Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index e0212a34ff..b458cf162f 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/cli", - "version": "0.26.7-next.2", + "version": "0.26.10-next.0", "description": "CLI for developing Backstage plugins and apps", "backstage": { "role": "cli" @@ -90,7 +90,7 @@ "css-loader": "^6.5.1", "ctrlc-windows": "^2.1.0", "diff": "^5.0.0", - "esbuild": "^0.20.0", + "esbuild": "^0.21.0", "esbuild-loader": "^4.0.0", "eslint": "^8.6.0", "eslint-config-prettier": "^9.0.0", @@ -187,13 +187,13 @@ "nodemon": "^3.0.1", "vite": "^4.4.9", "vite-plugin-html": "^3.2.0", - "vite-plugin-node-polyfills": "^0.21.0" + "vite-plugin-node-polyfills": "^0.22.0" }, "peerDependencies": { "@vitejs/plugin-react": "^4.0.4", "vite": "^4.4.9", "vite-plugin-html": "^3.2.0", - "vite-plugin-node-polyfills": "^0.21.0" + "vite-plugin-node-polyfills": "^0.22.0" }, "peerDependenciesMeta": { "@vitejs/plugin-react": { diff --git a/packages/cli/src/commands/repo/fix.ts b/packages/cli/src/commands/repo/fix.ts index 370e5c0cb1..a55440c53f 100644 --- a/packages/cli/src/commands/repo/fix.ts +++ b/packages/cli/src/commands/repo/fix.ts @@ -277,7 +277,7 @@ export function fixPluginId(pkg: FixablePackage) { const currentId = pkg.packageJson.backstage?.pluginId; if (currentId !== undefined) { - if (typeof currentId !== 'string') { + if (typeof currentId !== 'string' && currentId !== null) { throw new Error( `Invalid 'backstage.pluginId' field in "${pkg.packageJson.name}", must be a string`, ); @@ -363,7 +363,8 @@ export function fixPluginPackages( if ( role === 'common-library' || role === 'web-library' || - role === 'node-library' + role === 'node-library' || + role === 'frontend-plugin-module' // TODO(Rugvip): Remove this once frontend modules are required to have a plugin ID ) { return; } diff --git a/packages/cli/src/commands/versions/bump.ts b/packages/cli/src/commands/versions/bump.ts index 1544240704..d6d5f424ba 100644 --- a/packages/cli/src/commands/versions/bump.ts +++ b/packages/cli/src/commands/versions/bump.ts @@ -14,6 +14,12 @@ * limitations under the License. */ +import { bootstrap } from 'global-agent'; + +if (shouldUseGlobalAgent()) { + bootstrap(); +} + import fs from 'fs-extra'; import chalk from 'chalk'; import ora from 'ora'; @@ -38,10 +44,22 @@ import { getManifestByVersion, ReleaseManifest, } from '@backstage/release-manifests'; -import 'global-agent/bootstrap'; import { PackageGraph } from '@backstage/cli-node'; import { migrateMovedPackages } from './migrate'; +function shouldUseGlobalAgent(): boolean { + // see https://www.npmjs.com/package/global-agent + const namespace = + process.env.GLOBAL_AGENT_ENVIRONMENT_VARIABLE_NAMESPACE ?? 'GLOBAL_AGENT_'; + if ( + process.env[`${namespace}HTTP_PROXY`] || + process.env[`${namespace}HTTPS_PROXY`] + ) { + return true; + } + return false; +} + const DEP_TYPES = [ 'dependencies', 'devDependencies', diff --git a/packages/cli/src/lib/new/factories/pluginCommon.test.ts b/packages/cli/src/lib/new/factories/pluginCommon.test.ts index d85e490510..82c1c87169 100644 --- a/packages/cli/src/lib/new/factories/pluginCommon.test.ts +++ b/packages/cli/src/lib/new/factories/pluginCommon.test.ts @@ -67,7 +67,7 @@ describe('pluginCommon factory', () => { expect(modified).toBe(true); expectLogsToMatch(output, [ - 'Creating backend plugin backstage-plugin-test-common', + 'Creating common plugin package backstage-plugin-test-common', 'Checking Prerequisites:', `availability plugins${sep}test-common`, 'creating temp dir', diff --git a/packages/cli/src/lib/new/factories/pluginCommon.ts b/packages/cli/src/lib/new/factories/pluginCommon.ts index 560386c618..5f694124ea 100644 --- a/packages/cli/src/lib/new/factories/pluginCommon.ts +++ b/packages/cli/src/lib/new/factories/pluginCommon.ts @@ -46,7 +46,7 @@ export const pluginCommon = createFactory({ }); Task.log(); - Task.log(`Creating backend plugin ${chalk.cyan(name)}`); + Task.log(`Creating common plugin package ${chalk.cyan(name)}`); const targetDir = ctx.isMonoRepo ? paths.resolveTargetRoot('plugins', suffix) diff --git a/packages/cli/src/lib/new/factories/scaffolderModule.test.ts b/packages/cli/src/lib/new/factories/scaffolderModule.test.ts index b43946228b..d83c2ce3f7 100644 --- a/packages/cli/src/lib/new/factories/scaffolderModule.test.ts +++ b/packages/cli/src/lib/new/factories/scaffolderModule.test.ts @@ -80,6 +80,7 @@ describe('scaffolderModule factory', () => { 'copying example.test.ts', 'copying example.ts', 'copying index.ts', + 'copying module.ts', 'Installing:', `moving plugins${sep}scaffolder-backend-module-test`, ]); diff --git a/packages/cli/src/lib/packager/productionPack.ts b/packages/cli/src/lib/packager/productionPack.ts index 6a59924a30..3c2b5aa89e 100644 --- a/packages/cli/src/lib/packager/productionPack.ts +++ b/packages/cli/src/lib/packager/productionPack.ts @@ -180,7 +180,9 @@ async function prepareExportsEntryPoints( await fs.writeJson( resolvePath(entryPointDir, PKG_PATH), { - name: pkg.name, + // Need a temporary name, as sharing the same name causes some typescript issues with caching of packages names + // And their defined `types` field. + name: `${pkg.name}__${entryPoint.name.toLocaleLowerCase('en-US')}`, version: pkg.version, ...(exp.default ? { main: posixPath.join('..', exp.default) } : {}), ...(exp.import ? { module: posixPath.join('..', exp.import) } : {}), diff --git a/packages/cli/src/lib/publishing.ts b/packages/cli/src/lib/publishing.ts index 20e4241985..c213355478 100644 --- a/packages/cli/src/lib/publishing.ts +++ b/packages/cli/src/lib/publishing.ts @@ -30,8 +30,9 @@ export function publishPreflightCheck(pkg: BackstagePackage): void { if ( role === 'backend-plugin' || role === 'backend-plugin-module' || - role === 'frontend-plugin' || - role === 'frontend-plugin-module' + role === 'frontend-plugin' + // TODO(Rugvip): We currently support plugin-less frontend modules for the new frontend system, but it needs a different solution + // || role === 'frontend-plugin-module' ) { if (!backstage.pluginId) { throw new Error( @@ -62,7 +63,8 @@ export function publishPreflightCheck(pkg: BackstagePackage): void { } if (role === 'backend-plugin-module' || role === 'frontend-plugin-module') { - if (!backstage.pluginPackage) { + // TODO(Rugvip): Remove this .pluginId check once frontend modules are required to have a plugin ID + if (backstage.pluginId && !backstage.pluginPackage) { throw new Error( `Plugin module package ${name} is missing a backstage.pluginPackage, please run 'backstage-cli repo fix --publish'`, ); diff --git a/packages/cli/src/lib/versioning/Lockfile.ts b/packages/cli/src/lib/versioning/Lockfile.ts index 6af115a4da..50d0a77cfd 100644 --- a/packages/cli/src/lib/versioning/Lockfile.ts +++ b/packages/cli/src/lib/versioning/Lockfile.ts @@ -98,24 +98,6 @@ export class Lockfile { return Lockfile.parse(lockfileContents); } - static #getRangesFromDataKey(key: string): string[] { - const [, name, ranges] = key.match(ENTRY_PATTERN) ?? []; - if (!name) { - throw new Error(`Failed to parse yarn.lock entry '${key}'`); - } - - return ranges.split(/\s*,\s*/).map(rangePart => { - let range = rangePart; - if (range.startsWith(`${name}@`)) { - range = range.slice(`${name}@`.length); - } - if (range.startsWith('npm:')) { - range = range.slice('npm:'.length); - } - return range; - }); - } - static parse(content: string) { const legacy = LEGACY_REGEX.test(content); @@ -131,7 +113,7 @@ export class Lockfile { for (const [key, value] of Object.entries(data)) { if (SPECIAL_OBJECT_KEYS.includes(key)) continue; - const [, name] = ENTRY_PATTERN.exec(key) ?? []; + const [, name, ranges] = ENTRY_PATTERN.exec(key) ?? []; if (!name) { throw new Error(`Failed to parse yarn.lock entry '${key}'`); } @@ -141,8 +123,13 @@ export class Lockfile { queries = []; packages.set(name, queries); } - const ranges = Lockfile.#getRangesFromDataKey(key); - for (const range of ranges) { + for (let range of ranges.split(/\s*,\s*/)) { + if (range.startsWith(`${name}@`)) { + range = range.slice(`${name}@`.length); + } + if (range.startsWith('npm:')) { + range = range.slice('npm:'.length); + } queries.push({ range, version: value.version, dataKey: key }); } } @@ -289,34 +276,9 @@ export class Lockfile { } remove(name: string, range: string): boolean { - const simpleQuery = `${name}@${range}`; - const query = this.getEntryOf(name, range); - + const query = `${name}@${range}`; const existed = Boolean(this.data[query]); - - if (simpleQuery === query) { - // Single-versioned entry, just delete - delete this.data[query]; - } else { - // Remove this version from the entry key. This modifies the key, so the - // package queries' needs to be updated too. - const newRanges = Lockfile.#getRangesFromDataKey(query).filter( - q => q !== simpleQuery, - ); - const newQuery = newRanges.join(', '); - - // Replace the entry with a new one without this particular range - const entry = this.data[query]; - delete this.data[query]; - this.data[newQuery] = entry; - - // Fix all package queries pointing to the old query - this.packages.get(name)?.forEach(q => { - if (q.dataKey === query) { - q.dataKey = newQuery; - } - }); - } + delete this.data[query]; const newEntries = this.packages.get(name)?.filter(e => e.range !== range); if (newEntries) { @@ -326,35 +288,19 @@ export class Lockfile { return existed; } - getEntryOf(name: string, range: string) { - const query = this.packages.get(name)?.find(q => q.range === range); - if (!query) { - throw new Error(`No entry data for ${name}@${range}`); - } - - return query.dataKey; - } - /** Modifies the lockfile by bumping packages to the suggested versions */ replaceVersions(results: AnalyzeResultNewVersion[]) { - // When replacing versions, we might replace the same version multiple times, - // as a query may contain multiple versions. This keeps the original version, - // to ensure we don't make mistakes. - const oldVersions = Object.fromEntries( - Object.entries(this.data).map(([key, val]) => [key, val.version]), - ); - for (const { name, range, oldVersion, newVersion } of results) { - const query = this.getEntryOf(name, range); + const query = `${name}@${range}`; // Update the backing data const entryData = this.data[query]; if (!entryData) { throw new Error(`No entry data for ${query}`); } - if (oldVersions[query] !== oldVersion) { + if (entryData.version !== oldVersion) { throw new Error( - `Expected existing version data for ${query} to be ${oldVersion}, was ${oldVersions[query]}`, + `Expected existing version data for ${query} to be ${oldVersion}, was ${entryData.version}`, ); } diff --git a/packages/cli/templates/default-backend-plugin/README.md.hbs b/packages/cli/templates/default-backend-plugin/README.md.hbs index 366ed27104..d519c3f459 100644 --- a/packages/cli/templates/default-backend-plugin/README.md.hbs +++ b/packages/cli/templates/default-backend-plugin/README.md.hbs @@ -11,4 +11,4 @@ start` in the root directory, and then navigating to [/{{id}}/health](http://loc You can also serve the plugin in isolation by running `yarn start` in the plugin directory. 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 [/dev](/dev) directory. +It is only meant for local development, and the setup for it can be found inside the [/dev](./dev) directory. diff --git a/packages/cli/templates/default-backend-plugin/package.json.hbs b/packages/cli/templates/default-backend-plugin/package.json.hbs index 6b7aa915aa..3b808fc5e5 100644 --- a/packages/cli/templates/default-backend-plugin/package.json.hbs +++ b/packages/cli/templates/default-backend-plugin/package.json.hbs @@ -32,20 +32,19 @@ "@backstage/backend-defaults": "{{versionQuery '@backstage/backend-defaults'}}", "@backstage/backend-plugin-api": "{{versionQuery '@backstage/backend-plugin-api'}}", "@backstage/config": "{{versionQuery '@backstage/config'}}", - "@types/express": "{{versionQuery '@types/express' '4.17.6'}}", "express": "{{versionQuery 'express' '4.17.1'}}", "express-promise-router": "{{versionQuery 'express-promise-router' '4.1.0'}}", - "winston": "{{versionQuery 'winston' '3.2.1'}}", - "node-fetch": "{{versionQuery 'node-fetch' '2.6.7'}}", - "yn": "{{versionQuery 'yn' '4.0.0'}}" + "node-fetch": "{{versionQuery 'node-fetch' '2.6.7'}}" }, "devDependencies": { + "@backstage/backend-test-utils": "{{versionQuery '@backstage/backend-test-utils'}}", "@backstage/cli": "{{versionQuery '@backstage/cli'}}", "@backstage/plugin-auth-backend": "{{versionQuery '@backstage/plugin-auth-backend'}}", "@backstage/plugin-auth-backend-module-guest-provider": "{{versionQuery '@backstage/plugin-auth-backend-module-guest-provider'}}", + "@types/express": "{{versionQuery '@types/express' '4.17.6'}}", "@types/supertest": "{{versionQuery '@types/supertest' '2.0.12'}}", "supertest": "{{versionQuery 'supertest' '6.2.4'}}", - "msw": "{{versionQuery 'msw' '1.0.0'}}" + "msw": "{{versionQuery 'msw' '2.3.1'}}" }, "files": [ "dist" diff --git a/packages/cli/templates/default-backend-plugin/src/plugin.ts.hbs b/packages/cli/templates/default-backend-plugin/src/plugin.ts.hbs index 773bd4354f..bf04b43afe 100644 --- a/packages/cli/templates/default-backend-plugin/src/plugin.ts.hbs +++ b/packages/cli/templates/default-backend-plugin/src/plugin.ts.hbs @@ -16,14 +16,17 @@ export const {{pluginVar}} = createBackendPlugin({ deps: { httpRouter: coreServices.httpRouter, logger: coreServices.logger, + config: coreServices.rootConfig, }, async init({ httpRouter, logger, + config, }) { httpRouter.use( await createRouter({ logger, + config, }), ); httpRouter.addAuthPolicy({ diff --git a/packages/cli/templates/default-backend-plugin/src/service/router.test.ts b/packages/cli/templates/default-backend-plugin/src/service/router.test.ts index 4f5079744e..ed19d50d2b 100644 --- a/packages/cli/templates/default-backend-plugin/src/service/router.test.ts +++ b/packages/cli/templates/default-backend-plugin/src/service/router.test.ts @@ -1,4 +1,4 @@ -import { getVoidLogger } from '@backstage/backend-common'; +import { mockServices } from '@backstage/backend-test-utils'; import express from 'express'; import request from 'supertest'; @@ -9,7 +9,8 @@ describe('createRouter', () => { beforeAll(async () => { const router = await createRouter({ - logger: getVoidLogger(), + logger: mockServices.logger.mock(), + config: mockServices.rootConfig(), }); app = express().use(router); }); diff --git a/packages/cli/templates/default-backend-plugin/src/service/router.ts b/packages/cli/templates/default-backend-plugin/src/service/router.ts index ff7134e59d..312d7e252e 100644 --- a/packages/cli/templates/default-backend-plugin/src/service/router.ts +++ b/packages/cli/templates/default-backend-plugin/src/service/router.ts @@ -1,16 +1,18 @@ -import { errorHandler } from '@backstage/backend-common'; +import { MiddlewareFactory } from '@backstage/backend-defaults/rootHttpRouter'; import { LoggerService } from '@backstage/backend-plugin-api'; +import { Config } from '@backstage/config'; import express from 'express'; import Router from 'express-promise-router'; export interface RouterOptions { logger: LoggerService; + config: Config; } export async function createRouter( options: RouterOptions, ): Promise { - const { logger } = options; + const { logger, config } = options; const router = Router(); router.use(express.json()); @@ -20,6 +22,8 @@ export async function createRouter( response.json({ status: 'ok' }); }); - router.use(errorHandler()); + const middleware = MiddlewareFactory.create({ logger, config }); + + router.use(middleware.error()); return router; } diff --git a/packages/cli/templates/default-plugin/package.json.hbs b/packages/cli/templates/default-plugin/package.json.hbs index fb86c7e792..c833c125f6 100644 --- a/packages/cli/templates/default-plugin/package.json.hbs +++ b/packages/cli/templates/default-plugin/package.json.hbs @@ -48,7 +48,8 @@ "@testing-library/jest-dom": "{{versionQuery '@testing-library/jest-dom' '6.0.0'}}", "@testing-library/react": "{{versionQuery '@testing-library/react' '14.0.0'}}", "@testing-library/user-event": "{{versionQuery '@testing-library/user-event' '14.0.0'}}", - "msw": "{{versionQuery 'msw' '1.0.0'}}" + "msw": "{{versionQuery 'msw' '1.0.0'}}", + "react": "{{versionQuery 'react' '^16.13.1 || ^17.0.0 || ^18.0.0'}}" }, "files": [ "dist" diff --git a/packages/cli/templates/default-react-plugin-package/package.json.hbs b/packages/cli/templates/default-react-plugin-package/package.json.hbs index c5e92eb7d6..79f3430f46 100644 --- a/packages/cli/templates/default-react-plugin-package/package.json.hbs +++ b/packages/cli/templates/default-react-plugin-package/package.json.hbs @@ -40,7 +40,8 @@ "@backstage/cli": "{{versionQuery '@backstage/cli'}}", "@backstage/test-utils": "{{versionQuery '@backstage/test-utils'}}", "@testing-library/jest-dom": "{{versionQuery '@testing-library/jest-dom' '6.0.0'}}", - "@testing-library/react": "{{versionQuery '@testing-library/react' '14.0.0'}}" + "@testing-library/react": "{{versionQuery '@testing-library/react' '14.0.0'}}", + "react": "{{versionQuery 'react' '^16.13.1 || ^17.0.0 || ^18.0.0'}}" }, "files": [ "dist" diff --git a/packages/cli/templates/scaffolder-module/src/actions/example/index.ts b/packages/cli/templates/scaffolder-module/src/actions/example/index.ts index e81099f333..06ce5befc0 100644 --- a/packages/cli/templates/scaffolder-module/src/actions/example/index.ts +++ b/packages/cli/templates/scaffolder-module/src/actions/example/index.ts @@ -1 +1,7 @@ +import { scaffolderModule } from './module'; + +/* + @deprecated - this way of importing modules will soon be unsupported, and you should use `backend.add(import(...))` instead. +*/ export { createAcmeExampleAction } from './example'; +export default scaffolderModule; diff --git a/packages/cli/templates/scaffolder-module/src/actions/example/module.ts b/packages/cli/templates/scaffolder-module/src/actions/example/module.ts new file mode 100644 index 0000000000..238268dcec --- /dev/null +++ b/packages/cli/templates/scaffolder-module/src/actions/example/module.ts @@ -0,0 +1,21 @@ +import { createBackendModule } from "@backstage/backend-plugin-api"; +import { scaffolderActionsExtensionPoint } from '@backstage/plugin-scaffolder-node/alpha'; +import { createAcmeExampleAction } from "./example"; + +/** + * A backend module that registers the action into the scaffolder + */ +export const scaffolderModule = createBackendModule({ + moduleId: 'acme:example', + pluginId: 'scaffolder', + register({ registerInit }) { + registerInit({ + deps: { + scaffolderActions: scaffolderActionsExtensionPoint + }, + async init({ scaffolderActions}) { + scaffolderActions.addActions(createAcmeExampleAction()); + } + }); + }, +}) diff --git a/packages/codemods/CHANGELOG.md b/packages/codemods/CHANGELOG.md index 58e7434b32..2a47e34b54 100644 --- a/packages/codemods/CHANGELOG.md +++ b/packages/codemods/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/codemods +## 0.1.49 + +### Patch Changes + +- Updated dependencies + - @backstage/cli-common@0.1.14 + +## 0.1.49-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/cli-common@0.1.14-next.0 + ## 0.1.48 ### Patch Changes diff --git a/packages/codemods/package.json b/packages/codemods/package.json index e4efd7f614..6bab6f3df8 100644 --- a/packages/codemods/package.json +++ b/packages/codemods/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/codemods", - "version": "0.1.48", + "version": "0.1.49", "description": "A collection of codemods for Backstage projects", "backstage": { "role": "cli" diff --git a/packages/config-loader/CHANGELOG.md b/packages/config-loader/CHANGELOG.md index 2adf312d23..fb048e7237 100644 --- a/packages/config-loader/CHANGELOG.md +++ b/packages/config-loader/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/config-loader +## 1.8.1 + +### Patch Changes + +- Updated dependencies + - @backstage/cli-common@0.1.14 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + +## 1.8.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/cli-common@0.1.14-next.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + ## 1.8.0 ### Minor Changes diff --git a/packages/config-loader/package.json b/packages/config-loader/package.json index 99dba31d4a..28718b8290 100644 --- a/packages/config-loader/package.json +++ b/packages/config-loader/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/config-loader", - "version": "1.8.0", + "version": "1.8.1", "description": "Config loading functionality used by Backstage backend, and CLI", "backstage": { "role": "node-library" diff --git a/packages/core-app-api/CHANGELOG.md b/packages/core-app-api/CHANGELOG.md index 53a9807c61..32edc95e49 100644 --- a/packages/core-app-api/CHANGELOG.md +++ b/packages/core-app-api/CHANGELOG.md @@ -1,5 +1,64 @@ # @backstage/core-app-api +## 1.13.0-next.0 + +### Minor Changes + +- d3c39fc: Allow for the disabling of external routes through config, which was rendered impossible after the introduction of default targets. + + ```yaml + app: + routes: + bindings: + # This has the effect of removing the button for registering new + # catalog entities in the scaffolder template list view + scaffolder.registerComponent: false + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.9.3 + - @backstage/config@1.2.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.8 + +## 1.12.6 + +### Patch Changes + +- 35fbe09: Added support for configuration of route bindings through static configuration, and default targets for external route refs. + + In addition to configuring route bindings through code, it is now also possible to configure route bindings under the `app.routes.bindings` key, for example: + + ```yaml + app: + routes: + bindings: + catalog.createComponent: catalog-import.importPage + ``` + + Each key in the route binding object is of the form `.`, where the route name is key used in the `externalRoutes` object passed to `createPlugin`. The value is of the same form, but with the name taken from the plugin `routes` option instead. + + The equivalent of the above configuration in code is the following: + + ```ts + const app = createApp({ + // ... + bindRoutes({ bind }) { + bind(catalogPlugin.externalRoutes, { + createComponent: catalogImportPlugin.routes.importPage, + }); + }, + }); + ``` + +- Updated dependencies + - @backstage/core-plugin-api@1.9.3 + - @backstage/config@1.2.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.8 + ## 1.12.6-next.0 ### Patch Changes diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index 8c9c31946d..bdd6a1f663 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.12.6-next.0", + "version": "1.13.0-next.0", "publishConfig": { "access": "public" }, diff --git a/packages/core-app-api/src/app/resolveRouteBindings.test.ts b/packages/core-app-api/src/app/resolveRouteBindings.test.ts index 9dfbbfd452..7d5c649a34 100644 --- a/packages/core-app-api/src/app/resolveRouteBindings.test.ts +++ b/packages/core-app-api/src/app/resolveRouteBindings.test.ts @@ -194,4 +194,35 @@ describe('collectRouteIds', () => { 'test.extRef': extRef, }); }); + + it('can disable external routes that have defaults', () => { + const source = createExternalRouteRef({ + id: 'test', + defaultTarget: 'test.target1', + }); + const target1 = createRouteRef({ id: 'test' }); + const plugin = createPlugin({ + id: 'test', + routes: { target1 }, + externalRoutes: { source }, + }); + + // resolves normally with no config + let result = resolveRouteBindings(() => {}, new MockConfigApi({}), [ + plugin, + ]); + + expect(result.get(source)).toBe(target1); + + // can be disabled + result = resolveRouteBindings( + () => {}, + new MockConfigApi({ + app: { routes: { bindings: { 'test.source': false } } }, + }), + [plugin], + ); + + expect(result.get(source)).toBe(undefined); + }); }); diff --git a/packages/core-app-api/src/app/resolveRouteBindings.ts b/packages/core-app-api/src/app/resolveRouteBindings.ts index 55e1139b29..07dfea43ee 100644 --- a/packages/core-app-api/src/app/resolveRouteBindings.ts +++ b/packages/core-app-api/src/app/resolveRouteBindings.ts @@ -102,11 +102,12 @@ export function resolveRouteBindings( const bindings = config .getOptionalConfig('app.routes.bindings') ?.get(); + const disabledExternalRefs = new Set(); if (bindings) { for (const [externalRefId, targetRefId] of Object.entries(bindings)) { - if (typeof targetRefId !== 'string' || targetRefId === '') { + if (!isValidTargetRefId(targetRefId)) { throw new Error( - `Invalid config at app.routes.bindings['${externalRefId}'], value must be a non-empty string`, + `Invalid config at app.routes.bindings['${externalRefId}'], value must be a non-empty string or false`, ); } @@ -116,23 +117,27 @@ export function resolveRouteBindings( `Invalid config at app.routes.bindings, '${externalRefId}' is not a valid external route`, ); } - 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); + if (targetRefId === false) { + disabledExternalRefs.add(externalRef); + + result.delete(externalRef); + } else if (!result.has(externalRef)) { + 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); + } } } // Finally fall back to attempting to map defaults, at lowest priority for (const externalRef of routesById.externalRoutes.values()) { - if (!result.has(externalRef)) { + if (!result.has(externalRef) && !disabledExternalRefs.has(externalRef)) { const defaultRefId = 'getDefaultTarget' in externalRef ? (externalRef.getDefaultTarget as () => string | undefined)() @@ -148,3 +153,15 @@ export function resolveRouteBindings( return result; } + +function isValidTargetRefId(value: unknown): value is string | false { + if (value === false) { + return true; + } + + if (typeof value === 'string' && value) { + return true; + } + + return false; +} diff --git a/packages/core-compat-api/CHANGELOG.md b/packages/core-compat-api/CHANGELOG.md index 852b7303f0..8bcedca9c4 100644 --- a/packages/core-compat-api/CHANGELOG.md +++ b/packages/core-compat-api/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/core-compat-api +## 0.2.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.6.7-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/version-bridge@1.0.8 + +## 0.2.6 + +### Patch Changes + +- 35fbe09: Add support for forwarding default target from legacy external route refs. +- Updated dependencies + - @backstage/core-plugin-api@1.9.3 + - @backstage/frontend-plugin-api@0.6.6 + - @backstage/version-bridge@1.0.8 + +## 0.2.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.6.6-next.2 + - @backstage/core-plugin-api@1.9.3-next.0 + - @backstage/version-bridge@1.0.8 + ## 0.2.6-next.1 ### Patch Changes diff --git a/packages/core-compat-api/package.json b/packages/core-compat-api/package.json index 9fa663ba7a..954cd6deb3 100644 --- a/packages/core-compat-api/package.json +++ b/packages/core-compat-api/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/core-compat-api", - "version": "0.2.6-next.1", + "version": "0.2.7-next.0", "backstage": { "role": "web-library" }, diff --git a/packages/core-components/CHANGELOG.md b/packages/core-components/CHANGELOG.md index c85c90ae6c..f42b6396ce 100644 --- a/packages/core-components/CHANGELOG.md +++ b/packages/core-components/CHANGELOG.md @@ -1,5 +1,48 @@ # @backstage/core-components +## 0.14.9-next.0 + +### Patch Changes + +- d4ffdbb: Fixed bug where `', () => { expect(input.textContent).toBe('test 1'); }); + it('display nothing when placeholder is empty string and items updated to none', () => { + const initialValue = 'initial'; + const initialItems = [{ label: initialValue, value: initialValue }]; + const { getByTestId, rerender } = render( + ); + + expect(getByTestId('select').textContent).toBe(''); + }); + it('display the placeholder value when selected props updated to undefined', async () => { const { getByTestId, rerender } = render( { + onChange(e.target.value); + }} + value={value} + autoComplete="off" + /> + + + + + ); +}; diff --git a/plugins/scaffolder-react/src/next/components/SecretWidget/SecretWidget.tsx b/plugins/scaffolder-react/src/next/components/SecretWidget/SecretWidget.tsx new file mode 100644 index 0000000000..e2d139f98b --- /dev/null +++ b/plugins/scaffolder-react/src/next/components/SecretWidget/SecretWidget.tsx @@ -0,0 +1,53 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { WidgetProps } from '@rjsf/utils'; +import { useTemplateSecrets } from '@backstage/plugin-scaffolder-react'; +import InputLabel from '@material-ui/core/InputLabel'; +import Input from '@material-ui/core/Input'; +import React from 'react'; + +/** + * Secret Widget for overriding the default password input widget + * @alpha + */ +export const SecretWidget = ( + props: Pick, +) => { + const { setSecrets, secrets } = useTemplateSecrets(); + const { + name, + onChange, + schema: { title }, + } = props; + + return ( + <> + {title} + { + onChange(Array(e.target?.value.length).fill('*').join('')); + setSecrets({ [name]: e.target?.value }); + }} + value={secrets[name] ?? ''} + type="password" + autoComplete="off" + /> + + ); +}; diff --git a/plugins/scaffolder-react/src/next/components/SecretWidget/index.ts b/plugins/scaffolder-react/src/next/components/SecretWidget/index.ts new file mode 100644 index 0000000000..9f0964516c --- /dev/null +++ b/plugins/scaffolder-react/src/next/components/SecretWidget/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export * from './SecretWidget'; diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx index 5bfdf1a44a..269b6a11d5 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx @@ -20,7 +20,6 @@ import MuiStep from '@material-ui/core/Step'; import MuiStepLabel from '@material-ui/core/StepLabel'; import Button from '@material-ui/core/Button'; import LinearProgress from '@material-ui/core/LinearProgress'; -import { makeStyles } from '@material-ui/core/styles'; import { type IChangeEvent } from '@rjsf/core'; import { ErrorSchema } from '@rjsf/utils'; import React, { @@ -49,6 +48,8 @@ import { } from '@backstage/plugin-scaffolder-react'; import { ReviewStepProps } from '@backstage/plugin-scaffolder-react'; import { ErrorListTemplate } from './ErrorListTemplate'; +import { makeStyles } from '@material-ui/core/styles'; +import { PasswordWidget } from '../PasswordWidget/PasswordWidget'; const useStyles = makeStyles(theme => ({ backButton: { @@ -232,6 +233,7 @@ export const Stepper = (stepperProps: StepperProps) => { showErrorList="top" templates={{ ErrorListTemplate }} onChange={handleChange} + widgets={{ password: PasswordWidget }} experimental_defaultFormStateBehavior={{ allOf: 'populateDefaults', }} diff --git a/plugins/scaffolder-react/src/next/components/Workflow/Workflow.test.tsx b/plugins/scaffolder-react/src/next/components/Workflow/Workflow.test.tsx index 27fde2083f..3a2aa1469f 100644 --- a/plugins/scaffolder-react/src/next/components/Workflow/Workflow.test.tsx +++ b/plugins/scaffolder-react/src/next/components/Workflow/Workflow.test.tsx @@ -36,6 +36,7 @@ const scaffolderApiMock: jest.Mocked = { streamLogs: jest.fn(), listActions: jest.fn(), listTasks: jest.fn(), + autocomplete: jest.fn(), }; const catalogApiMock: jest.Mocked = { getEntityByRef: jest.fn(), diff --git a/plugins/scaffolder-react/src/next/components/index.ts b/plugins/scaffolder-react/src/next/components/index.ts index 119f983a9f..02f00bb1a8 100644 --- a/plugins/scaffolder-react/src/next/components/index.ts +++ b/plugins/scaffolder-react/src/next/components/index.ts @@ -26,3 +26,4 @@ export * from './TaskLogStream'; export * from './TemplateCategoryPicker'; export * from './ScaffolderPageContextMenu'; export * from './ScaffolderField'; +export * from './SecretWidget'; diff --git a/plugins/scaffolder/CHANGELOG.md b/plugins/scaffolder/CHANGELOG.md index 7260522e54..55d7271807 100644 --- a/plugins/scaffolder/CHANGELOG.md +++ b/plugins/scaffolder/CHANGELOG.md @@ -1,5 +1,134 @@ # @backstage/plugin-scaffolder +## 1.22.0-next.0 + +### Minor Changes + +- 52b6db0: Use virtualization with `EntityPicker` as done earlier with `MultiEntityPicker` to fix performance issues with large data sets. `VirtualizedListbox` extracted into reusable component. +- 3583ce5: Use virtualization with `MultiEntityPicker`. Fixes performance issues with large data sets. +- b5deed0: Add support for `bitbucketCloud` autocomplete in `RepoUrlPicker` + +### Patch Changes + +- 661b354: Fixed a bug where the `RepoUrlPicker` would still require the `owner` field for `azure` +- 89c44b3: Support `catalogFilter` array on `OwnedEntityPicker` +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/plugin-catalog-react@1.12.2-next.0 + - @backstage/plugin-scaffolder-react@1.10.0-next.0 + - @backstage/frontend-plugin-api@0.6.7-next.0 + - @backstage/integration-react@1.1.29-next.0 + - @backstage/core-compat-api@0.2.7-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.24 + - @backstage/plugin-permission-react@0.4.23 + - @backstage/plugin-scaffolder-common@1.5.3 + +## 1.21.0 + +### Minor Changes + +- d57ebbc: Changed the way to display entities in EntityPicker to use entityPresentationApi instead of humanizeEntityRef +- 62bd9eb: Replace `ui:widget: password` with the a warning message stating that it's not secure and to use the build in `SecretField`. + + You can do this by updating your `template.yaml` files that have the reference `ui:widget: password` to `ui:field: Secret` instead. + + ```diff + apiVersion: backstage.io/v1alpha1 + kind: Template + metadata: + ... + + spec: + parameters: + - title: collect some information + schema: + type: object + properties: + password: + title: Password + type: string + - ui:widget: password + + ui:field: Secret + steps: + - id: collect-info + name: Collect some information + action: acme:do:something + input: + - password: ${{ parameters.password }} + + password: ${{ secrets.password }} + ``` + +- 60085dd: Added the following default targets for external routes: + + - `registerComponent` binds to the catalog import page. + - `viewTechDoc` binds to the TechDocs entity documentation page. + +### Patch Changes + +- cbebad1: Internal updates to allow reusing Backstage's `fetchApi` implementation for event source requests. This allows you to for example, override the `Authorization` header. +- 1ea7679: Removed waiting for the workspace and repository fields to be filled in before requesting user credentials +- d44a20a: Added additional plugin metadata to `package.json`. +- 6cb4886: Updated dependency `@rjsf/utils` to `5.18.4`. + Updated dependency `@rjsf/core` to `5.18.4`. + Updated dependency `@rjsf/material-ui` to `5.18.4`. + Updated dependency `@rjsf/validator-ajv8` to `5.18.4`. +- 75dcd7e: Fixing bug in `formData` type as it should be `optional` as it's possibly undefined +- bcec60f: updated the ContextMenu, ActionsPage, OngoingTask and TemplateCard frontend components to support the new scaffolder permissions: + + - `scaffolder.task.create` + - `scaffolder.task.cancel` + - `scaffolder.task.read` + +- 612a453: Change owner to project for azure host +- Updated dependencies + - @backstage/core-components@0.14.8 + - @backstage/core-compat-api@0.2.6 + - @backstage/integration@1.12.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/plugin-scaffolder-react@1.9.0 + - @backstage/plugin-scaffolder-common@1.5.3 + - @backstage/plugin-permission-react@0.4.23 + - @backstage/plugin-catalog-common@1.0.24 + - @backstage/plugin-catalog-react@1.12.1 + - @backstage/integration-react@1.1.28 + - @backstage/frontend-plugin-api@0.6.6 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + +## 1.21.0-next.3 + +### Minor Changes + +- d57ebbc: Changed the way to display entities in EntityPicker to use entityPresentationApi instead of humanizeEntityRef + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/core-components@0.14.8-next.2 + - @backstage/integration@1.12.0-next.1 + - @backstage/plugin-scaffolder-common@1.5.3-next.1 + - @backstage/plugin-permission-react@0.4.23-next.1 + - @backstage/plugin-scaffolder-react@1.8.7-next.3 + - @backstage/plugin-catalog-common@1.0.24-next.0 + - @backstage/plugin-catalog-react@1.12.1-next.2 + - @backstage/integration-react@1.1.28-next.1 + - @backstage/frontend-plugin-api@0.6.6-next.2 + - @backstage/core-compat-api@0.2.6-next.2 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/core-plugin-api@1.9.3-next.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + ## 1.21.0-next.2 ### Minor Changes diff --git a/plugins/scaffolder/api-report.md b/plugins/scaffolder/api-report.md index 5c766af890..f479b13ec4 100644 --- a/plugins/scaffolder/api-report.md +++ b/plugins/scaffolder/api-report.md @@ -502,6 +502,22 @@ export class ScaffolderClient implements ScaffolderApi_2 { useLongPollingLogs?: boolean; }); // (undocumented) + autocomplete({ + token, + resource, + provider, + context, + }: { + token: string; + provider: string; + resource: string; + context?: Record; + }): Promise<{ + results: { + title: string; + }[]; + }>; + // (undocumented) cancelTask(taskId: string): Promise; // (undocumented) dryRun( diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index cb6842c1c0..4cce0a83ce 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder", - "version": "1.21.0-next.2", + "version": "1.22.0-next.0", "description": "The Backstage plugin that helps you create new things", "backstage": { "role": "frontend-plugin", @@ -81,10 +81,10 @@ "@material-ui/lab": "4.0.0-alpha.61", "@microsoft/fetch-event-source": "^2.0.1", "@react-hookz/web": "^24.0.0", - "@rjsf/core": "5.18.2", - "@rjsf/material-ui": "5.18.2", - "@rjsf/utils": "5.18.2", - "@rjsf/validator-ajv8": "5.18.2", + "@rjsf/core": "5.18.4", + "@rjsf/material-ui": "5.18.4", + "@rjsf/utils": "5.18.4", + "@rjsf/validator-ajv8": "5.18.4", "@types/react": "^16.13.1 || ^17.0.0 || ^18.0.0", "@uiw/react-codemirror": "^4.9.3", "classnames": "^2.2.6", @@ -97,6 +97,7 @@ "luxon": "^3.0.0", "qs": "^6.9.4", "react-use": "^17.2.4", + "react-window": "^1.8.10", "yaml": "^2.0.0", "zen-observable": "^0.10.0", "zod": "^3.22.4", @@ -115,6 +116,7 @@ "@testing-library/user-event": "^14.0.0", "@types/humanize-duration": "^3.18.1", "@types/json-schema": "^7.0.9", + "@types/react-window": "^1.8.8", "msw": "^1.0.0", "swr": "^2.0.0" }, diff --git a/plugins/scaffolder/src/api.ts b/plugins/scaffolder/src/api.ts index 6ef5fff588..1809ed4c15 100644 --- a/plugins/scaffolder/src/api.ts +++ b/plugins/scaffolder/src/api.ts @@ -337,4 +337,38 @@ export class ScaffolderClient implements ScaffolderApi { return await response.json(); } + + async autocomplete({ + token, + resource, + provider, + context, + }: { + token: string; + provider: string; + resource: string; + context?: Record; + }): Promise<{ results: { title: string }[] }> { + const baseUrl = await this.discoveryApi.getBaseUrl('scaffolder'); + + const url = `${baseUrl}/v2/autocomplete/${provider}/${resource}`; + + const response = await this.fetchApi.fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + token, + context: context ?? {}, + }), + }); + + if (!response.ok) { + throw await ResponseError.fromResponse(response); + } + + const { results } = await response.json(); + return { results }; + } } diff --git a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx index 614e3fcff0..b548bcbad4 100644 --- a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx +++ b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx @@ -33,6 +33,7 @@ const scaffolderApiMock: jest.Mocked = { streamLogs: jest.fn(), listActions: jest.fn(), listTasks: jest.fn(), + autocomplete: jest.fn(), }; const apis = TestApiRegistry.from([scaffolderApiRef, scaffolderApiMock]); diff --git a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx index 176f6e9ce0..9eca3e85c5 100644 --- a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx +++ b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx @@ -43,6 +43,7 @@ import { EntityPickerUiOptions, EntityPickerFilterQuery, } from './schema'; +import { VirtualizedListbox } from '../VirtualizedListbox'; export { EntityPickerSchema } from './schema'; @@ -205,6 +206,7 @@ export const EntityPicker = (props: EntityPickerProps) => { entities?.entityRefToPresentation.get(stringifyEntityRef(option)) ?.primaryTitle!, })} + ListboxComponent={VirtualizedListbox} /> ); diff --git a/plugins/scaffolder/src/components/fields/MultiEntityPicker/MultiEntityPicker.tsx b/plugins/scaffolder/src/components/fields/MultiEntityPicker/MultiEntityPicker.tsx index 4ea26b4414..d800c9b372 100644 --- a/plugins/scaffolder/src/components/fields/MultiEntityPicker/MultiEntityPicker.tsx +++ b/plugins/scaffolder/src/components/fields/MultiEntityPicker/MultiEntityPicker.tsx @@ -43,6 +43,7 @@ import { MultiEntityPickerUiOptions, MultiEntityPickerFilterQuery, } from './schema'; +import { VirtualizedListbox } from '../VirtualizedListbox'; export { MultiEntityPickerSchema } from './schema'; @@ -177,6 +178,7 @@ export const MultiEntityPicker = (props: MultiEntityPickerProps) => { }} /> )} + ListboxComponent={VirtualizedListbox} /> ); diff --git a/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx b/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx index d5351d54e5..02c437ceb6 100644 --- a/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx +++ b/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx @@ -90,17 +90,11 @@ function buildEntityPickerUISchema( uiSchema?.['ui:options'] || {}; const allowedKinds = uiOptions.allowedKinds; - const catalogFilter = { - ...uiOptions.catalogFilter, - ...(allowedKinds - ? { - kind: allowedKinds, - [`relations.${RELATION_OWNED_BY}`]: identityRefs || [], - } - : { - [`relations.${RELATION_OWNED_BY}`]: identityRefs || [], - }), - }; + const catalogFilter = asArray(uiOptions.catalogFilter).map(e => ({ + ...e, + ...(allowedKinds ? { kind: allowedKinds } : {}), + [`relations.${RELATION_OWNED_BY}`]: identityRefs || [], + })); return { 'ui:options': { @@ -108,3 +102,10 @@ function buildEntityPickerUISchema( }, }; } + +function asArray(catalogFilter: any): any[] { + if (catalogFilter) { + return Array.isArray(catalogFilter) ? catalogFilter : [catalogFilter]; + } + return [{}]; +} diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/BitbucketRepoPicker.test.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/BitbucketRepoPicker.test.tsx index f799d68c2d..2ae89233ff 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/BitbucketRepoPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/BitbucketRepoPicker.test.tsx @@ -16,18 +16,33 @@ import React from 'react'; import { BitbucketRepoPicker } from './BitbucketRepoPicker'; -import { render, fireEvent } from '@testing-library/react'; +import { render, fireEvent, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { TestApiProvider } from '@backstage/test-utils'; +import { + ScaffolderApi, + scaffolderApiRef, +} from '@backstage/plugin-scaffolder-react'; +import { act } from 'react-dom/test-utils'; describe('BitbucketRepoPicker', () => { + const scaffolderApiMock: Partial = { + autocomplete: jest.fn().mockImplementation(opts => ({ + results: [{ title: `${opts.resource}_example` }], + })), + }; + it('renders a select if there is a list of allowed owners', async () => { const allowedOwners = ['owner1', 'owner2']; const { findByText } = render( - , + + + , ); expect(await findByText('owner1')).toBeInTheDocument(); @@ -38,7 +53,13 @@ describe('BitbucketRepoPicker', () => { const state = { host: 'bitbucket.org', workspace: 'lolsWorkspace' }; const { getAllByRole } = render( - , + + + , ); expect(getAllByRole('textbox')).toHaveLength(2); @@ -51,7 +72,13 @@ describe('BitbucketRepoPicker', () => { }; const { getAllByRole } = render( - , + + + , ); expect(getAllByRole('textbox')).toHaveLength(1); @@ -61,16 +88,24 @@ describe('BitbucketRepoPicker', () => { it('calls onChange when the workspace changes', () => { const onChange = jest.fn(); const { getAllByRole } = render( - , + + + , ); const workspaceInput = getAllByRole('textbox')[0]; - fireEvent.change(workspaceInput, { target: { value: 'test-workspace' } }); + act(() => { + workspaceInput.focus(); + fireEvent.change(workspaceInput, { + target: { value: 'test-workspace' }, + }); + workspaceInput.blur(); + }); expect(onChange).toHaveBeenCalledWith({ workspace: 'test-workspace' }); }); @@ -80,27 +115,35 @@ describe('BitbucketRepoPicker', () => { it('calls onChange when the project changes', () => { const onChange = jest.fn(); const { getAllByRole } = render( - , + + + , ); const projectInput = getAllByRole('textbox')[1]; - fireEvent.change(projectInput, { target: { value: 'test-project' } }); + act(() => { + projectInput.focus(); + fireEvent.change(projectInput, { target: { value: 'test-project' } }); + projectInput.blur(); + }); expect(onChange).toHaveBeenCalledWith({ project: 'test-project' }); }); it('Does not render a select if the list of allowed projects does not exist', async () => { const { getAllByRole } = render( - , + + + , ); expect(getAllByRole('textbox')).toHaveLength(2); @@ -109,12 +152,14 @@ describe('BitbucketRepoPicker', () => { it('Does not render a select if the list of allowed projects is empty', async () => { const { getAllByRole } = render( - , + + + , ); expect(getAllByRole('textbox')).toHaveLength(2); @@ -124,16 +169,104 @@ describe('BitbucketRepoPicker', () => { it('Does render a select if there is a list of allowed projects', async () => { const allowedProjects = ['project1', 'project2']; const { findByText } = render( - , + + + , ); expect(await findByText('project1')).toBeInTheDocument(); expect(await findByText('project2')).toBeInTheDocument(); }); }); + + describe('autocompletion', () => { + it('should populate workspaces if host is set and accessToken is provided', async () => { + const onChange = jest.fn(); + + const { getAllByRole, getByText } = render( + + + , + ); + + // Open the Autcomplete dropdown + const workspaceInput = getAllByRole('textbox')[0]; + await userEvent.click(workspaceInput); + + // Verify that the available workspaces are shown + await waitFor(() => + expect(getByText('workspaces_example')).toBeInTheDocument(), + ); + + // Verify that selecting an option calls onChange + await userEvent.click(getByText('workspaces_example')); + expect(onChange).toHaveBeenCalledWith({ + workspace: 'workspaces_example', + }); + }); + + it('should populate projects if host and workspace are set and accessToken is provided', async () => { + const onChange = jest.fn(); + + const { getAllByRole, getByText } = render( + + + , + ); + + // Open the Autcomplete dropdown + const projectInput = getAllByRole('textbox')[1]; + await userEvent.click(projectInput); + + // Verify that the available projects are shown + await waitFor(() => + expect(getByText('projects_example')).toBeInTheDocument(), + ); + + // Verify that selecting an option calls onChange + await userEvent.click(getByText('projects_example')); + expect(onChange).toHaveBeenCalledWith({ project: 'projects_example' }); + }); + + it('should populate repositories if host, workspace and project are set and accessToken is provided', async () => { + const onChange = jest.fn(); + + render( + + + , + ); + + // Verify that the available repos are updated + await waitFor(() => + expect(onChange).toHaveBeenCalledWith({ + availableRepos: ['repositories_example'], + }), + ); + }); + }); }); diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/BitbucketRepoPicker.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/BitbucketRepoPicker.tsx index d070e3fee5..10d4a6e6c3 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/BitbucketRepoPicker.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/BitbucketRepoPicker.tsx @@ -13,13 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React, { useEffect } from 'react'; +import React, { useEffect, useState } from 'react'; import FormControl from '@material-ui/core/FormControl'; import FormHelperText from '@material-ui/core/FormHelperText'; -import Input from '@material-ui/core/Input'; -import InputLabel from '@material-ui/core/InputLabel'; import { Select, SelectItem } from '@backstage/core-components'; import { RepoUrlPickerState } from './types'; +import Autocomplete from '@material-ui/lab/Autocomplete'; +import TextField from '@material-ui/core/TextField'; +import useDebounce from 'react-use/esm/useDebounce'; +import { useApi } from '@backstage/core-plugin-api'; +import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react'; /** * The underlying component that is rendered in the form for the `BitbucketRepoPicker` @@ -36,6 +39,7 @@ export const BitbucketRepoPicker = (props: { onChange: (state: RepoUrlPickerState) => void; state: RepoUrlPickerState; rawErrors: string[]; + accessToken?: string; }) => { const { allowedOwners = [], @@ -43,6 +47,7 @@ export const BitbucketRepoPicker = (props: { onChange, rawErrors, state, + accessToken, } = props; const { host, workspace, project } = state; const ownerItems: SelectItem[] = allowedOwners @@ -58,6 +63,100 @@ export const BitbucketRepoPicker = (props: { } }, [allowedOwners, host, onChange]); + const scaffolderApi = useApi(scaffolderApiRef); + + const [availableWorkspaces, setAvailableWorkspaces] = useState([]); + const [availableProjects, setAvailableProjects] = useState([]); + + // Update available workspaces when client is available + useDebounce( + () => { + const updateAvailableWorkspaces = async () => { + if ( + host === 'bitbucket.org' && + accessToken && + scaffolderApi.autocomplete + ) { + const { results } = await scaffolderApi.autocomplete({ + token: accessToken, + resource: 'workspaces', + context: {}, + provider: 'bitbucket-cloud', + }); + + setAvailableWorkspaces(results.map(r => r.title)); + } else { + setAvailableWorkspaces([]); + } + }; + + updateAvailableWorkspaces().catch(() => setAvailableWorkspaces([])); + }, + 500, + [host, accessToken], + ); + + // Update available projects when client is available and workspace changes + useDebounce( + () => { + const updateAvailableProjects = async () => { + if ( + host === 'bitbucket.org' && + accessToken && + workspace && + scaffolderApi.autocomplete + ) { + const { results } = await scaffolderApi.autocomplete({ + token: accessToken, + resource: 'projects', + context: { workspace }, + provider: 'bitbucket-cloud', + }); + + setAvailableProjects(results.map(r => r.title)); + } else { + setAvailableProjects([]); + } + }; + + updateAvailableProjects().catch(() => setAvailableProjects([])); + }, + 500, + [host, accessToken, workspace], + ); + + // Update available repositories when client is available and workspace or project changes + useDebounce( + () => { + const updateAvailableRepositories = async () => { + if ( + host === 'bitbucket.org' && + accessToken && + workspace && + project && + scaffolderApi.autocomplete + ) { + const { results } = await scaffolderApi.autocomplete({ + token: accessToken, + resource: 'repositories', + context: { workspace, project }, + provider: 'bitbucket-cloud', + }); + + onChange({ availableRepos: results.map(r => r.title) }); + } else { + onChange({ availableRepos: [] }); + } + }; + + updateAvailableRepositories().catch(() => + onChange({ availableRepos: [] }), + ); + }, + 500, + [host, accessToken, workspace, project], + ); + return ( <> {host === 'bitbucket.org' && ( @@ -78,14 +177,18 @@ export const BitbucketRepoPicker = (props: { items={ownerItems} /> ) : ( - <> - Workspace - onChange({ workspace: e.target.value })} - value={workspace} - /> - + { + onChange({ workspace: newValue || '' }); + }} + options={availableWorkspaces} + renderInput={params => ( + + )} + freeSolo + autoSelect + /> )} The Workspace that this repo will belong to @@ -109,14 +212,18 @@ export const BitbucketRepoPicker = (props: { items={projectItems} /> ) : ( - <> - Project - onChange({ project: e.target.value })} - value={project} - /> - + { + onChange({ project: newValue || '' }); + }} + options={availableProjects} + renderInput={params => ( + + )} + freeSolo + autoSelect + /> )} The Project that this repo will belong to diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx index 1fa723c8c6..002652cfab 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx @@ -98,8 +98,15 @@ describe('RepoUrlPicker', () => { const [ownerInput, repoInput] = getAllByRole('textbox'); const submitButton = getByRole('button'); - fireEvent.change(ownerInput, { target: { value: 'backstage' } }); - fireEvent.change(repoInput, { target: { value: 'repo123' } }); + act(() => { + ownerInput.focus(); + fireEvent.change(ownerInput, { target: { value: 'backstage' } }); + ownerInput.blur(); + + repoInput.focus(); + fireEvent.change(repoInput, { target: { value: 'repo123' } }); + repoInput.blur(); + }); fireEvent.click(submitButton); @@ -213,7 +220,7 @@ describe('RepoUrlPicker', () => {
{JSON.stringify({ secrets })}
); }; - const { getAllByRole, getByTestId } = await renderInTestApp( + const { getByTestId } = await renderInTestApp( { , ); - const [ownerInput, repoInput] = getAllByRole('textbox'); - await act(async () => { - fireEvent.change(ownerInput, { target: { value: 'backstage' } }); - fireEvent.change(repoInput, { target: { value: 'repo123' } }); - // need to wait for the debounce to finish await new Promise(resolve => setTimeout(resolve, 600)); }); expect(mockScmAuthApi.getCredentials).toHaveBeenCalledWith({ - url: 'https://github.com/backstage/repo123', + url: 'https://github.com', additionalScope: { repoWrite: true, customScopes: { @@ -278,7 +280,7 @@ describe('RepoUrlPicker', () => {
{JSON.stringify({ secrets })}
); }; - const { getAllByRole } = await renderInTestApp( + await renderInTestApp( { , ); - const [projectInput, repoInput] = getAllByRole('textbox'); - await act(async () => { - fireEvent.change(projectInput, { - target: { value: 'backstage/mysubgroup' }, - }); - fireEvent.change(repoInput, { target: { value: 'repo123' } }); - // need to wait for the debounce to finish await new Promise(resolve => setTimeout(resolve, 600)); }); expect(mockScmAuthApi.getCredentials).toHaveBeenCalledWith({ - url: 'https://gitlab.example.com/backstage/mysubgroup/repo123', + url: 'https://gitlab.example.com', additionalScope: { repoWrite: true, }, }); }); - it('should call the scmAuthApi with the correct params if only a project is set', async () => { - const SecretsComponent = () => { - const { secrets } = useTemplateSecrets(); - return ( -
{JSON.stringify({ secrets })}
- ); - }; - const { getAllByRole, getByTestId } = await renderInTestApp( - - -
, - }} - /> - - - , - ); - - const [projectInput, repoInput] = getAllByRole('textbox'); - - await act(async () => { - fireEvent.change(projectInput, { target: { value: 'backstage' } }); - fireEvent.change(repoInput, { target: { value: 'repo123' } }); - - // need to wait for the debounce to finish - await new Promise(resolve => setTimeout(resolve, 600)); - }); - - expect(mockScmAuthApi.getCredentials).toHaveBeenCalledWith({ - url: 'https://server.bitbucket.org/backstage/repo123', - additionalScope: { - repoWrite: true, - }, - }); - - const currentSecrets = JSON.parse( - getByTestId('current-secrets').textContent!, - ); - - expect(currentSecrets).toEqual({ - secrets: { testKey: 'abc123' }, - }); - }); it('should not call the scmAuthApi if secret is available in the state', async () => { const SecretsComponent = () => { @@ -397,7 +330,7 @@ describe('RepoUrlPicker', () => {
{JSON.stringify({ secrets })}
); }; - const { getAllByRole, getByTestId } = await renderInTestApp( + const { getByTestId } = await renderInTestApp( { , ); - const [ownerInput, repoInput] = getAllByRole('textbox'); - await act(async () => { - fireEvent.change(ownerInput, { target: { value: 'backstage' } }); - fireEvent.change(repoInput, { target: { value: 'repo123' } }); - // need to wait for the debounce to finish await new Promise(resolve => setTimeout(resolve, 600)); }); diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx index 5a40480889..e0d714ffda 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx @@ -124,11 +124,7 @@ export const RepoUrlPicker = (props: RepoUrlPickerProps) => { async () => { const { requestUserCredentials } = uiSchema?.['ui:options'] ?? {}; - const workspace = state.owner ? state.owner : state.project; - if ( - !requestUserCredentials || - !(state.host && workspace && state.repoName) - ) { + if (!requestUserCredentials || !state.host) { return; } @@ -137,19 +133,11 @@ export const RepoUrlPicker = (props: RepoUrlPickerProps) => { return; } - // previously, we were encodeURI for state.host, workspace and state.repoName separately. - // That created an issue where GitLab workspace can be nested like groupA/subgroupB - // when we encodeURi separately and then join, the URL will be malformed and - // resulting in 400 request error from GitLab API - const [encodedHost, encodedRepoName] = [state.host, state.repoName].map( - encodeURIComponent, - ); - // user has requested that we use the users credentials // so lets grab them using the scmAuthApi and pass through // any additional scopes from the ui:options const { token } = await scmAuthApi.getCredentials({ - url: `https://${encodedHost}/${workspace}/${encodedRepoName}`, + url: `https://${state.host}`, additionalScope: { repoWrite: true, customScopes: requestUserCredentials.additionalScopes, @@ -215,6 +203,10 @@ export const RepoUrlPicker = (props: RepoUrlPickerProps) => { rawErrors={rawErrors} state={state} onChange={updateLocalState} + accessToken={ + uiSchema?.['ui:options']?.requestUserCredentials?.secretsKey && + secrets[uiSchema['ui:options'].requestUserCredentials.secretsKey] + } /> )} {hostType === 'azure' && ( @@ -240,6 +232,7 @@ export const RepoUrlPicker = (props: RepoUrlPickerProps) => { setState(prevState => ({ ...prevState, repoName: repo })) } rawErrors={rawErrors} + availableRepos={state.availableRepos} /> ); diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerRepoName.test.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerRepoName.test.tsx index 4c392d646c..95407084c6 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerRepoName.test.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerRepoName.test.tsx @@ -16,6 +16,8 @@ import React from 'react'; import { RepoUrlPickerRepoName } from './RepoUrlPickerRepoName'; import { render, fireEvent } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { act } from 'react-dom/test-utils'; describe('RepoUrlPickerRepoName', () => { it('should call onChange with the first allowed repo if there is none set already', async () => { @@ -69,8 +71,39 @@ describe('RepoUrlPickerRepoName', () => { expect(textArea).toBeVisible(); - fireEvent.change(textArea, { target: { value: 'foo' } }); + act(() => { + textArea.focus(); + fireEvent.change(textArea, { target: { value: 'foo' } }); + textArea.blur(); + }); expect(onChange).toHaveBeenCalledWith('foo'); }); + + it('should autocomplete with provided availableRepos', async () => { + const availableRepos = ['foo', 'bar']; + + const onChange = jest.fn(); + + const { getByRole, getByText } = render( + , + ); + + // Open the Autocomplete dropdown + const input = getByRole('textbox'); + await userEvent.click(input); + + // Verify that available repos are shown + for (const repo of availableRepos) { + expect(getByText(repo)).toBeInTheDocument(); + } + + // Verify that selecting an option calls onChange + await userEvent.click(getByText(availableRepos[0])); + expect(onChange).toHaveBeenCalledWith(availableRepos[0]); + }); }); diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerRepoName.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerRepoName.tsx index f2d68b08f3..01878cb619 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerRepoName.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerRepoName.tsx @@ -17,16 +17,17 @@ import React, { useEffect } from 'react'; import { Select, SelectItem } from '@backstage/core-components'; import FormControl from '@material-ui/core/FormControl'; import FormHelperText from '@material-ui/core/FormHelperText'; -import Input from '@material-ui/core/Input'; -import InputLabel from '@material-ui/core/InputLabel'; +import Autocomplete from '@material-ui/lab/Autocomplete'; +import TextField from '@material-ui/core/TextField'; export const RepoUrlPickerRepoName = (props: { repoName?: string; allowedRepos?: string[]; onChange: (host: string) => void; rawErrors: string[]; + availableRepos?: string[]; }) => { - const { repoName, allowedRepos, onChange, rawErrors } = props; + const { repoName, allowedRepos, onChange, rawErrors, availableRepos } = props; useEffect(() => { // If there is no repoName chosen currently @@ -61,14 +62,18 @@ export const RepoUrlPickerRepoName = (props: { items={repoItems} /> ) : ( - <> - Repository - onChange(String(e.target.value))} - value={repoName} - /> - + { + onChange(newValue || ''); + }} + options={availableRepos || []} + renderInput={params => ( + + )} + freeSolo + autoSelect + /> )} The name of the repository diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/types.ts b/plugins/scaffolder/src/components/fields/RepoUrlPicker/types.ts index 5e979e789e..1430b10b84 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/types.ts +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/types.ts @@ -20,4 +20,5 @@ export interface RepoUrlPickerState { organization?: string; workspace?: string; project?: string; + availableRepos?: string[]; } diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.test.ts b/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.test.ts index b9c481957c..2b59775d3a 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.test.ts +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.test.ts @@ -36,6 +36,11 @@ describe('RepoPicker Validation', () => { host: 'server.bitbucket.com', }, ], + azure: [ + { + host: 'dev.azure.com', + }, + ], github: [ { host: 'github.com', @@ -201,4 +206,59 @@ describe('RepoPicker Validation', () => { 'Incomplete repository location provided, repo not provided', ); }); + + it('validates properly with proper input for azure', () => { + const mockFieldValidation = fieldValidator(); + + repoPickerValidation( + 'dev.azure.com?project=a&repo=b', + mockFieldValidation, + { + apiHolder: apiHolderMock, + }, + ); + + expect(mockFieldValidation.addError).not.toHaveBeenCalled(); + }); + + it('validates when no project or repo provided for azure', () => { + const mockFieldValidation = fieldValidator(); + + repoPickerValidation('dev.azure.com', mockFieldValidation, { + apiHolder: apiHolderMock, + }); + + expect(mockFieldValidation.addError).toHaveBeenNthCalledWith( + 1, + 'Incomplete repository location provided, project not provided', + ); + expect(mockFieldValidation.addError).toHaveBeenNthCalledWith( + 2, + 'Incomplete repository location provided, repo not provided', + ); + }); + + it('validates when no project provided for azure', () => { + const mockFieldValidation = fieldValidator(); + + repoPickerValidation('dev.azure.com?repo=r', mockFieldValidation, { + apiHolder: apiHolderMock, + }); + + expect(mockFieldValidation.addError).toHaveBeenCalledWith( + 'Incomplete repository location provided, project not provided', + ); + }); + + it('validates when no repo provided for azure', () => { + const mockFieldValidation = fieldValidator(); + + repoPickerValidation('dev.azure.com?project=p', mockFieldValidation, { + apiHolder: apiHolderMock, + }); + + expect(mockFieldValidation.addError).toHaveBeenCalledWith( + 'Incomplete repository location provided, repo not provided', + ); + }); }); diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts b/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts index 55ba92abdc..06c2fd5684 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts @@ -48,13 +48,19 @@ export const repoPickerValidation = ( ); } + if (!searchParams.get('project')) { + validation.addError( + 'Incomplete repository location provided, project not provided', + ); + } + } else if (integrationApi?.byHost(host)?.type === 'azure') { if (!searchParams.get('project')) { validation.addError( 'Incomplete repository location provided, project not provided', ); } } - // For anything other than bitbucket and gerrit + // For anything other than bitbucket, azure, and gerrit else if (integrationApi?.byHost(host)?.type !== 'gerrit') { if (!searchParams.get('owner')) { validation.addError( diff --git a/plugins/scaffolder/src/components/fields/SecretInput/SecretInput.tsx b/plugins/scaffolder/src/components/fields/SecretInput/SecretInput.tsx index aac0cf809a..a588286d97 100644 --- a/plugins/scaffolder/src/components/fields/SecretInput/SecretInput.tsx +++ b/plugins/scaffolder/src/components/fields/SecretInput/SecretInput.tsx @@ -14,18 +14,15 @@ * limitations under the License. */ import React from 'react'; -import { useTemplateSecrets } from '@backstage/plugin-scaffolder-react'; import { ScaffolderRJSFFieldProps } from '@backstage/plugin-scaffolder-react'; -import { ScaffolderField } from '@backstage/plugin-scaffolder-react/alpha'; -import Input from '@material-ui/core/Input'; -import InputLabel from '@material-ui/core/InputLabel'; +import { + ScaffolderField, + SecretWidget, +} from '@backstage/plugin-scaffolder-react/alpha'; export const SecretInput = (props: ScaffolderRJSFFieldProps) => { - const { setSecrets, secrets } = useTemplateSecrets(); const { - name, - onChange, - schema: { title, description }, + schema: { description }, rawErrors, disabled, errors, @@ -40,18 +37,7 @@ export const SecretInput = (props: ScaffolderRJSFFieldProps) => { errors={errors} required={required} > - {title} - { - onChange(Array(e.target?.value.length).fill('*').join('')); - setSecrets({ [name]: e.target?.value }); - }} - value={secrets[name] ?? ''} - type="password" - autoComplete="off" - /> + ); }; diff --git a/plugins/scaffolder/src/components/fields/VirtualizedListbox.tsx b/plugins/scaffolder/src/components/fields/VirtualizedListbox.tsx new file mode 100644 index 0000000000..b0920b626a --- /dev/null +++ b/plugins/scaffolder/src/components/fields/VirtualizedListbox.tsx @@ -0,0 +1,50 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { FixedSizeList, ListChildComponentProps } from 'react-window'; + +const renderRow = (props: ListChildComponentProps) => { + const { data, index, style } = props; + return React.cloneElement(data[index], { style }); +}; + +export const VirtualizedListbox = React.forwardRef< + HTMLDivElement, + { children?: React.ReactNode } +>((props, ref) => { + const itemData = React.Children.toArray(props.children); + const itemCount = itemData.length; + + const itemSize = 36; + + const itemsToShow = Math.min(10, itemCount); + const height = Math.max(itemSize, itemsToShow * itemSize - 0.5 * itemSize); + + return ( +
+ + {renderRow} + +
+ ); +}); diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.test.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.test.tsx index 269ff81271..2639e8149c 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.test.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.test.tsx @@ -51,6 +51,7 @@ const scaffolderApiMock: jest.Mocked = { streamLogs: jest.fn(), listActions: jest.fn(), listTasks: jest.fn(), + autocomplete: jest.fn(), }; const catalogApiMock: jest.Mocked = { diff --git a/plugins/search-backend-module-catalog/CHANGELOG.md b/plugins/search-backend-module-catalog/CHANGELOG.md index beb7c7dc3c..e2d6440c94 100644 --- a/plugins/search-backend-module-catalog/CHANGELOG.md +++ b/plugins/search-backend-module-catalog/CHANGELOG.md @@ -1,5 +1,62 @@ # @backstage/plugin-search-backend-module-catalog +## 0.1.27-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/plugin-catalog-node@1.12.3-next.0 + - @backstage/plugin-search-backend-node@1.2.26-next.0 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/plugin-catalog-common@1.0.24 + - @backstage/plugin-permission-common@0.7.14 + - @backstage/plugin-search-common@1.2.12 + +## 0.1.25 + +### Patch Changes + +- 78a0b08: Internal refactor to handle `BackendFeature` contract change. +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/backend-common@0.23.0 + - @backstage/backend-plugin-api@0.6.19 + - @backstage/backend-tasks@0.5.24 + - @backstage/plugin-catalog-node@1.12.1 + - @backstage/plugin-search-backend-node@1.2.24 + - @backstage/plugin-permission-common@0.7.14 + - @backstage/plugin-catalog-common@1.0.24 + - @backstage/plugin-search-common@1.2.12 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + +## 0.1.25-next.3 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/backend-plugin-api@0.6.19-next.3 + - @backstage/plugin-search-backend-node@1.2.24-next.3 + - @backstage/plugin-permission-common@0.7.14-next.0 + - @backstage/plugin-catalog-common@1.0.24-next.0 + - @backstage/plugin-search-common@1.2.12-next.0 + - @backstage/plugin-catalog-node@1.12.1-next.2 + - @backstage/backend-tasks@0.5.24-next.3 + - @backstage/backend-common@0.23.0-next.3 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + ## 0.1.25-next.2 ### Patch Changes diff --git a/plugins/search-backend-module-catalog/api-report-alpha.md b/plugins/search-backend-module-catalog/api-report-alpha.md index f840884f68..a645532384 100644 --- a/plugins/search-backend-module-catalog/api-report-alpha.md +++ b/plugins/search-backend-module-catalog/api-report-alpha.md @@ -3,7 +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 { BackendFeatureCompat } from '@backstage/backend-plugin-api'; import { CatalogCollatorEntityTransformer } from '@backstage/plugin-search-backend-module-catalog'; import { ExtensionPoint } from '@backstage/backend-plugin-api'; @@ -16,7 +16,7 @@ export type CatalogCollatorExtensionPoint = { export const catalogCollatorExtensionPoint: ExtensionPoint; // @alpha -const _default: () => BackendFeature; +const _default: BackendFeatureCompat; export default _default; // (No @packageDocumentation comment for this package) diff --git a/plugins/search-backend-module-catalog/package.json b/plugins/search-backend-module-catalog/package.json index ddeb0cb823..d46e220029 100644 --- a/plugins/search-backend-module-catalog/package.json +++ b/plugins/search-backend-module-catalog/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-backend-module-catalog", - "version": "0.1.25-next.2", + "version": "0.1.27-next.0", "description": "A module for the search backend that exports catalog modules", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/search-backend-module-catalog/src/alpha.test.ts b/plugins/search-backend-module-catalog/src/alpha.test.ts index eb2a795ecc..94c585161b 100644 --- a/plugins/search-backend-module-catalog/src/alpha.test.ts +++ b/plugins/search-backend-module-catalog/src/alpha.test.ts @@ -28,7 +28,7 @@ describe('searchModuleCatalogCollator', () => { extensionPoints: [ [searchIndexRegistryExtensionPoint, extensionPointMock], ], - features: [searchModuleCatalogCollator()], + features: [searchModuleCatalogCollator], }); expect(extensionPointMock.addCollator).toHaveBeenCalledTimes(1); @@ -50,7 +50,7 @@ describe('searchModuleCatalogCollator', () => { ], ], features: [ - searchModuleCatalogCollator(), + searchModuleCatalogCollator, mockServices.rootConfig.factory({ data: { search: { diff --git a/plugins/search-backend-module-elasticsearch/CHANGELOG.md b/plugins/search-backend-module-elasticsearch/CHANGELOG.md index 350d8b3d5e..16cf473283 100644 --- a/plugins/search-backend-module-elasticsearch/CHANGELOG.md +++ b/plugins/search-backend-module-elasticsearch/CHANGELOG.md @@ -1,5 +1,58 @@ # @backstage/plugin-search-backend-module-elasticsearch +## 1.5.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/plugin-search-backend-node@1.2.26-next.0 + - @backstage/config@1.2.0 + - @backstage/integration-aws-node@0.1.12 + - @backstage/plugin-search-common@1.2.12 + +## 1.5.0 + +### Minor Changes + +- b186701: **BREAKING**: The ElasticSearch indexer will now delete stale indices matching the indexer's pattern. + The method `getAliases` of `ElasticSearchClientWrapper` has been deprecated and might be removed in future releases. + + An indexer using the `some-type-index__*` pattern will remove indices matching this pattern after indexation + to prevent stale indices leading to shards exhaustion. + + Before upgrading ensure that the index pattern doesn't match indices that are not managed by Backstage + and thus shouldn't be deleted. + + Note: The ElasticSearch indexer already uses wildcards patterns to remove aliases on these indices. + +### Patch Changes + +- 78a0b08: Internal refactor to handle `BackendFeature` contract change. +- 6a576dc: Replace the usage of `getVoidLogger` with `mockServices.logger.mock` in order to remove the dependency with the soon-to-be-deprecated `backend-common` package. +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/backend-common@0.23.0 + - @backstage/backend-plugin-api@0.6.19 + - @backstage/plugin-search-backend-node@1.2.24 + - @backstage/plugin-search-common@1.2.12 + - @backstage/config@1.2.0 + - @backstage/integration-aws-node@0.1.12 + +## 1.4.2-next.3 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/backend-plugin-api@0.6.19-next.3 + - @backstage/plugin-search-backend-node@1.2.24-next.3 + - @backstage/plugin-search-common@1.2.12-next.0 + - @backstage/backend-common@0.23.0-next.3 + - @backstage/config@1.2.0 + - @backstage/integration-aws-node@0.1.12 + ## 1.4.2-next.2 ### Patch Changes diff --git a/plugins/search-backend-module-elasticsearch/api-report-alpha.md b/plugins/search-backend-module-elasticsearch/api-report-alpha.md index c0c30f7f2b..ca1858f9c8 100644 --- a/plugins/search-backend-module-elasticsearch/api-report-alpha.md +++ b/plugins/search-backend-module-elasticsearch/api-report-alpha.md @@ -3,12 +3,12 @@ > 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 { BackendFeatureCompat } from '@backstage/backend-plugin-api'; import { ElasticSearchQueryTranslator } from '@backstage/plugin-search-backend-module-elasticsearch'; import { ExtensionPoint } from '@backstage/backend-plugin-api'; // @alpha -const _default: () => BackendFeature; +const _default: BackendFeatureCompat; export default _default; // @alpha (undocumented) diff --git a/plugins/search-backend-module-elasticsearch/api-report.md b/plugins/search-backend-module-elasticsearch/api-report.md index 053c267f29..4c55dad91e 100644 --- a/plugins/search-backend-module-elasticsearch/api-report.md +++ b/plugins/search-backend-module-elasticsearch/api-report.md @@ -153,7 +153,7 @@ export class ElasticSearchClientWrapper { static fromClientOptions( options: ElasticSearchClientOptions, ): ElasticSearchClientWrapper; - // (undocumented) + // @deprecated (undocumented) getAliases(options: { aliases: string[]; }): @@ -166,6 +166,12 @@ export class ElasticSearchClientWrapper { | TransportRequestPromise> | TransportRequestPromise_2>; // (undocumented) + listIndices(options: { + index: string; + }): + | TransportRequestPromise, unknown>> + | TransportRequestPromise_2, unknown>>; + // (undocumented) putIndexTemplate( template: ElasticSearchCustomIndexTemplate, ): diff --git a/plugins/search-backend-module-elasticsearch/package.json b/plugins/search-backend-module-elasticsearch/package.json index a8c245c4d3..57414ec6e5 100644 --- a/plugins/search-backend-module-elasticsearch/package.json +++ b/plugins/search-backend-module-elasticsearch/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-backend-module-elasticsearch", - "version": "1.4.2-next.2", + "version": "1.5.2-next.0", "description": "A module for the search backend that implements search using ElasticSearch", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchClientWrapper.test.ts b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchClientWrapper.test.ts index 75f2e36b2b..dd5a37e5f0 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchClientWrapper.test.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchClientWrapper.test.ts @@ -39,6 +39,7 @@ jest.mock('@elastic/elasticsearch', () => ({ .mockImplementation(async args => ({ client: 'es', args })), }, indices: { + get: jest.fn().mockImplementation(async args => ({ client: 'es', args })), create: jest .fn() .mockImplementation(async args => ({ client: 'es', args })), @@ -75,6 +76,7 @@ jest.mock('@opensearch-project/opensearch', () => ({ .mockImplementation(async args => ({ client: 'os', args })), }, indices: { + get: jest.fn().mockImplementation(async args => ({ client: 'os', args })), create: jest .fn() .mockImplementation(async args => ({ client: 'os', args })), @@ -154,6 +156,16 @@ describe('ElasticSearchClientWrapper', () => { expect(result.args).toStrictEqual(indexTemplate); }); + it('indexList', async () => { + const wrapper = ElasticSearchClientWrapper.fromClientOptions(esOptions); + + const input = { index: 'xyz-*' }; + const result = (await wrapper.listIndices(input)) as any; + + expect(result.client).toBe('es'); + expect(result.args).toStrictEqual(input); + }); + it('indexExists', async () => { const wrapper = ElasticSearchClientWrapper.fromClientOptions(esOptions); @@ -282,6 +294,16 @@ describe('ElasticSearchClientWrapper', () => { expect(result.args).toStrictEqual(indexTemplate); }); + it('indexList', async () => { + const wrapper = ElasticSearchClientWrapper.fromClientOptions(osOptions); + + const input = { index: 'xyz-*' }; + const result = (await wrapper.listIndices(input)) as any; + + expect(result.client).toBe('os'); + expect(result.args).toStrictEqual(input); + }); + it('indexExists', async () => { const wrapper = ElasticSearchClientWrapper.fromClientOptions(osOptions); diff --git a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchClientWrapper.ts b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchClientWrapper.ts index a7aca3d03f..4bf8a3d998 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchClientWrapper.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchClientWrapper.ts @@ -141,6 +141,18 @@ export class ElasticSearchClientWrapper { throw new Error('No client defined'); } + listIndices(options: { index: string }) { + if (this.openSearchClient) { + return this.openSearchClient.indices.get(options); + } + + if (this.elasticSearchClient) { + return this.elasticSearchClient.indices.get(options); + } + + throw new Error('No client defined'); + } + indexExists(options: { index: string | string[] }) { if (this.openSearchClient) { return this.openSearchClient.indices.exists(options); @@ -165,18 +177,9 @@ export class ElasticSearchClientWrapper { throw new Error('No client defined'); } - createIndex(options: { index: string }) { - if (this.openSearchClient) { - return this.openSearchClient.indices.create(options); - } - - if (this.elasticSearchClient) { - return this.elasticSearchClient.indices.create(options); - } - - throw new Error('No client defined'); - } - + /** + * @deprecated unused by the ElasticSearch Engine, will be removed in the future + */ getAliases(options: { aliases: string[] }) { const { aliases } = options; @@ -197,6 +200,18 @@ export class ElasticSearchClientWrapper { throw new Error('No client defined'); } + createIndex(options: { index: string }) { + if (this.openSearchClient) { + return this.openSearchClient.indices.create(options); + } + + if (this.elasticSearchClient) { + return this.elasticSearchClient.indices.create(options); + } + + throw new Error('No client defined'); + } + updateAliases(options: { actions: ElasticSearchAliasAction[] }) { const filteredActions = options.actions.filter(Boolean); diff --git a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngineIndexer.test.ts b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngineIndexer.test.ts index 44d33c27a5..1590d5fb2a 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngineIndexer.test.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngineIndexer.test.ts @@ -30,7 +30,7 @@ const clientWrapper = ElasticSearchClientWrapper.fromClientOptions({ describe('ElasticSearchSearchEngineIndexer', () => { let indexer: ElasticSearchSearchEngineIndexer; let bulkSpy: jest.Mock; - let catSpy: jest.Mock; + let getSpy: jest.Mock; let createSpy: jest.Mock; let aliasesSpy: jest.Mock; let deleteSpy: jest.Mock; @@ -68,30 +68,24 @@ describe('ElasticSearchSearchEngineIndexer', () => { refreshSpy, ); - catSpy = jest.fn().mockReturnValue([ - { - alias: 'some-type-index__search', - index: 'some-type-index__123tobedeleted', - filter: '-', - 'routing.index': '-', - 'routing.search': '-', - is_write_index: '-', + getSpy = jest.fn().mockReturnValue({ + 'some-type-index__123tobedeleted': { + aliases: {}, + mappings: {}, + settings: {}, }, - { - alias: 'some-type-index__search_removable', - index: 'some-type-index__456tobedeleted', - filter: '-', - 'routing.index': '-', - 'routing.search': '-', - is_write_index: '-', + 'some-type-index__456tobedeleted': { + aliases: {}, + mappings: {}, + settings: {}, }, - ]); + }); mock.add( { method: 'GET', - path: '/_cat/aliases/some-type-index__search%2Csome-type-index__search_removable', + path: '/some-type-index__*', }, - catSpy, + getSpy, ); createSpy = jest.fn().mockReturnValue({ @@ -120,7 +114,7 @@ describe('ElasticSearchSearchEngineIndexer', () => { mock.add( { method: 'DELETE', - path: '/some-type-index__123tobedeleted%2Csome-type-index__456tobedeleted', + path: '/*', }, deleteSpy, ); @@ -143,7 +137,7 @@ describe('ElasticSearchSearchEngineIndexer', () => { await TestPipeline.fromIndexer(indexer).withDocuments(documents).execute(); // Older indices should have been queried for. - expect(catSpy).toHaveBeenCalled(); + expect(getSpy).toHaveBeenCalled(); // A new index should have been created. const createdIndex = createSpy.mock.calls[0][0].path.slice(1); @@ -163,27 +157,22 @@ describe('ElasticSearchSearchEngineIndexer', () => { remove: { index: 'some-type-index__*', alias: 'some-type-index__search' }, }); expect(aliasActions[1]).toStrictEqual({ - add: { - indices: [ - 'some-type-index__123tobedeleted', - 'some-type-index__456tobedeleted', - ], - alias: 'some-type-index__search_removable', - }, - }); - expect(aliasActions[2]).toStrictEqual({ add: { index: createdIndex, alias: 'some-type-index__search' }, }); // Old index should be cleaned up. - expect(deleteSpy).toHaveBeenCalled(); + expect(deleteSpy).toHaveBeenCalledWith( + expect.objectContaining({ + path: '/some-type-index__123tobedeleted%2Csome-type-index__456tobedeleted', + }), + ); }); it('handles when no documents are received', async () => { await TestPipeline.fromIndexer(indexer).withDocuments([]).execute(); // Older indices should have been queried for. - expect(catSpy).toHaveBeenCalled(); + expect(getSpy).toHaveBeenCalled(); // A new index should have been created. expect(createSpy).toHaveBeenNthCalledWith( @@ -200,7 +189,11 @@ describe('ElasticSearchSearchEngineIndexer', () => { expect(aliasesSpy).not.toHaveBeenCalled(); // Old index should not be cleaned up. - expect(deleteSpy).not.toHaveBeenCalled(); + expect(deleteSpy).toHaveBeenCalledWith( + expect.objectContaining({ + path: expect.not.stringContaining('tobedeleted'), + }), + ); }); it('handles bulk and batching during indexing', async () => { @@ -236,17 +229,17 @@ describe('ElasticSearchSearchEngineIndexer', () => { ]; // Update initial alias cat to return nothing. - catSpy = jest.fn().mockReturnValue([]); + getSpy = jest.fn().mockReturnValue({}); mock.clear({ method: 'GET', - path: '/_cat/aliases/some-type-index__search%2Csome-type-index__search_removable', + path: '/some-type-index__*', }); mock.add( { method: 'GET', - path: '/_cat/aliases/some-type-index__search%2Csome-type-index__search_removable', + path: '/some-type-index__*', }, - catSpy, + getSpy, ); await TestPipeline.fromIndexer(indexer).withDocuments(documents).execute(); @@ -255,6 +248,47 @@ describe('ElasticSearchSearchEngineIndexer', () => { expect(deleteSpy).not.toHaveBeenCalled(); }); + it('split index deletion in chunks', async () => { + // Generate 200 existing indices + const currentIndices = Array.from( + new Array(200), + (_, i) => `some-type-index__old${i}`, + ); + + const indicesResponse = currentIndices.reduce((acc, curr) => { + return { + ...acc, + [curr]: { mappings: {}, aliases: {} }, + }; + }, {}); + + getSpy = jest.fn().mockReturnValue(indicesResponse); + mock.clear({ + method: 'GET', + path: '/some-type-index__*', + }); + mock.add( + { + method: 'GET', + path: '/some-type-index__*', + }, + getSpy, + ); + + await TestPipeline.fromIndexer(indexer) + .withDocuments([ + { + title: 'testTerm', + text: 'testText', + location: 'test/location', + }, + ]) + .execute(); + + // Delete endpoint should have been called for 4 chunks of 50 (200 indices) + expect(deleteSpy).toHaveBeenCalledTimes(4); + }); + it('handles bulk client rejection', async () => { // Given an ES client wrapper that rejects an error const expectedError = new Error('HTTP Timeout'); diff --git a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngineIndexer.ts b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngineIndexer.ts index 4b1307114a..616c1ca349 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngineIndexer.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngineIndexer.ts @@ -56,7 +56,6 @@ export class ElasticSearchSearchEngineIndexer extends BatchSearchEngineIndexer { private readonly indexPrefix: string; private readonly indexSeparator: string; private readonly alias: string; - private readonly removableAlias: string; private readonly logger: Logger | LoggerService; private readonly sourceStream: Readable; private readonly elasticSearchClientWrapper: ElasticSearchClientWrapper; @@ -74,7 +73,6 @@ export class ElasticSearchSearchEngineIndexer extends BatchSearchEngineIndexer { this.indexSeparator = options.indexSeparator; this.indexName = this.constructIndexName(`${Date.now()}`); this.alias = options.alias; - this.removableAlias = `${this.alias}_removable`; this.elasticSearchClientWrapper = options.elasticSearchClientWrapper; // The ES client bulk helper supports stream-based indexing, but we have to @@ -108,13 +106,13 @@ export class ElasticSearchSearchEngineIndexer extends BatchSearchEngineIndexer { async initialize(): Promise { this.logger.info(`Started indexing documents for index ${this.type}`); - const aliases = await this.elasticSearchClientWrapper.getAliases({ - aliases: [this.alias, this.removableAlias], + const indices = await this.elasticSearchClientWrapper.listIndices({ + index: this.constructIndexName('*'), }); - this.removableIndices = [ - ...new Set(aliases.body.map((r: Record) => r.index)), - ] as string[]; + for (const key of Object.keys(indices.body)) { + this.removableIndices.push(key); + } await this.elasticSearchClientWrapper.createIndex({ index: this.indexName, @@ -171,14 +169,6 @@ export class ElasticSearchSearchEngineIndexer extends BatchSearchEngineIndexer { { remove: { index: this.constructIndexName('*'), alias: this.alias }, }, - this.removableIndices.length - ? { - add: { - indices: this.removableIndices, - alias: this.removableAlias, - }, - } - : undefined, { add: { index: this.indexName, alias: this.alias }, }, @@ -191,12 +181,33 @@ export class ElasticSearchSearchEngineIndexer extends BatchSearchEngineIndexer { this.logger.info('Removing stale search indices', { removableIndices: this.removableIndices, }); - try { - await this.elasticSearchClientWrapper.deleteIndex({ - index: this.removableIndices, - }); - } catch (e) { - this.logger.warn(`Failed to remove stale search indices: ${e}`); + + // Split the array into chunks of up to 50 indices to handle the case + // where we need to delete a lot of stalled indices + const chunks = this.removableIndices.reduce( + (resultArray, item, index) => { + const chunkIndex = Math.floor(index / 50); + + if (!resultArray[chunkIndex]) { + resultArray[chunkIndex] = []; // start a new chunk + } + + resultArray[chunkIndex].push(item); + + return resultArray; + }, + [] as string[][], + ); + + // Call deleteIndex for each chunk + for (const chunk of chunks) { + try { + await this.elasticSearchClientWrapper.deleteIndex({ + index: chunk, + }); + } catch (e) { + this.logger.warn(`Failed to remove stale search indices: ${e}`); + } } } } diff --git a/plugins/search-backend-module-explore/CHANGELOG.md b/plugins/search-backend-module-explore/CHANGELOG.md index 4ca395300b..4b75d163f9 100644 --- a/plugins/search-backend-module-explore/CHANGELOG.md +++ b/plugins/search-backend-module-explore/CHANGELOG.md @@ -1,5 +1,44 @@ # @backstage/plugin-search-backend-module-explore +## 0.1.27-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/plugin-search-backend-node@1.2.26-next.0 + - @backstage/config@1.2.0 + - @backstage/plugin-search-common@1.2.12 + +## 0.1.25 + +### Patch Changes + +- 78a0b08: Internal refactor to handle `BackendFeature` contract change. +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/backend-common@0.23.0 + - @backstage/backend-plugin-api@0.6.19 + - @backstage/backend-tasks@0.5.24 + - @backstage/plugin-search-backend-node@1.2.24 + - @backstage/plugin-search-common@1.2.12 + - @backstage/config@1.2.0 + +## 0.1.25-next.3 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/backend-plugin-api@0.6.19-next.3 + - @backstage/plugin-search-backend-node@1.2.24-next.3 + - @backstage/plugin-search-common@1.2.12-next.0 + - @backstage/backend-tasks@0.5.24-next.3 + - @backstage/backend-common@0.23.0-next.3 + - @backstage/config@1.2.0 + ## 0.1.25-next.2 ### Patch Changes diff --git a/plugins/search-backend-module-explore/api-report-alpha.md b/plugins/search-backend-module-explore/api-report-alpha.md index e1ecb85886..052860b957 100644 --- a/plugins/search-backend-module-explore/api-report-alpha.md +++ b/plugins/search-backend-module-explore/api-report-alpha.md @@ -3,10 +3,10 @@ > 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 { BackendFeatureCompat } from '@backstage/backend-plugin-api'; // @alpha -const _default: () => BackendFeature; +const _default: BackendFeatureCompat; export default _default; // (No @packageDocumentation comment for this package) diff --git a/plugins/search-backend-module-explore/package.json b/plugins/search-backend-module-explore/package.json index 2d177c73bf..13cba189e5 100644 --- a/plugins/search-backend-module-explore/package.json +++ b/plugins/search-backend-module-explore/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-backend-module-explore", - "version": "0.1.25-next.2", + "version": "0.1.27-next.0", "description": "A module for the search backend that exports explore modules", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/search-backend-module-explore/src/alpha.test.ts b/plugins/search-backend-module-explore/src/alpha.test.ts index fa6ab8a909..2ba01ec478 100644 --- a/plugins/search-backend-module-explore/src/alpha.test.ts +++ b/plugins/search-backend-module-explore/src/alpha.test.ts @@ -35,7 +35,7 @@ describe('searchModuleExploreCollator', () => { [searchIndexRegistryExtensionPoint, extensionPointMock], ], features: [ - searchModuleExploreCollator(), + searchModuleExploreCollator, mockServices.rootConfig.factory({ data: { search: { diff --git a/plugins/search-backend-module-pg/CHANGELOG.md b/plugins/search-backend-module-pg/CHANGELOG.md index afd7d5d5b6..376d266f8f 100644 --- a/plugins/search-backend-module-pg/CHANGELOG.md +++ b/plugins/search-backend-module-pg/CHANGELOG.md @@ -1,5 +1,45 @@ # @backstage/plugin-search-backend-module-pg +## 0.5.31-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-app-api@0.7.9-next.0 + - @backstage/plugin-search-backend-node@1.2.26-next.0 + - @backstage/config@1.2.0 + - @backstage/plugin-search-common@1.2.12 + +## 0.5.28 + +### Patch Changes + +- 78a0b08: Internal refactor to handle `BackendFeature` contract change. +- 6a576dc: Replace the usage of `getVoidLogger` with `mockServices.logger.mock` in order to remove the dependency with the soon-to-be-deprecated `backend-common` package. +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/backend-app-api@0.7.6 + - @backstage/backend-common@0.23.0 + - @backstage/backend-plugin-api@0.6.19 + - @backstage/plugin-search-backend-node@1.2.24 + - @backstage/plugin-search-common@1.2.12 + - @backstage/config@1.2.0 + +## 0.5.28-next.3 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/backend-plugin-api@0.6.19-next.3 + - @backstage/plugin-search-backend-node@1.2.24-next.3 + - @backstage/plugin-search-common@1.2.12-next.0 + - @backstage/backend-common@0.23.0-next.3 + - @backstage/backend-app-api@0.7.6-next.3 + - @backstage/config@1.2.0 + ## 0.5.28-next.2 ### Patch Changes diff --git a/plugins/search-backend-module-pg/api-report-alpha.md b/plugins/search-backend-module-pg/api-report-alpha.md index b021f6884f..ea2f6afece 100644 --- a/plugins/search-backend-module-pg/api-report-alpha.md +++ b/plugins/search-backend-module-pg/api-report-alpha.md @@ -3,10 +3,10 @@ > 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 { BackendFeatureCompat } from '@backstage/backend-plugin-api'; // @alpha -const _default: () => BackendFeature; +const _default: BackendFeatureCompat; export default _default; // (No @packageDocumentation comment for this package) diff --git a/plugins/search-backend-module-pg/package.json b/plugins/search-backend-module-pg/package.json index 83f6d72875..3319d85dbb 100644 --- a/plugins/search-backend-module-pg/package.json +++ b/plugins/search-backend-module-pg/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-backend-module-pg", - "version": "0.5.28-next.2", + "version": "0.5.31-next.0", "description": "A module for the search backend that implements search using PostgreSQL", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/search-backend-module-stack-overflow-collator/CHANGELOG.md b/plugins/search-backend-module-stack-overflow-collator/CHANGELOG.md index 63f008a851..91652d5543 100644 --- a/plugins/search-backend-module-stack-overflow-collator/CHANGELOG.md +++ b/plugins/search-backend-module-stack-overflow-collator/CHANGELOG.md @@ -1,5 +1,44 @@ # @backstage/plugin-search-backend-module-stack-overflow-collator +## 0.1.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/plugin-search-backend-node@1.2.26-next.0 + - @backstage/config@1.2.0 + - @backstage/plugin-search-common@1.2.12 + +## 0.1.12 + +### Patch Changes + +- 78a0b08: Internal refactor to handle `BackendFeature` contract change. +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/backend-common@0.23.0 + - @backstage/backend-plugin-api@0.6.19 + - @backstage/backend-tasks@0.5.24 + - @backstage/plugin-search-backend-node@1.2.24 + - @backstage/plugin-search-common@1.2.12 + - @backstage/config@1.2.0 + +## 0.1.12-next.3 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/backend-plugin-api@0.6.19-next.3 + - @backstage/plugin-search-backend-node@1.2.24-next.3 + - @backstage/plugin-search-common@1.2.12-next.0 + - @backstage/backend-tasks@0.5.24-next.3 + - @backstage/backend-common@0.23.0-next.3 + - @backstage/config@1.2.0 + ## 0.1.12-next.2 ### Patch Changes diff --git a/plugins/search-backend-module-stack-overflow-collator/api-report.md b/plugins/search-backend-module-stack-overflow-collator/api-report.md index d70b5f79fd..bf5ebb5408 100644 --- a/plugins/search-backend-module-stack-overflow-collator/api-report.md +++ b/plugins/search-backend-module-stack-overflow-collator/api-report.md @@ -5,7 +5,7 @@ ```ts /// -import { BackendFeature } from '@backstage/backend-plugin-api'; +import { BackendFeatureCompat } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import { DocumentCollatorFactory } from '@backstage/plugin-search-common'; import { IndexableDocument } from '@backstage/plugin-search-common'; @@ -13,7 +13,7 @@ import { LoggerService } from '@backstage/backend-plugin-api'; import { Readable } from 'stream'; // @public -const searchStackOverflowCollatorModule: () => BackendFeature; +const searchStackOverflowCollatorModule: BackendFeatureCompat; export default searchStackOverflowCollatorModule; // @public diff --git a/plugins/search-backend-module-stack-overflow-collator/package.json b/plugins/search-backend-module-stack-overflow-collator/package.json index c35347f8da..60b658a34a 100644 --- a/plugins/search-backend-module-stack-overflow-collator/package.json +++ b/plugins/search-backend-module-stack-overflow-collator/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-backend-module-stack-overflow-collator", - "version": "0.1.12-next.2", + "version": "0.1.14-next.0", "description": "A module for the search backend that exports stack overflow modules", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/search-backend-module-stack-overflow-collator/src/module/SearchStackOverflowCollatorModule.test.ts b/plugins/search-backend-module-stack-overflow-collator/src/module/SearchStackOverflowCollatorModule.test.ts index a785ead6eb..4e9bc05b73 100644 --- a/plugins/search-backend-module-stack-overflow-collator/src/module/SearchStackOverflowCollatorModule.test.ts +++ b/plugins/search-backend-module-stack-overflow-collator/src/module/SearchStackOverflowCollatorModule.test.ts @@ -35,7 +35,7 @@ describe('searchStackOverflowCollatorModule', () => { [searchIndexRegistryExtensionPoint, extensionPointMock], ], features: [ - searchStackOverflowCollatorModule(), + searchStackOverflowCollatorModule, mockServices.rootConfig.factory({ data: { stackoverflow: { diff --git a/plugins/search-backend-module-techdocs/CHANGELOG.md b/plugins/search-backend-module-techdocs/CHANGELOG.md index e2d7c21867..4e7e3c4baa 100644 --- a/plugins/search-backend-module-techdocs/CHANGELOG.md +++ b/plugins/search-backend-module-techdocs/CHANGELOG.md @@ -1,5 +1,62 @@ # @backstage/plugin-search-backend-module-techdocs +## 0.1.26-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/plugin-catalog-node@1.12.3-next.0 + - @backstage/plugin-search-backend-node@1.2.26-next.0 + - @backstage/plugin-techdocs-node@1.12.7-next.0 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/plugin-catalog-common@1.0.24 + - @backstage/plugin-permission-common@0.7.14 + - @backstage/plugin-search-common@1.2.12 + +## 0.1.24 + +### Patch Changes + +- 78a0b08: Internal refactor to handle `BackendFeature` contract change. +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/backend-common@0.23.0 + - @backstage/backend-plugin-api@0.6.19 + - @backstage/backend-tasks@0.5.24 + - @backstage/plugin-techdocs-node@1.12.5 + - @backstage/plugin-catalog-node@1.12.1 + - @backstage/plugin-search-backend-node@1.2.24 + - @backstage/plugin-permission-common@0.7.14 + - @backstage/plugin-catalog-common@1.0.24 + - @backstage/plugin-search-common@1.2.12 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + +## 0.1.24-next.3 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/backend-plugin-api@0.6.19-next.3 + - @backstage/plugin-search-backend-node@1.2.24-next.3 + - @backstage/plugin-permission-common@0.7.14-next.0 + - @backstage/plugin-catalog-common@1.0.24-next.0 + - @backstage/plugin-search-common@1.2.12-next.0 + - @backstage/plugin-techdocs-node@1.12.5-next.3 + - @backstage/plugin-catalog-node@1.12.1-next.2 + - @backstage/backend-tasks@0.5.24-next.3 + - @backstage/backend-common@0.23.0-next.3 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + ## 0.1.24-next.2 ### Patch Changes diff --git a/plugins/search-backend-module-techdocs/api-report-alpha.md b/plugins/search-backend-module-techdocs/api-report-alpha.md index df98623631..ed1e72b3bf 100644 --- a/plugins/search-backend-module-techdocs/api-report-alpha.md +++ b/plugins/search-backend-module-techdocs/api-report-alpha.md @@ -3,12 +3,12 @@ > 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 { BackendFeatureCompat } from '@backstage/backend-plugin-api'; import { ExtensionPoint } from '@backstage/backend-plugin-api'; import { TechDocsCollatorEntityTransformer } from '@backstage/plugin-search-backend-module-techdocs'; // @alpha -const _default: () => BackendFeature; +const _default: BackendFeatureCompat; export default _default; // @alpha (undocumented) diff --git a/plugins/search-backend-module-techdocs/package.json b/plugins/search-backend-module-techdocs/package.json index d487866f3d..1650012d93 100644 --- a/plugins/search-backend-module-techdocs/package.json +++ b/plugins/search-backend-module-techdocs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-backend-module-techdocs", - "version": "0.1.24-next.2", + "version": "0.1.26-next.0", "description": "A module for the search backend that exports techdocs modules", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/search-backend-module-techdocs/src/alpha.test.ts b/plugins/search-backend-module-techdocs/src/alpha.test.ts index a278614b75..f1875a881b 100644 --- a/plugins/search-backend-module-techdocs/src/alpha.test.ts +++ b/plugins/search-backend-module-techdocs/src/alpha.test.ts @@ -35,7 +35,7 @@ describe('searchModuleTechDocsCollator', () => { [searchIndexRegistryExtensionPoint, extensionPointMock], ], features: [ - searchModuleTechDocsCollator(), + searchModuleTechDocsCollator, mockServices.rootConfig.factory({ data: { search: { diff --git a/plugins/search-backend-node/CHANGELOG.md b/plugins/search-backend-node/CHANGELOG.md index c0cc9e1c0e..5209cb8753 100644 --- a/plugins/search-backend-node/CHANGELOG.md +++ b/plugins/search-backend-node/CHANGELOG.md @@ -1,5 +1,48 @@ # @backstage/plugin-search-backend-node +## 1.2.26-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-tasks@0.5.26-next.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/plugin-permission-common@0.7.14 + - @backstage/plugin-search-common@1.2.12 + +## 1.2.24 + +### Patch Changes + +- 6a576dc: Replace the usage of `getVoidLogger` with `mockServices.logger.mock` in order to remove the dependency with the soon-to-be-deprecated `backend-common` package. +- d44a20a: Added additional plugin metadata to `package.json`. +- 5b6f979: Split backend search plugin startup into "init" and "start" stages to ensure necessary initialization has happened before startup +- Updated dependencies + - @backstage/backend-common@0.23.0 + - @backstage/backend-plugin-api@0.6.19 + - @backstage/backend-tasks@0.5.24 + - @backstage/plugin-permission-common@0.7.14 + - @backstage/plugin-search-common@1.2.12 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + +## 1.2.24-next.3 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/backend-plugin-api@0.6.19-next.3 + - @backstage/plugin-permission-common@0.7.14-next.0 + - @backstage/plugin-search-common@1.2.12-next.0 + - @backstage/backend-tasks@0.5.24-next.3 + - @backstage/backend-common@0.23.0-next.3 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + ## 1.2.24-next.2 ### Patch Changes diff --git a/plugins/search-backend-node/package.json b/plugins/search-backend-node/package.json index 20d5e70048..ef655ac566 100644 --- a/plugins/search-backend-node/package.json +++ b/plugins/search-backend-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-backend-node", - "version": "1.2.24-next.2", + "version": "1.2.26-next.0", "description": "A library for Backstage backend plugins that want to interact with the search backend plugin", "backstage": { "role": "node-library", diff --git a/plugins/search-backend/CHANGELOG.md b/plugins/search-backend/CHANGELOG.md index c51185b2a3..ea4142e583 100644 --- a/plugins/search-backend/CHANGELOG.md +++ b/plugins/search-backend/CHANGELOG.md @@ -1,5 +1,62 @@ # @backstage/plugin-search-backend +## 1.5.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-defaults@0.3.3-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/backend-openapi-utils@0.1.14-next.0 + - @backstage/plugin-permission-node@0.7.32-next.0 + - @backstage/plugin-search-backend-node@1.2.26-next.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.14 + - @backstage/plugin-search-common@1.2.12 + +## 1.5.10 + +### Patch Changes + +- 8869b8e: Updated local development setup. +- 78a0b08: Internal refactor to handle `BackendFeature` contract change. +- d44a20a: Added additional plugin metadata to `package.json`. +- 5b6f979: Split backend search plugin startup into "init" and "start" stages to ensure necessary initialization has happened before startup +- 34dc47d: Move @backstage/repo-tools to devDependencies +- Updated dependencies + - @backstage/backend-common@0.23.0 + - @backstage/backend-plugin-api@0.6.19 + - @backstage/backend-defaults@0.3.0 + - @backstage/plugin-search-backend-node@1.2.24 + - @backstage/plugin-permission-node@0.7.30 + - @backstage/plugin-permission-common@0.7.14 + - @backstage/plugin-search-common@1.2.12 + - @backstage/backend-openapi-utils@0.1.12 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + +## 1.5.10-next.3 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/backend-plugin-api@0.6.19-next.3 + - @backstage/backend-defaults@0.3.0-next.3 + - @backstage/plugin-search-backend-node@1.2.24-next.3 + - @backstage/plugin-permission-common@0.7.14-next.0 + - @backstage/plugin-permission-node@0.7.30-next.3 + - @backstage/plugin-search-common@1.2.12-next.0 + - @backstage/backend-common@0.23.0-next.3 + - @backstage/backend-openapi-utils@0.1.12-next.2 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + ## 1.5.10-next.2 ### Patch Changes diff --git a/plugins/search-backend/api-report-alpha.md b/plugins/search-backend/api-report-alpha.md index 548f4c6608..2e5de660cb 100644 --- a/plugins/search-backend/api-report-alpha.md +++ b/plugins/search-backend/api-report-alpha.md @@ -3,10 +3,10 @@ > 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 { BackendFeatureCompat } from '@backstage/backend-plugin-api'; // @alpha -const _default: () => BackendFeature; +const _default: BackendFeatureCompat; export default _default; // (No @packageDocumentation comment for this package) diff --git a/plugins/search-backend/package.json b/plugins/search-backend/package.json index 97287b8f87..c1d536d4d4 100644 --- a/plugins/search-backend/package.json +++ b/plugins/search-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-backend", - "version": "1.5.10-next.2", + "version": "1.5.13-next.0", "description": "The Backstage backend plugin that provides your backstage app with search", "backstage": { "role": "backend-plugin", diff --git a/plugins/search-backend/src/alpha.test.ts b/plugins/search-backend/src/alpha.test.ts index a18ab7e104..dfe80987d4 100644 --- a/plugins/search-backend/src/alpha.test.ts +++ b/plugins/search-backend/src/alpha.test.ts @@ -21,7 +21,7 @@ import searchPlugin from './alpha'; describe('searchPlugin', () => { it('should serve search results on query endpoint', async () => { const { server } = await startTestBackend({ - features: [searchPlugin()], + features: [searchPlugin], }); const response = await request(server).get('/api/search/query'); diff --git a/plugins/search-common/CHANGELOG.md b/plugins/search-common/CHANGELOG.md index ae1b24dea6..e034c62315 100644 --- a/plugins/search-common/CHANGELOG.md +++ b/plugins/search-common/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-search-common +## 1.2.12 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/plugin-permission-common@0.7.14 + - @backstage/types@1.1.1 + +## 1.2.12-next.0 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/plugin-permission-common@0.7.14-next.0 + - @backstage/types@1.1.1 + ## 1.2.11 ### Patch Changes diff --git a/plugins/search-common/package.json b/plugins/search-common/package.json index 346a248bf6..61edfd13f3 100644 --- a/plugins/search-common/package.json +++ b/plugins/search-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-common", - "version": "1.2.11", + "version": "1.2.12", "description": "Common functionalities for Search, to be shared between various search-enabled plugins", "backstage": { "role": "common-library", diff --git a/plugins/search-react/CHANGELOG.md b/plugins/search-react/CHANGELOG.md index ab153126eb..19ace29f0c 100644 --- a/plugins/search-react/CHANGELOG.md +++ b/plugins/search-react/CHANGELOG.md @@ -1,5 +1,46 @@ # @backstage/plugin-search-react +## 1.7.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/frontend-plugin-api@0.6.7-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/theme@0.5.6 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.8 + - @backstage/plugin-search-common@1.2.12 + +## 1.7.12 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/core-components@0.14.8 + - @backstage/core-plugin-api@1.9.3 + - @backstage/theme@0.5.6 + - @backstage/plugin-search-common@1.2.12 + - @backstage/frontend-plugin-api@0.6.6 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.8 + +## 1.7.12-next.2 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/core-components@0.14.8-next.2 + - @backstage/plugin-search-common@1.2.12-next.0 + - @backstage/frontend-plugin-api@0.6.6-next.2 + - @backstage/core-plugin-api@1.9.3-next.0 + - @backstage/theme@0.5.6-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.8 + ## 1.7.12-next.1 ### Patch Changes diff --git a/plugins/search-react/package.json b/plugins/search-react/package.json index 2cd8d0af3d..25bc946bd4 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.12-next.1", + "version": "1.7.13-next.0", "backstage": { "role": "web-library", "pluginId": "search", diff --git a/plugins/search/CHANGELOG.md b/plugins/search/CHANGELOG.md index d1bcaa6c97..effe205170 100644 --- a/plugins/search/CHANGELOG.md +++ b/plugins/search/CHANGELOG.md @@ -1,5 +1,56 @@ # @backstage/plugin-search +## 1.4.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/plugin-catalog-react@1.12.2-next.0 + - @backstage/frontend-plugin-api@0.6.7-next.0 + - @backstage/plugin-search-react@1.7.13-next.0 + - @backstage/core-compat-api@0.2.7-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.8 + - @backstage/plugin-search-common@1.2.12 + +## 1.4.12 + +### Patch Changes + +- 4f92394: Migrate from identityApi to fetchApi in frontend plugins. +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/core-components@0.14.8 + - @backstage/core-compat-api@0.2.6 + - @backstage/core-plugin-api@1.9.3 + - @backstage/plugin-catalog-react@1.12.1 + - @backstage/plugin-search-common@1.2.12 + - @backstage/plugin-search-react@1.7.12 + - @backstage/frontend-plugin-api@0.6.6 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.8 + +## 1.4.12-next.3 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/core-components@0.14.8-next.2 + - @backstage/plugin-catalog-react@1.12.1-next.2 + - @backstage/plugin-search-common@1.2.12-next.0 + - @backstage/plugin-search-react@1.7.12-next.2 + - @backstage/frontend-plugin-api@0.6.6-next.2 + - @backstage/core-compat-api@0.2.6-next.2 + - @backstage/core-plugin-api@1.9.3-next.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.8 + ## 1.4.12-next.2 ### Patch Changes diff --git a/plugins/search/package.json b/plugins/search/package.json index bfc4f0f103..f25bff3e26 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search", - "version": "1.4.12-next.2", + "version": "1.4.13-next.0", "description": "The Backstage plugin that provides your backstage app with search", "backstage": { "role": "frontend-plugin", diff --git a/plugins/signals-backend/CHANGELOG.md b/plugins/signals-backend/CHANGELOG.md index ecb0b6905b..1e9c57e1da 100644 --- a/plugins/signals-backend/CHANGELOG.md +++ b/plugins/signals-backend/CHANGELOG.md @@ -1,5 +1,48 @@ # @backstage/plugin-signals-backend +## 0.1.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/plugin-events-node@0.3.7-next.0 + - @backstage/plugin-signals-node@0.1.7-next.0 + - @backstage/config@1.2.0 + - @backstage/types@1.1.1 + +## 0.1.5 + +### Patch Changes + +- 78a0b08: Internal refactor to handle `BackendFeature` contract change. +- 6a576dc: Replace the usage of `getVoidLogger` with `mockServices.logger.mock` in order to remove the dependency with the soon-to-be-deprecated `backend-common` package. +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/backend-common@0.23.0 + - @backstage/backend-plugin-api@0.6.19 + - @backstage/plugin-auth-node@0.4.14 + - @backstage/plugin-events-node@0.3.5 + - @backstage/plugin-signals-node@0.1.5 + - @backstage/config@1.2.0 + - @backstage/types@1.1.1 + +## 0.1.5-next.3 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/backend-plugin-api@0.6.19-next.3 + - @backstage/plugin-auth-node@0.4.14-next.3 + - @backstage/plugin-signals-node@0.1.5-next.3 + - @backstage/plugin-events-node@0.3.5-next.2 + - @backstage/backend-common@0.23.0-next.3 + - @backstage/config@1.2.0 + - @backstage/types@1.1.1 + ## 0.1.5-next.2 ### Patch Changes diff --git a/plugins/signals-backend/api-report.md b/plugins/signals-backend/api-report.md index d59ca8e5ad..b85bbc4c03 100644 --- a/plugins/signals-backend/api-report.md +++ b/plugins/signals-backend/api-report.md @@ -4,7 +4,7 @@ ```ts import { AuthService } from '@backstage/backend-plugin-api'; -import { BackendFeature } from '@backstage/backend-plugin-api'; +import { BackendFeatureCompat } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import { EventsService } from '@backstage/plugin-events-node'; import express from 'express'; @@ -38,7 +38,7 @@ export interface RouterOptions { } // @public -const signalsPlugin: () => BackendFeature; +const signalsPlugin: BackendFeatureCompat; export default signalsPlugin; // (No @packageDocumentation comment for this package) diff --git a/plugins/signals-backend/package.json b/plugins/signals-backend/package.json index f4e4f03a8d..9501878d87 100644 --- a/plugins/signals-backend/package.json +++ b/plugins/signals-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-signals-backend", - "version": "0.1.5-next.2", + "version": "0.1.7-next.0", "backstage": { "role": "backend-plugin", "pluginId": "signals", diff --git a/plugins/signals-node/CHANGELOG.md b/plugins/signals-node/CHANGELOG.md index 1e033a75e2..28db4b57fa 100644 --- a/plugins/signals-node/CHANGELOG.md +++ b/plugins/signals-node/CHANGELOG.md @@ -1,5 +1,43 @@ # @backstage/plugin-signals-node +## 0.1.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/plugin-events-node@0.3.7-next.0 + - @backstage/config@1.2.0 + - @backstage/types@1.1.1 + +## 0.1.5 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/backend-common@0.23.0 + - @backstage/backend-plugin-api@0.6.19 + - @backstage/plugin-auth-node@0.4.14 + - @backstage/plugin-events-node@0.3.5 + - @backstage/config@1.2.0 + - @backstage/types@1.1.1 + +## 0.1.5-next.3 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/backend-plugin-api@0.6.19-next.3 + - @backstage/plugin-auth-node@0.4.14-next.3 + - @backstage/plugin-events-node@0.3.5-next.2 + - @backstage/backend-common@0.23.0-next.3 + - @backstage/config@1.2.0 + - @backstage/types@1.1.1 + ## 0.1.5-next.2 ### Patch Changes diff --git a/plugins/signals-node/package.json b/plugins/signals-node/package.json index e7eb39c9e1..8185c27d6b 100644 --- a/plugins/signals-node/package.json +++ b/plugins/signals-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-signals-node", - "version": "0.1.5-next.2", + "version": "0.1.7-next.0", "description": "Node.js library for the signals plugin", "backstage": { "role": "node-library", diff --git a/plugins/signals-react/CHANGELOG.md b/plugins/signals-react/CHANGELOG.md index b013dfeb84..7d2af3c4d6 100644 --- a/plugins/signals-react/CHANGELOG.md +++ b/plugins/signals-react/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-signals-react +## 0.0.4 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/core-plugin-api@1.9.3 + - @backstage/types@1.1.1 + +## 0.0.4-next.1 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/core-plugin-api@1.9.3-next.0 + - @backstage/types@1.1.1 + ## 0.0.4-next.0 ### Patch Changes diff --git a/plugins/signals-react/package.json b/plugins/signals-react/package.json index 37353a7d80..b970c8e5dd 100644 --- a/plugins/signals-react/package.json +++ b/plugins/signals-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-signals-react", - "version": "0.0.4-next.0", + "version": "0.0.4", "description": "Web library for the signals plugin", "backstage": { "role": "web-library", diff --git a/plugins/signals/CHANGELOG.md b/plugins/signals/CHANGELOG.md index fb60992916..f5992789c5 100644 --- a/plugins/signals/CHANGELOG.md +++ b/plugins/signals/CHANGELOG.md @@ -1,5 +1,40 @@ # @backstage/plugin-signals +## 0.0.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/theme@0.5.6 + - @backstage/types@1.1.1 + - @backstage/plugin-signals-react@0.0.4 + +## 0.0.7 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/core-components@0.14.8 + - @backstage/core-plugin-api@1.9.3 + - @backstage/theme@0.5.6 + - @backstage/plugin-signals-react@0.0.4 + - @backstage/types@1.1.1 + +## 0.0.7-next.2 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/core-components@0.14.8-next.2 + - @backstage/plugin-signals-react@0.0.4-next.1 + - @backstage/core-plugin-api@1.9.3-next.0 + - @backstage/theme@0.5.6-next.0 + - @backstage/types@1.1.1 + ## 0.0.7-next.1 ### Patch Changes diff --git a/plugins/signals/package.json b/plugins/signals/package.json index c211003927..18345295b5 100644 --- a/plugins/signals/package.json +++ b/plugins/signals/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-signals", - "version": "0.0.7-next.1", + "version": "0.0.8-next.0", "backstage": { "role": "frontend-plugin", "pluginId": "signals", diff --git a/plugins/techdocs-addons-test-utils/CHANGELOG.md b/plugins/techdocs-addons-test-utils/CHANGELOG.md index 5838a42270..93552868b9 100644 --- a/plugins/techdocs-addons-test-utils/CHANGELOG.md +++ b/plugins/techdocs-addons-test-utils/CHANGELOG.md @@ -1,5 +1,52 @@ # @backstage/plugin-techdocs-addons-test-utils +## 1.0.34-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-techdocs-react@1.2.6-next.0 + - @backstage/plugin-techdocs@1.10.7-next.0 + - @backstage/core-app-api@1.13.0-next.0 + - @backstage/plugin-catalog-react@1.12.2-next.0 + - @backstage/plugin-catalog@1.21.1-next.0 + - @backstage/integration-react@1.1.29-next.0 + - @backstage/plugin-search-react@1.7.13-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/test-utils@1.5.7-next.0 + +## 1.0.33 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/plugin-techdocs@1.10.6 + - @backstage/core-plugin-api@1.9.3 + - @backstage/plugin-techdocs-react@1.2.5 + - @backstage/plugin-catalog-react@1.12.1 + - @backstage/plugin-search-react@1.7.12 + - @backstage/plugin-catalog@1.21.0 + - @backstage/core-app-api@1.12.6 + - @backstage/integration-react@1.1.28 + - @backstage/test-utils@1.5.6 + +## 1.0.33-next.2 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/plugin-techdocs-react@1.2.5-next.2 + - @backstage/plugin-catalog-react@1.12.1-next.2 + - @backstage/plugin-search-react@1.7.12-next.2 + - @backstage/plugin-techdocs@1.10.6-next.2 + - @backstage/plugin-catalog@1.21.0-next.3 + - @backstage/integration-react@1.1.28-next.1 + - @backstage/test-utils@1.5.6-next.2 + - @backstage/core-app-api@1.12.6-next.0 + - @backstage/core-plugin-api@1.9.3-next.0 + ## 1.0.33-next.1 ### Patch Changes diff --git a/plugins/techdocs-addons-test-utils/package.json b/plugins/techdocs-addons-test-utils/package.json index b3fa6128fb..a18bfea16f 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.33-next.1", + "version": "1.0.34-next.0", "backstage": { "role": "web-library", "pluginId": "techdocs-addons", diff --git a/plugins/techdocs-backend/CHANGELOG.md b/plugins/techdocs-backend/CHANGELOG.md index f201caa389..286ea77341 100644 --- a/plugins/techdocs-backend/CHANGELOG.md +++ b/plugins/techdocs-backend/CHANGELOG.md @@ -1,5 +1,62 @@ # @backstage/plugin-techdocs-backend +## 1.10.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.1.26-next.0 + - @backstage/plugin-techdocs-node@1.12.7-next.0 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/plugin-catalog-common@1.0.24 + - @backstage/plugin-permission-common@0.7.14 + +## 1.10.6 + +### Patch Changes + +- e64bfb2: Allow defining custom build log transport for techdocs builder +- 8869b8e: Updated local development setup. +- 78a0b08: Internal refactor to handle `BackendFeature` contract change. +- 2110d76: Removed `dockerode` dependency. +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/backend-common@0.23.0 + - @backstage/backend-plugin-api@0.6.19 + - @backstage/plugin-techdocs-node@1.12.5 + - @backstage/integration@1.12.0 + - @backstage/plugin-search-backend-module-techdocs@0.1.24 + - @backstage/plugin-permission-common@0.7.14 + - @backstage/plugin-catalog-common@1.0.24 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + +## 1.10.6-next.3 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/backend-plugin-api@0.6.19-next.3 + - @backstage/integration@1.12.0-next.1 + - @backstage/plugin-search-backend-module-techdocs@0.1.24-next.3 + - @backstage/plugin-permission-common@0.7.14-next.0 + - @backstage/plugin-catalog-common@1.0.24-next.0 + - @backstage/plugin-techdocs-node@1.12.5-next.3 + - @backstage/backend-common@0.23.0-next.3 + - @backstage/catalog-client@1.6.5 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + ## 1.10.6-next.2 ### Patch Changes diff --git a/plugins/techdocs-backend/api-report-alpha.md b/plugins/techdocs-backend/api-report-alpha.md index 311dafd9a8..241c1cdbd2 100644 --- a/plugins/techdocs-backend/api-report-alpha.md +++ b/plugins/techdocs-backend/api-report-alpha.md @@ -3,10 +3,10 @@ > 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 { BackendFeatureCompat } from '@backstage/backend-plugin-api'; // @alpha -const techdocsPlugin: () => BackendFeature; +const techdocsPlugin: BackendFeatureCompat; export default techdocsPlugin; // (No @packageDocumentation comment for this package) diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index d202c35719..01891b83d4 100644 --- a/plugins/techdocs-backend/package.json +++ b/plugins/techdocs-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs-backend", - "version": "1.10.6-next.2", + "version": "1.10.8-next.0", "description": "The Backstage backend plugin that renders technical documentation for your components", "backstage": { "role": "backend-plugin", @@ -69,7 +69,6 @@ "@backstage/plugin-search-backend-module-techdocs": "workspace:^", "@backstage/plugin-techdocs-node": "workspace:^", "@types/express": "^4.17.6", - "dockerode": "^4.0.0", "express": "^4.17.1", "express-promise-router": "^4.1.0", "fs-extra": "^11.2.0", @@ -83,7 +82,6 @@ "@backstage/backend-defaults": "workspace:^", "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", - "@types/dockerode": "^3.3.0", "msw": "^1.0.0", "supertest": "^6.1.3" }, diff --git a/plugins/techdocs-backend/src/plugin.ts b/plugins/techdocs-backend/src/plugin.ts index 094335a0f0..e3a0c60a15 100644 --- a/plugins/techdocs-backend/src/plugin.ts +++ b/plugins/techdocs-backend/src/plugin.ts @@ -16,7 +16,6 @@ import { cacheToPluginCacheManager, - DockerContainerRunner, loggerToWinstonLogger, } from '@backstage/backend-common'; import { @@ -36,7 +35,6 @@ import { techdocsGeneratorExtensionPoint, techdocsPreparerExtensionPoint, } from '@backstage/plugin-techdocs-node'; -import Docker from 'dockerode'; import { createRouter } from '@backstage/plugin-techdocs-backend'; import * as winston from 'winston'; @@ -118,14 +116,9 @@ export const techdocsPlugin = createBackendPlugin({ preparers.register(protocol, preparer); } - // Docker client (conditionally) used by the generators, based on techdocs.generators config. - const dockerClient = new Docker(); - const containerRunner = new DockerContainerRunner({ dockerClient }); - // Generators are used for generating documentation sites. const generators = await Generators.fromConfig(config, { logger: winstonLogger, - containerRunner, customGenerator: customTechdocsGenerator, }); diff --git a/plugins/techdocs-module-addons-contrib/CHANGELOG.md b/plugins/techdocs-module-addons-contrib/CHANGELOG.md index 72efbff1af..da76210708 100644 --- a/plugins/techdocs-module-addons-contrib/CHANGELOG.md +++ b/plugins/techdocs-module-addons-contrib/CHANGELOG.md @@ -1,5 +1,40 @@ # @backstage/plugin-techdocs-module-addons-contrib +## 1.1.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-techdocs-react@1.2.6-next.0 + - @backstage/core-components@0.14.9-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/integration-react@1.1.29-next.0 + - @backstage/core-plugin-api@1.9.3 + +## 1.1.11 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/core-components@0.14.8 + - @backstage/integration@1.12.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/plugin-techdocs-react@1.2.5 + - @backstage/integration-react@1.1.28 + +## 1.1.11-next.2 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/core-components@0.14.8-next.2 + - @backstage/integration@1.12.0-next.1 + - @backstage/plugin-techdocs-react@1.2.5-next.2 + - @backstage/integration-react@1.1.28-next.1 + - @backstage/core-plugin-api@1.9.3-next.0 + ## 1.1.11-next.1 ### Patch Changes diff --git a/plugins/techdocs-module-addons-contrib/package.json b/plugins/techdocs-module-addons-contrib/package.json index 7836dc3e05..f0b2301dfb 100644 --- a/plugins/techdocs-module-addons-contrib/package.json +++ b/plugins/techdocs-module-addons-contrib/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs-module-addons-contrib", - "version": "1.1.11-next.1", + "version": "1.1.12-next.0", "description": "Plugin module for contributed TechDocs Addons", "backstage": { "role": "frontend-plugin-module", diff --git a/plugins/techdocs-node/CHANGELOG.md b/plugins/techdocs-node/CHANGELOG.md index 5242fa8ec6..0093f6a1eb 100644 --- a/plugins/techdocs-node/CHANGELOG.md +++ b/plugins/techdocs-node/CHANGELOG.md @@ -1,5 +1,52 @@ # @backstage/plugin-techdocs-node +## 1.12.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/integration-aws-node@0.1.12 + - @backstage/plugin-search-common@1.2.12 + +## 1.12.5 + +### Patch Changes + +- e64bfb2: Allow defining custom build log transport for techdocs builder +- 48c38f0: `TechdocsGenerator` won't require a `containerRunner` option anymore for generating TechDocs in docker. +- d44a20a: Added additional plugin metadata to `package.json`. +- 5db7536: Updated `getRepoUrlFromLocationAnnotation` to check for Harness SCM integration +- Updated dependencies + - @backstage/backend-common@0.23.0 + - @backstage/backend-plugin-api@0.6.19 + - @backstage/integration@1.12.0 + - @backstage/plugin-search-common@1.2.12 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/integration-aws-node@0.1.12 + +## 1.12.5-next.3 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/backend-plugin-api@0.6.19-next.3 + - @backstage/integration@1.12.0-next.1 + - @backstage/plugin-search-common@1.2.12-next.0 + - @backstage/backend-common@0.23.0-next.3 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/integration-aws-node@0.1.12 + ## 1.12.5-next.2 ### Patch Changes diff --git a/plugins/techdocs-node/api-report.md b/plugins/techdocs-node/api-report.md index 2d3ca90983..3966b7d2d8 100644 --- a/plugins/techdocs-node/api-report.md +++ b/plugins/techdocs-node/api-report.md @@ -48,8 +48,8 @@ export type GeneratorBuilder = { // @public export type GeneratorOptions = { - containerRunner?: ContainerRunner; logger: Logger; + containerRunner?: ContainerRunner; }; // @public @@ -72,7 +72,7 @@ export class Generators implements GeneratorBuilder { config: Config, options: { logger: Logger; - containerRunner: ContainerRunner; + containerRunner?: ContainerRunner; customGenerator?: TechdocsGenerator; }, ): Promise; diff --git a/plugins/techdocs-node/package.json b/plugins/techdocs-node/package.json index fdedeb679d..ae11fcb1df 100644 --- a/plugins/techdocs-node/package.json +++ b/plugins/techdocs-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs-node", - "version": "1.12.5-next.2", + "version": "1.12.7-next.0", "description": "Common node.js functionalities for TechDocs, to be shared between techdocs-backend plugin and techdocs-cli", "backstage": { "role": "node-library", @@ -64,6 +64,7 @@ "@smithy/node-http-handler": "^2.1.7", "@trendyol-js/openstack-swift-sdk": "^0.0.7", "@types/express": "^4.17.6", + "dockerode": "^4.0.0", "express": "^4.17.1", "fs-extra": "^11.2.0", "git-url-parse": "^14.0.0", diff --git a/plugins/techdocs-node/src/stages/generate/DockerContainerRunner.test.ts b/plugins/techdocs-node/src/stages/generate/DockerContainerRunner.test.ts new file mode 100644 index 0000000000..4a9e364af3 --- /dev/null +++ b/plugins/techdocs-node/src/stages/generate/DockerContainerRunner.test.ts @@ -0,0 +1,218 @@ +/* + * 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 fs from 'fs-extra'; +import Stream, { PassThrough } from 'stream'; +import { DockerContainerRunner, UserOptions } from './DockerContainerRunner'; +import { createMockDirectory } from '@backstage/backend-test-utils'; + +const mockPull = jest.fn(); +const mockRun = jest.fn(); +const mockPing = jest.fn(); + +jest.mock( + 'dockerode', + () => + function MockDocker() { + return { + pull: mockPull, + run: mockRun, + ping: mockPing, + }; + }, +); + +describe('DockerContainerRunner', () => { + let containerTaskApi: DockerContainerRunner; + + const inputDir = createMockDirectory(); + const outputDir = createMockDirectory(); + + beforeEach(() => { + inputDir.clear(); + outputDir.clear(); + + mockPull.mockImplementation( + ( + _repoTag: string, + _options: {}, + callback: (error?: any, result?: any) => void, + ) => { + const mockStream = new PassThrough(); + callback(undefined, mockStream); + mockStream.end(); + }, + ); + mockRun.mockResolvedValue([{ Error: null, StatusCode: 0 }]); + mockPing.mockResolvedValue(Buffer.from('OK', 'utf-8')); + + containerTaskApi = new DockerContainerRunner(); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + const imageName = 'dockerorg/image'; + const args = ['bash', '-c', 'echo test']; + const mountDirs = { + [inputDir.path]: '/input', + [outputDir.path]: '/output', + }; + const workingDir = inputDir.path; + const envVars = { HOME: '/tmp', LOG_LEVEL: 'debug' }; + const envVarsArray = ['HOME=/tmp', 'LOG_LEVEL=debug']; + + it('should pull the docker container', async () => { + await containerTaskApi.runContainer({ + imageName, + args, + }); + + expect(mockPull).toHaveBeenCalledWith(imageName, {}, expect.any(Function)); + + expect(mockRun).toHaveBeenCalled(); + }); + + it('should not pull the docker container when pullImage is false', async () => { + await containerTaskApi.runContainer({ + imageName, + args, + pullImage: false, + }); + + expect(mockPull).not.toHaveBeenCalled(); + expect(mockRun).toHaveBeenCalled(); + }); + + it('should call the dockerClient run command with the correct arguments passed through', async () => { + await containerTaskApi.runContainer({ + imageName, + args, + mountDirs, + envVars, + workingDir, + }); + + expect(mockRun).toHaveBeenCalledWith( + imageName, + args, + expect.any(Stream), + expect.objectContaining({ + Env: envVarsArray, + WorkingDir: workingDir, + HostConfig: { + AutoRemove: true, + Binds: expect.arrayContaining([ + `${await fs.realpath(inputDir.path)}:/input`, + `${await fs.realpath(outputDir.path)}:/output`, + ]), + }, + Volumes: { + '/input': {}, + '/output': {}, + }, + }), + ); + }); + + it('should ping docker to test availability', async () => { + await containerTaskApi.runContainer({ + imageName, + args, + }); + + expect(mockPing).toHaveBeenCalled(); + }); + + it('should pass through the user and group id from the host machine and set the home dir', async () => { + await containerTaskApi.runContainer({ + imageName, + args, + }); + + const userOptions: UserOptions = {}; + if (process.getuid && process.getgid) { + userOptions.User = `${process.getuid()}:${process.getgid()}`; + } + + expect(mockRun).toHaveBeenCalledWith( + imageName, + args, + expect.any(Stream), + expect.objectContaining({ + ...userOptions, + }), + ); + }); + + it('throws a correct error if the command fails in docker', async () => { + mockRun.mockResolvedValueOnce([ + { + Error: new Error('Something went wrong with docker'), + StatusCode: 0, + }, + ]); + + await expect( + containerTaskApi.runContainer({ + imageName, + args, + }), + ).rejects.toThrow(/Something went wrong with docker/); + }); + + describe('where docker is unavailable', () => { + const dockerError = 'a docker error'; + + beforeEach(() => { + mockPing.mockImplementationOnce(() => { + throw new Error(dockerError); + }); + }); + + it('should throw with a descriptive error message including the docker error message', async () => { + await expect( + containerTaskApi.runContainer({ + imageName, + args, + }), + ).rejects.toThrow(new RegExp(`.+: ${dockerError}`)); + }); + }); + + it('should pass through the log stream to the docker client', async () => { + const logStream = new PassThrough(); + await containerTaskApi.runContainer({ + imageName, + args, + logStream, + }); + + expect(mockRun).toHaveBeenCalledWith( + imageName, + args, + logStream, + expect.objectContaining({ + HostConfig: { + AutoRemove: true, + Binds: [], + }, + Volumes: {}, + }), + ); + }); +}); diff --git a/plugins/techdocs-node/src/stages/generate/DockerContainerRunner.ts b/plugins/techdocs-node/src/stages/generate/DockerContainerRunner.ts new file mode 100644 index 0000000000..b7cb7f1c86 --- /dev/null +++ b/plugins/techdocs-node/src/stages/generate/DockerContainerRunner.ts @@ -0,0 +1,145 @@ +/* + * 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 Docker from 'dockerode'; +import fs from 'fs-extra'; +import { ForwardedError } from '@backstage/errors'; +import { PassThrough } from 'stream'; +import { pipeline as pipelineStream } from 'stream'; +import { promisify } from 'util'; +import { Writable } from 'stream'; + +const pipeline = promisify(pipelineStream); + +export type UserOptions = { + User?: string; +}; + +/** + * @internal + */ +export class DockerContainerRunner { + private readonly dockerClient: Docker; + + constructor() { + this.dockerClient = new Docker(); + } + + async runContainer(options: { + imageName: string; + command?: string | string[]; + args: string[]; + logStream?: Writable; + mountDirs?: Record; + workingDir?: string; + envVars?: Record; + pullImage?: boolean; + defaultUser?: boolean; + }) { + const { + imageName, + command, + args, + logStream = new PassThrough(), + mountDirs = {}, + workingDir, + envVars = {}, + pullImage = true, + defaultUser = false, + } = options; + + // Show a better error message when Docker is unavailable. + try { + await this.dockerClient.ping(); + } catch (e) { + throw new ForwardedError( + 'This operation requires Docker. Docker does not appear to be available. Docker.ping() failed with', + e, + ); + } + + if (pullImage) { + await new Promise((resolve, reject) => { + this.dockerClient.pull(imageName, {}, (err, stream) => { + if (err) { + reject(err); + return; + } + + pipeline(stream, logStream, { end: false }) + .then(resolve) + .catch(reject); + }); + }); + } + + const userOptions: UserOptions = {}; + if (!defaultUser && process.getuid && process.getgid) { + // Files that are created inside the Docker container will be owned by + // root on the host system on non Mac systems, because of reasons. Mainly the fact that + // volume sharing is done using NFS on Mac and actual mounts in Linux world. + // So we set the user in the container as the same user and group id as the host. + // On Windows we don't have process.getuid nor process.getgid + userOptions.User = `${process.getuid()}:${process.getgid()}`; + } + + // Initialize volumes to mount based on mountDirs map + const Volumes: { [T: string]: object } = {}; + for (const containerDir of Object.values(mountDirs)) { + Volumes[containerDir] = {}; + } + + // Create bind volumes + const Binds: string[] = []; + for (const [hostDir, containerDir] of Object.entries(mountDirs)) { + // Need to use realpath here as Docker mounting does not like + // symlinks for binding volumes + const realHostDir = await fs.realpath(hostDir); + Binds.push(`${realHostDir}:${containerDir}`); + } + + // Create docker environment variables array + const Env = []; + for (const [key, value] of Object.entries(envVars)) { + Env.push(`${key}=${value}`); + } + + const [{ Error: error, StatusCode: statusCode }] = + await this.dockerClient.run(imageName, args, logStream, { + Volumes, + HostConfig: { + AutoRemove: true, + Binds, + }, + ...(workingDir ? { WorkingDir: workingDir } : {}), + Entrypoint: command, + Env, + ...userOptions, + } as Docker.ContainerCreateOptions); + + if (error) { + throw new Error( + `Docker failed to run with the following error message: ${error}`, + ); + } + + if (statusCode !== 0) { + throw new Error( + `Docker container returned a non-zero exit code (${statusCode})`, + ); + } + } +} diff --git a/plugins/techdocs-node/src/stages/generate/generators.test.ts b/plugins/techdocs-node/src/stages/generate/generators.test.ts index 3e0571af54..f80f070796 100644 --- a/plugins/techdocs-node/src/stages/generate/generators.test.ts +++ b/plugins/techdocs-node/src/stages/generate/generators.test.ts @@ -14,10 +14,7 @@ * limitations under the License. */ -import { - ContainerRunner, - loggerToWinstonLogger, -} from '@backstage/backend-common'; +import { loggerToWinstonLogger } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { Generators } from './generators'; import { TechdocsGenerator } from './techdocs'; @@ -34,10 +31,6 @@ const mockEntity = { }; describe('generators', () => { - const containerRunner: jest.Mocked = { - runContainer: jest.fn(), - }; - it('should return error if no generator is registered', async () => { const generators = new Generators(); @@ -50,7 +43,6 @@ describe('generators', () => { const generators = new Generators(); const techdocs = TechdocsGenerator.fromConfig(new ConfigReader({}), { logger, - containerRunner, }); generators.register('techdocs', techdocs); diff --git a/plugins/techdocs-node/src/stages/generate/generators.ts b/plugins/techdocs-node/src/stages/generate/generators.ts index 603c714370..0c20ac1588 100644 --- a/plugins/techdocs-node/src/stages/generate/generators.ts +++ b/plugins/techdocs-node/src/stages/generate/generators.ts @@ -42,7 +42,7 @@ export class Generators implements GeneratorBuilder { config: Config, options: { logger: Logger; - containerRunner: ContainerRunner; + containerRunner?: ContainerRunner; customGenerator?: TechdocsGenerator; }, ): Promise { diff --git a/plugins/techdocs-node/src/stages/generate/helpers.ts b/plugins/techdocs-node/src/stages/generate/helpers.ts index df1a31470d..5efe96877f 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.ts @@ -101,11 +101,13 @@ export const getRepoUrlFromLocationAnnotation = ( if (locationType === 'url') { const integration = scmIntegrations.byUrl(target); - // We only support it for github, gitlab and bitbucketServer for now as the edit_uri + // We only support it for github, gitlab, bitbucketServer and harness for now as the edit_uri // is not properly supported for others yet. if ( integration && - ['github', 'gitlab', 'bitbucketServer'].includes(integration.type) + ['github', 'gitlab', 'bitbucketServer', 'harness'].includes( + integration.type, + ) ) { // handle the case where a user manually writes url:https://github.com/backstage/backstage i.e. without /blob/... const { filepathtype } = gitUrlParse(target); diff --git a/plugins/techdocs-node/src/stages/generate/techdocs.ts b/plugins/techdocs-node/src/stages/generate/techdocs.ts index c5130a3f8f..e5e2b7191e 100644 --- a/plugins/techdocs-node/src/stages/generate/techdocs.ts +++ b/plugins/techdocs-node/src/stages/generate/techdocs.ts @@ -14,7 +14,6 @@ * limitations under the License. */ -import { ContainerRunner } from '@backstage/backend-common'; import { Config } from '@backstage/config'; import path from 'path'; import { Logger } from 'winston'; @@ -43,6 +42,8 @@ import { GeneratorRunOptions, } from './types'; import { ForwardedError } from '@backstage/errors'; +import { DockerContainerRunner } from './DockerContainerRunner'; +import { ContainerRunner } from '@backstage/backend-common'; /** * Generates documentation files @@ -155,13 +156,10 @@ export class TechdocsGenerator implements GeneratorBase { `Successfully generated docs from ${inputDir} into ${outputDir} using local mkdocs`, ); break; - case 'docker': - if (this.containerRunner === undefined) { - throw new Error( - "Invalid state: containerRunner cannot be undefined when runIn is 'docker'", - ); - } - await this.containerRunner.runContainer({ + case 'docker': { + const containerRunner = + this.containerRunner || new DockerContainerRunner(); + await containerRunner.runContainer({ imageName: this.options.dockerImage ?? TechdocsGenerator.defaultDockerImage, args: ['build', '-d', '/output'], @@ -178,6 +176,7 @@ export class TechdocsGenerator implements GeneratorBase { `Successfully generated docs from ${inputDir} into ${outputDir} using techdocs-container`, ); break; + } default: throw new Error( `Invalid config value "${this.options.runIn}" provided in 'techdocs.generators.techdocs'.`, diff --git a/plugins/techdocs-node/src/stages/generate/types.ts b/plugins/techdocs-node/src/stages/generate/types.ts index 149c3c2195..ca816d560f 100644 --- a/plugins/techdocs-node/src/stages/generate/types.ts +++ b/plugins/techdocs-node/src/stages/generate/types.ts @@ -14,11 +14,11 @@ * limitations under the License. */ -import { ContainerRunner } from '@backstage/backend-common'; import { Entity } from '@backstage/catalog-model'; import { Writable } from 'stream'; import { Logger } from 'winston'; import { ParsedLocationAnnotation } from '../../helpers'; +import { ContainerRunner } from '@backstage/backend-common'; // Determines where the generator will be run export type GeneratorRunInType = 'docker' | 'local'; @@ -28,8 +28,12 @@ export type GeneratorRunInType = 'docker' | 'local'; * @public */ export type GeneratorOptions = { - containerRunner?: ContainerRunner; logger: Logger; + /** + * @deprecated containerRunner is now instantiated in + * the generator and this option will be removed in the future + */ + containerRunner?: ContainerRunner; }; /** diff --git a/plugins/techdocs-react/CHANGELOG.md b/plugins/techdocs-react/CHANGELOG.md index 569a1cb49b..d07ed27eb0 100644 --- a/plugins/techdocs-react/CHANGELOG.md +++ b/plugins/techdocs-react/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-techdocs-react +## 1.2.6-next.0 + +### Patch Changes + +- 8ac9ce5: Fixed a bug with the TechDocsReaderPageProvider not re-rendering when setShadowDom is called, meaning that the useShadowDom hooks were inconsistent. This issue caused the TextSize addon changes not to reapply during navigation. +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/version-bridge@1.0.8 + +## 1.2.5 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/core-components@0.14.8 + - @backstage/core-plugin-api@1.9.3 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/version-bridge@1.0.8 + +## 1.2.5-next.2 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/core-components@0.14.8-next.2 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/core-plugin-api@1.9.3-next.0 + - @backstage/version-bridge@1.0.8 + ## 1.2.5-next.1 ### Patch Changes diff --git a/plugins/techdocs-react/api-report.md b/plugins/techdocs-react/api-report.md index c158bbd81e..7d787c4da6 100644 --- a/plugins/techdocs-react/api-report.md +++ b/plugins/techdocs-react/api-report.md @@ -116,6 +116,8 @@ export type TechDocsReaderPageValue = { entityMetadata: AsyncState; shadowRoot?: ShadowRoot; setShadowRoot: Dispatch>; + shadowRootVersion: number; + incShadowRootVersion: () => void; title: string; setTitle: Dispatch>; subtitle: string; diff --git a/plugins/techdocs-react/package.json b/plugins/techdocs-react/package.json index 601eeea739..d002db68d1 100644 --- a/plugins/techdocs-react/package.json +++ b/plugins/techdocs-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs-react", - "version": "1.2.5-next.1", + "version": "1.2.6-next.0", "description": "Shared frontend utilities for TechDocs and Addons", "backstage": { "role": "web-library", diff --git a/plugins/techdocs-react/src/context.tsx b/plugins/techdocs-react/src/context.tsx index 43fdada98e..2e7cd9586d 100644 --- a/plugins/techdocs-react/src/context.tsx +++ b/plugins/techdocs-react/src/context.tsx @@ -25,6 +25,7 @@ import React, { } from 'react'; import useAsync, { AsyncState } from 'react-use/esm/useAsync'; import useAsyncRetry from 'react-use/esm/useAsyncRetry'; +import useCounter from 'react-use/esm/useCounter'; import { CompoundEntityRef, @@ -64,6 +65,8 @@ export type TechDocsReaderPageValue = { entityMetadata: AsyncState; shadowRoot?: ShadowRoot; setShadowRoot: Dispatch>; + shadowRootVersion: number; + incShadowRootVersion: () => void; title: string; setTitle: Dispatch>; subtitle: string; @@ -80,6 +83,8 @@ const defaultTechDocsReaderPageValue: TechDocsReaderPageValue = { setTitle: () => {}, setSubtitle: () => {}, setShadowRoot: () => {}, + shadowRootVersion: 0, + incShadowRootVersion: () => {}, metadata: { loading: true }, entityMetadata: { loading: true }, entityRef: { kind: '', name: '', namespace: '' }, @@ -134,6 +139,7 @@ export const TechDocsReaderPageProvider = memo( const [shadowRoot, setShadowRoot] = useState( defaultTechDocsReaderPageValue.shadowRoot, ); + const [shadowRootVersion, { inc: incShadowRootVersion }] = useCounter(0); useEffect(() => { if (shadowRoot && !metadata.value && !metadata.loading) { @@ -153,6 +159,8 @@ export const TechDocsReaderPageProvider = memo( entityMetadata, shadowRoot, setShadowRoot, + shadowRootVersion, + incShadowRootVersion, title, setTitle, subtitle, @@ -190,6 +198,5 @@ export const useTechDocsReaderPage = () => { if (context === undefined) { throw new Error('No context found for version 1.'); } - return context; }; diff --git a/plugins/techdocs/CHANGELOG.md b/plugins/techdocs/CHANGELOG.md index 2c7ad7fec8..fd35205da8 100644 --- a/plugins/techdocs/CHANGELOG.md +++ b/plugins/techdocs/CHANGELOG.md @@ -1,5 +1,76 @@ # @backstage/plugin-techdocs +## 1.10.7-next.0 + +### Patch Changes + +- 8ac9ce5: Fixed a bug with the TechDocsReaderPageProvider not re-rendering when setShadowDom is called, meaning that the useShadowDom hooks were inconsistent. This issue caused the TextSize addon changes not to reapply during navigation. +- Updated dependencies + - @backstage/plugin-techdocs-react@1.2.6-next.0 + - @backstage/core-components@0.14.9-next.0 + - @backstage/integration@1.13.0-next.0 + - @backstage/plugin-catalog-react@1.12.2-next.0 + - @backstage/frontend-plugin-api@0.6.7-next.0 + - @backstage/integration-react@1.1.29-next.0 + - @backstage/plugin-auth-react@0.1.4-next.0 + - @backstage/plugin-search-react@1.7.13-next.0 + - @backstage/core-compat-api@0.2.7-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/theme@0.5.6 + - @backstage/plugin-search-common@1.2.12 + +## 1.10.6 + +### Patch Changes + +- 654af4a: mkdocs-material have updated their CSS variable template, and a few are unset in Backstage. This patch adds the missing variables to ensure coverage. +- cbebad1: Internal updates to allow reusing Backstage's `fetchApi` implementation for event source requests. This allows you to for example, override the `Authorization` header. +- 96cd13e: `TechDocsIndexPage` now accepts an optional `ownerPickerMode` for toggling the behavior of the `EntityOwnerPicker`, exposing a new mode `` particularly suitable for larger catalogs. In this new mode, `EntityOwnerPicker` will display all the users and groups present in the catalog. +- e40bd9a: Fixed bug in `CopyToClipboardButton` component where positioning of the "Copy to clipboard" button in techdocs code snippets was broken in some cases. +- d44a20a: Added additional plugin metadata to `package.json`. +- 1256d88: Fixed an issue preventing the `TechDocsSearchBar` component from opening when clicking on the arrow icon. +- Updated dependencies + - @backstage/core-components@0.14.8 + - @backstage/core-compat-api@0.2.6 + - @backstage/integration@1.12.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/theme@0.5.6 + - @backstage/plugin-techdocs-react@1.2.5 + - @backstage/plugin-catalog-react@1.12.1 + - @backstage/plugin-search-common@1.2.12 + - @backstage/plugin-search-react@1.7.12 + - @backstage/plugin-auth-react@0.1.3 + - @backstage/integration-react@1.1.28 + - @backstage/frontend-plugin-api@0.6.6 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + +## 1.10.6-next.2 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- Updated dependencies + - @backstage/core-components@0.14.8-next.2 + - @backstage/integration@1.12.0-next.1 + - @backstage/plugin-techdocs-react@1.2.5-next.2 + - @backstage/plugin-catalog-react@1.12.1-next.2 + - @backstage/plugin-search-common@1.2.12-next.0 + - @backstage/plugin-search-react@1.7.12-next.2 + - @backstage/plugin-auth-react@0.1.3-next.2 + - @backstage/integration-react@1.1.28-next.1 + - @backstage/frontend-plugin-api@0.6.6-next.2 + - @backstage/core-compat-api@0.2.6-next.2 + - @backstage/catalog-model@1.5.0 + - @backstage/config@1.2.0 + - @backstage/core-plugin-api@1.9.3-next.0 + - @backstage/errors@1.2.4 + - @backstage/theme@0.5.6-next.0 + ## 1.10.6-next.1 ### Patch Changes diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 84c9df25a6..8212246aab 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs", - "version": "1.10.6-next.1", + "version": "1.10.7-next.0", "description": "The Backstage plugin that renders technical documentation for your components", "backstage": { "role": "frontend-plugin", diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx index 3692ed22d3..00df73cab3 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx @@ -80,6 +80,7 @@ export const TechDocsReaderPageContent = withTechDocsReaderProvider( entityMetadata: { value: entityMetadata, loading: entityMetadataLoading }, entityRef, setShadowRoot, + incShadowRootVersion, } = useTechDocsReaderPage(); const dom = useTechDocsReaderDom(entityRef); const path = window.location.pathname; @@ -102,11 +103,12 @@ export const TechDocsReaderPageContent = withTechDocsReaderProvider( const handleAppend = useCallback( (newShadowRoot: ShadowRoot) => { setShadowRoot(newShadowRoot); + incShadowRootVersion(); if (onReady instanceof Function) { onReady(); } }, - [setShadowRoot, onReady], + [setShadowRoot, incShadowRootVersion, onReady], ); // No entity metadata = 404. Don't render content at all. diff --git a/plugins/user-settings-backend/CHANGELOG.md b/plugins/user-settings-backend/CHANGELOG.md index 0e7600d0e3..cbd2ab7536 100644 --- a/plugins/user-settings-backend/CHANGELOG.md +++ b/plugins/user-settings-backend/CHANGELOG.md @@ -1,5 +1,53 @@ # @backstage/plugin-user-settings-backend +## 0.2.20-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.21-next.0 + - @backstage/backend-common@0.23.2-next.0 + - @backstage/plugin-auth-node@0.4.16-next.0 + - @backstage/plugin-signals-node@0.1.7-next.0 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + - @backstage/plugin-user-settings-common@0.0.1 + +## 0.2.18 + +### Patch Changes + +- 8869b8e: Updated local development setup. +- 78a0b08: Internal refactor to handle `BackendFeature` contract change. +- d44a20a: Added additional plugin metadata to `package.json`. +- e6ec179: Use signals to update user settings across sessions +- Updated dependencies + - @backstage/backend-common@0.23.0 + - @backstage/backend-plugin-api@0.6.19 + - @backstage/plugin-auth-node@0.4.14 + - @backstage/plugin-user-settings-common@0.0.1 + - @backstage/plugin-signals-node@0.1.5 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + +## 0.2.18-next.3 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- e6ec179: Use signals to update user settings across sessions +- Updated dependencies + - @backstage/backend-plugin-api@0.6.19-next.3 + - @backstage/plugin-auth-node@0.4.14-next.3 + - @backstage/plugin-user-settings-common@0.0.1-next.0 + - @backstage/plugin-signals-node@0.1.5-next.3 + - @backstage/backend-common@0.23.0-next.3 + - @backstage/config@1.2.0 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + ## 0.2.18-next.2 ### Patch Changes diff --git a/plugins/user-settings-backend/api-report-alpha.md b/plugins/user-settings-backend/api-report-alpha.md index aa6b246616..d4b15a5717 100644 --- a/plugins/user-settings-backend/api-report-alpha.md +++ b/plugins/user-settings-backend/api-report-alpha.md @@ -3,10 +3,10 @@ > 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 { BackendFeatureCompat } from '@backstage/backend-plugin-api'; // @alpha -const _default: () => BackendFeature; +const _default: BackendFeatureCompat; export default _default; // (No @packageDocumentation comment for this package) diff --git a/plugins/user-settings-backend/package.json b/plugins/user-settings-backend/package.json index ce15f2b6c3..d8dc0770a5 100644 --- a/plugins/user-settings-backend/package.json +++ b/plugins/user-settings-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-user-settings-backend", - "version": "0.2.18-next.2", + "version": "0.2.20-next.0", "description": "The Backstage backend plugin to manage user settings", "backstage": { "role": "backend-plugin", diff --git a/plugins/user-settings-common/CHANGELOG.md b/plugins/user-settings-common/CHANGELOG.md new file mode 100644 index 0000000000..652a308252 --- /dev/null +++ b/plugins/user-settings-common/CHANGELOG.md @@ -0,0 +1,15 @@ +# @backstage/plugin-user-settings-common + +## 0.0.1 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- e6ec179: Use signals to update user settings across sessions + +## 0.0.1-next.0 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- e6ec179: Use signals to update user settings across sessions diff --git a/plugins/user-settings-common/package.json b/plugins/user-settings-common/package.json index d36029092b..82c5db84f1 100644 --- a/plugins/user-settings-common/package.json +++ b/plugins/user-settings-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-user-settings-common", - "version": "0.0.0", + "version": "0.0.1", "description": "Common functionalities for the user-settings plugin", "backstage": { "role": "common-library", diff --git a/plugins/user-settings/CHANGELOG.md b/plugins/user-settings/CHANGELOG.md index 859f4636dc..20ef229a2d 100644 --- a/plugins/user-settings/CHANGELOG.md +++ b/plugins/user-settings/CHANGELOG.md @@ -1,5 +1,60 @@ # @backstage/plugin-user-settings +## 0.8.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.9-next.0 + - @backstage/core-app-api@1.13.0-next.0 + - @backstage/plugin-catalog-react@1.12.2-next.0 + - @backstage/frontend-plugin-api@0.6.7-next.0 + - @backstage/core-compat-api@0.2.7-next.0 + - @backstage/core-plugin-api@1.9.3 + - @backstage/errors@1.2.4 + - @backstage/theme@0.5.6 + - @backstage/types@1.1.1 + - @backstage/plugin-signals-react@0.0.4 + - @backstage/plugin-user-settings-common@0.0.1 + +## 0.8.7 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- e6ec179: Use signals to update user settings across sessions +- Updated dependencies + - @backstage/core-components@0.14.8 + - @backstage/core-compat-api@0.2.6 + - @backstage/core-plugin-api@1.9.3 + - @backstage/theme@0.5.6 + - @backstage/plugin-user-settings-common@0.0.1 + - @backstage/plugin-catalog-react@1.12.1 + - @backstage/plugin-signals-react@0.0.4 + - @backstage/core-app-api@1.12.6 + - @backstage/frontend-plugin-api@0.6.6 + - @backstage/errors@1.2.4 + - @backstage/types@1.1.1 + +## 0.8.7-next.2 + +### Patch Changes + +- d44a20a: Added additional plugin metadata to `package.json`. +- e6ec179: Use signals to update user settings across sessions +- Updated dependencies + - @backstage/core-components@0.14.8-next.2 + - @backstage/plugin-user-settings-common@0.0.1-next.0 + - @backstage/plugin-catalog-react@1.12.1-next.2 + - @backstage/plugin-signals-react@0.0.4-next.1 + - @backstage/frontend-plugin-api@0.6.6-next.2 + - @backstage/core-compat-api@0.2.6-next.2 + - @backstage/core-app-api@1.12.6-next.0 + - @backstage/core-plugin-api@1.9.3-next.0 + - @backstage/errors@1.2.4 + - @backstage/theme@0.5.6-next.0 + - @backstage/types@1.1.1 + ## 0.8.7-next.1 ### Patch Changes diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index 7546b8ca64..3257de8072 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-user-settings", - "version": "0.8.7-next.1", + "version": "0.8.8-next.0", "description": "A Backstage plugin that provides a settings page", "backstage": { "role": "frontend-plugin", diff --git a/scripts/patch-release-for-pr.js b/scripts/patch-release-for-pr.js index 04bfe4284e..d70eaa8ac5 100755 --- a/scripts/patch-release-for-pr.js +++ b/scripts/patch-release-for-pr.js @@ -149,6 +149,9 @@ async function main(args) { ); } + console.log('Running "yarn install" ...'); + await run('yarn', 'install'); + console.log('Running "yarn release" ...'); await run('yarn', 'release'); diff --git a/storybook/yarn.lock b/storybook/yarn.lock index 14a0fc7ee9..1702d6f4cc 100644 --- a/storybook/yarn.lock +++ b/storybook/yarn.lock @@ -2842,94 +2842,94 @@ __metadata: languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.5.0": - version: 1.5.0 - resolution: "@swc/core-darwin-arm64@npm:1.5.0" +"@swc/core-darwin-arm64@npm:1.5.29": + version: 1.5.29 + resolution: "@swc/core-darwin-arm64@npm:1.5.29" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.5.0": - version: 1.5.0 - resolution: "@swc/core-darwin-x64@npm:1.5.0" +"@swc/core-darwin-x64@npm:1.5.29": + version: 1.5.29 + resolution: "@swc/core-darwin-x64@npm:1.5.29" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.5.0": - version: 1.5.0 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.5.0" +"@swc/core-linux-arm-gnueabihf@npm:1.5.29": + version: 1.5.29 + resolution: "@swc/core-linux-arm-gnueabihf@npm:1.5.29" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@swc/core-linux-arm64-gnu@npm:1.5.0": - version: 1.5.0 - resolution: "@swc/core-linux-arm64-gnu@npm:1.5.0" +"@swc/core-linux-arm64-gnu@npm:1.5.29": + version: 1.5.29 + resolution: "@swc/core-linux-arm64-gnu@npm:1.5.29" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.5.0": - version: 1.5.0 - resolution: "@swc/core-linux-arm64-musl@npm:1.5.0" +"@swc/core-linux-arm64-musl@npm:1.5.29": + version: 1.5.29 + resolution: "@swc/core-linux-arm64-musl@npm:1.5.29" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.5.0": - version: 1.5.0 - resolution: "@swc/core-linux-x64-gnu@npm:1.5.0" +"@swc/core-linux-x64-gnu@npm:1.5.29": + version: 1.5.29 + resolution: "@swc/core-linux-x64-gnu@npm:1.5.29" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.5.0": - version: 1.5.0 - resolution: "@swc/core-linux-x64-musl@npm:1.5.0" +"@swc/core-linux-x64-musl@npm:1.5.29": + version: 1.5.29 + resolution: "@swc/core-linux-x64-musl@npm:1.5.29" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.5.0": - version: 1.5.0 - resolution: "@swc/core-win32-arm64-msvc@npm:1.5.0" +"@swc/core-win32-arm64-msvc@npm:1.5.29": + version: 1.5.29 + resolution: "@swc/core-win32-arm64-msvc@npm:1.5.29" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.5.0": - version: 1.5.0 - resolution: "@swc/core-win32-ia32-msvc@npm:1.5.0" +"@swc/core-win32-ia32-msvc@npm:1.5.29": + version: 1.5.29 + resolution: "@swc/core-win32-ia32-msvc@npm:1.5.29" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.5.0": - version: 1.5.0 - resolution: "@swc/core-win32-x64-msvc@npm:1.5.0" +"@swc/core-win32-x64-msvc@npm:1.5.29": + version: 1.5.29 + resolution: "@swc/core-win32-x64-msvc@npm:1.5.29" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "@swc/core@npm:^1.3.46": - version: 1.5.0 - resolution: "@swc/core@npm:1.5.0" + version: 1.5.29 + resolution: "@swc/core@npm:1.5.29" dependencies: - "@swc/core-darwin-arm64": 1.5.0 - "@swc/core-darwin-x64": 1.5.0 - "@swc/core-linux-arm-gnueabihf": 1.5.0 - "@swc/core-linux-arm64-gnu": 1.5.0 - "@swc/core-linux-arm64-musl": 1.5.0 - "@swc/core-linux-x64-gnu": 1.5.0 - "@swc/core-linux-x64-musl": 1.5.0 - "@swc/core-win32-arm64-msvc": 1.5.0 - "@swc/core-win32-ia32-msvc": 1.5.0 - "@swc/core-win32-x64-msvc": 1.5.0 - "@swc/counter": ^0.1.2 - "@swc/types": ^0.1.5 + "@swc/core-darwin-arm64": 1.5.29 + "@swc/core-darwin-x64": 1.5.29 + "@swc/core-linux-arm-gnueabihf": 1.5.29 + "@swc/core-linux-arm64-gnu": 1.5.29 + "@swc/core-linux-arm64-musl": 1.5.29 + "@swc/core-linux-x64-gnu": 1.5.29 + "@swc/core-linux-x64-musl": 1.5.29 + "@swc/core-win32-arm64-msvc": 1.5.29 + "@swc/core-win32-ia32-msvc": 1.5.29 + "@swc/core-win32-x64-msvc": 1.5.29 + "@swc/counter": ^0.1.3 + "@swc/types": ^0.1.8 peerDependencies: - "@swc/helpers": ^0.5.0 + "@swc/helpers": "*" dependenciesMeta: "@swc/core-darwin-arm64": optional: true @@ -2954,21 +2954,23 @@ __metadata: peerDependenciesMeta: "@swc/helpers": optional: true - checksum: 1abab0b57755020b60ebf2557629c23c65c3546e4cd80f9d02fbdf208d4169c9300a0229c088081b43a01e630c9d86d02f8c240c9fc2842eaed2a517770fcd1d + checksum: 19e3f8525ce4f4d9f6f3f62825b1f13e1e76146390930b6d5e663c0bb2c5e95ef3bf30268110d1444ea92b99dd95bfe5a3c6e2a3c0dd79291505dc7da1ed3dab languageName: node linkType: hard -"@swc/counter@npm:^0.1.2, @swc/counter@npm:^0.1.3": +"@swc/counter@npm:^0.1.3": version: 0.1.3 resolution: "@swc/counter@npm:0.1.3" checksum: df8f9cfba9904d3d60f511664c70d23bb323b3a0803ec9890f60133954173047ba9bdeabce28cd70ba89ccd3fd6c71c7b0bd58be85f611e1ffbe5d5c18616598 languageName: node linkType: hard -"@swc/types@npm:^0.1.5": - version: 0.1.5 - resolution: "@swc/types@npm:0.1.5" - checksum: 6aee11f62d3d805a64848e0bd5f0e0e615f958e327a9e1260056c368d7d28764d89e38bd8005a536c9bf18afbcd303edd84099d60df34a2975d62540f61df13b +"@swc/types@npm:^0.1.8": + version: 0.1.8 + resolution: "@swc/types@npm:0.1.8" + dependencies: + "@swc/counter": ^0.1.3 + checksum: e564d0e37b0e28546973c6d50c7a179395912a97168d695cfe9cf1051199c8b828680cdafcb8d43948f76d3703873bafb88dfb5bc2dfe0596b4ad18fcaf90c80 languageName: node linkType: hard diff --git a/yarn.lock b/yarn.lock index 5c0993f074..d396102ee2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1777,8 +1777,8 @@ __metadata: linkType: hard "@azure/identity@npm:^4.0.0": - version: 4.1.0 - resolution: "@azure/identity@npm:4.1.0" + version: 4.2.1 + resolution: "@azure/identity@npm:4.2.1" dependencies: "@azure/abort-controller": ^1.0.0 "@azure/core-auth": ^1.5.0 @@ -1788,13 +1788,13 @@ __metadata: "@azure/core-util": ^1.3.0 "@azure/logger": ^1.0.0 "@azure/msal-browser": ^3.11.1 - "@azure/msal-node": ^2.6.6 + "@azure/msal-node": ^2.9.2 events: ^3.0.0 jws: ^4.0.0 open: ^8.0.0 stoppable: ^1.1.0 tslib: ^2.2.0 - checksum: ff46494c7a7fdc866406f0e7938e7621c9ee0e852af2faad7ecf53d62a45b1528150f9c8b13a0fdd846995943025fbcbc88f2582b107cd5afac1511c28252377 + checksum: 2dbd7b0fa6b92904b7b8f828374d7316384cc4e00c71cdac3a2f2544b9e02c7287fe7ad58149bb8794c57913d77a927f5a7b5d1367e05abe82b0f2e1b162415c languageName: node linkType: hard @@ -1816,6 +1816,13 @@ __metadata: languageName: node linkType: hard +"@azure/msal-common@npm:14.12.0": + version: 14.12.0 + resolution: "@azure/msal-common@npm:14.12.0" + checksum: 9a987b7b9b6453500481ec48224b4d9f728c62ac584f9a35ef519eff46016fc63c1a7dc159f725a5ec3748bf1ade352654fd7a7170ba42bc27ca263a01cf59db + languageName: node + linkType: hard + "@azure/msal-common@npm:14.8.1": version: 14.8.1 resolution: "@azure/msal-common@npm:14.8.1" @@ -1823,14 +1830,14 @@ __metadata: languageName: node linkType: hard -"@azure/msal-node@npm:^2.6.6": - version: 2.6.6 - resolution: "@azure/msal-node@npm:2.6.6" +"@azure/msal-node@npm:^2.9.2": + version: 2.9.2 + resolution: "@azure/msal-node@npm:2.9.2" dependencies: - "@azure/msal-common": 14.8.1 + "@azure/msal-common": 14.12.0 jsonwebtoken: ^9.0.0 uuid: ^8.3.0 - checksum: 45a83d774af1bb58df99c67551c68c686385950f701421e0c4c446e4d1b80c316f5e525024189bdbdd520b34e326d0e901a476c2afae07389fb9efd1c616c867 + checksum: a2b51d4085d20cbac84752b9e68a5a22c7c9dbfdbc25a1713ee5e6918a504928f82e66c9317fc78db4f12053e7debd477b984cab578e0bea269aacc0862e7219 languageName: node linkType: hard @@ -1859,55 +1866,55 @@ __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.22.13, @babel/code-frame@npm:^7.23.5, @babel/code-frame@npm:^7.8.3": - version: 7.23.5 - resolution: "@babel/code-frame@npm:7.23.5" +"@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.24.2, @babel/code-frame@npm:^7.24.7, @babel/code-frame@npm:^7.8.3": + version: 7.24.7 + resolution: "@babel/code-frame@npm:7.24.7" dependencies: - "@babel/highlight": ^7.23.4 - chalk: ^2.4.2 - checksum: d90981fdf56a2824a9b14d19a4c0e8db93633fd488c772624b4e83e0ceac6039a27cd298a247c3214faa952bf803ba23696172ae7e7235f3b97f43ba278c569a + "@babel/highlight": ^7.24.7 + picocolors: ^1.0.0 + checksum: 830e62cd38775fdf84d612544251ce773d544a8e63df667728cc9e0126eeef14c6ebda79be0f0bc307e8318316b7f58c27ce86702e0a1f5c321d842eb38ffda4 languageName: node linkType: hard -"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.22.9": - version: 7.22.9 - resolution: "@babel/compat-data@npm:7.22.9" - checksum: bed77d9044ce948b4327b30dd0de0779fa9f3a7ed1f2d31638714ed00229fa71fc4d1617ae0eb1fad419338d3658d0e9a5a083297451e09e73e078d0347ff808 +"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.22.9, @babel/compat-data@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/compat-data@npm:7.24.7" + checksum: 1fc276825dd434fe044877367dfac84171328e75a8483a6976aa28bf833b32367e90ee6df25bdd97c287d1aa8019757adcccac9153de70b1932c0d243a978ae9 languageName: node linkType: hard -"@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.19.6, @babel/core@npm:^7.23.0, @babel/core@npm:^7.23.5": - version: 7.23.5 - resolution: "@babel/core@npm:7.23.5" +"@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.19.6, @babel/core@npm:^7.23.0, @babel/core@npm:^7.24.5": + version: 7.24.7 + resolution: "@babel/core@npm:7.24.7" dependencies: "@ampproject/remapping": ^2.2.0 - "@babel/code-frame": ^7.23.5 - "@babel/generator": ^7.23.5 - "@babel/helper-compilation-targets": ^7.22.15 - "@babel/helper-module-transforms": ^7.23.3 - "@babel/helpers": ^7.23.5 - "@babel/parser": ^7.23.5 - "@babel/template": ^7.22.15 - "@babel/traverse": ^7.23.5 - "@babel/types": ^7.23.5 + "@babel/code-frame": ^7.24.7 + "@babel/generator": ^7.24.7 + "@babel/helper-compilation-targets": ^7.24.7 + "@babel/helper-module-transforms": ^7.24.7 + "@babel/helpers": ^7.24.7 + "@babel/parser": ^7.24.7 + "@babel/template": ^7.24.7 + "@babel/traverse": ^7.24.7 + "@babel/types": ^7.24.7 convert-source-map: ^2.0.0 debug: ^4.1.0 gensync: ^1.0.0-beta.2 json5: ^2.2.3 semver: ^6.3.1 - checksum: 5e5dfb1e61f298676f1fca18c646dbf6fb164ca1056b0169b8d42b7f5c35e026d81823582ccb2358e93a61b035e22b3ad37e2abaae4bf43f1ffb93b6ce19466e + checksum: 017497e2a1b4683a885219eef7d2aee83c1c0cf353506b2e180b73540ec28841d8ef1ea1837fa69f8c561574b24ddd72f04764b27b87afedfe0a07299ccef24d languageName: node linkType: hard -"@babel/generator@npm:^7.23.5, @babel/generator@npm:^7.7.2": - version: 7.23.5 - resolution: "@babel/generator@npm:7.23.5" +"@babel/generator@npm:^7.24.7, @babel/generator@npm:^7.7.2": + version: 7.24.7 + resolution: "@babel/generator@npm:7.24.7" dependencies: - "@babel/types": ^7.23.5 - "@jridgewell/gen-mapping": ^0.3.2 - "@jridgewell/trace-mapping": ^0.3.17 + "@babel/types": ^7.24.7 + "@jridgewell/gen-mapping": ^0.3.5 + "@jridgewell/trace-mapping": ^0.3.25 jsesc: ^2.5.1 - checksum: 845ddda7cf38a3edf4be221cc8a439dee9ea6031355146a1a74047aa8007bc030305b27d8c68ec9e311722c910610bde38c0e13a9ce55225251e7cb7e7f3edc8 + checksum: 0ff31a73b15429f1287e4d57b439bba4a266f8c673bb445fe313b82f6d110f586776997eb723a777cd7adad9d340edd162aea4973a90112c5d0cfcaf6686844b languageName: node linkType: hard @@ -1929,16 +1936,16 @@ __metadata: languageName: node linkType: hard -"@babel/helper-compilation-targets@npm:^7.22.10, @babel/helper-compilation-targets@npm:^7.22.15, @babel/helper-compilation-targets@npm:^7.22.5, @babel/helper-compilation-targets@npm:^7.22.6": - version: 7.22.15 - resolution: "@babel/helper-compilation-targets@npm:7.22.15" +"@babel/helper-compilation-targets@npm:^7.22.10, @babel/helper-compilation-targets@npm:^7.22.5, @babel/helper-compilation-targets@npm:^7.22.6, @babel/helper-compilation-targets@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-compilation-targets@npm:7.24.7" dependencies: - "@babel/compat-data": ^7.22.9 - "@babel/helper-validator-option": ^7.22.15 - browserslist: ^4.21.9 + "@babel/compat-data": ^7.24.7 + "@babel/helper-validator-option": ^7.24.7 + browserslist: ^4.22.2 lru-cache: ^5.1.1 semver: ^6.3.1 - checksum: ce85196769e091ae54dd39e4a80c2a9df1793da8588e335c383d536d54f06baf648d0a08fc873044f226398c4ded15c4ae9120ee18e7dfd7c639a68e3cdc9980 + checksum: dfc88bc35e223ade796c7267901728217c665adc5bc2e158f7b0ae850de14f1b7941bec4fe5950ae46236023cfbdeddd9c747c276acf9b39ca31f8dd97dc6cc6 languageName: node linkType: hard @@ -1989,29 +1996,31 @@ __metadata: languageName: node linkType: hard -"@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 +"@babel/helper-environment-visitor@npm:^7.22.5, @babel/helper-environment-visitor@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-environment-visitor@npm:7.24.7" + dependencies: + "@babel/types": ^7.24.7 + checksum: 079d86e65701b29ebc10baf6ed548d17c19b808a07aa6885cc141b690a78581b180ee92b580d755361dc3b16adf975b2d2058b8ce6c86675fcaf43cf22f2f7c6 languageName: node linkType: hard -"@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" +"@babel/helper-function-name@npm:^7.22.5, @babel/helper-function-name@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-function-name@npm:7.24.7" dependencies: - "@babel/template": ^7.22.15 - "@babel/types": ^7.23.0 - checksum: e44542257b2d4634a1f979244eb2a4ad8e6d75eb6761b4cfceb56b562f7db150d134bc538c8e6adca3783e3bc31be949071527aa8e3aab7867d1ad2d84a26e10 + "@babel/template": ^7.24.7 + "@babel/types": ^7.24.7 + checksum: 142ee08922074dfdc0ff358e09ef9f07adf3671ab6eef4fca74dcf7a551f1a43717e7efa358c9e28d7eea84c28d7f177b7a58c70452fc312ae3b1893c5dab2a4 languageName: node linkType: hard -"@babel/helper-hoist-variables@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-hoist-variables@npm:7.22.5" +"@babel/helper-hoist-variables@npm:^7.22.5, @babel/helper-hoist-variables@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-hoist-variables@npm:7.24.7" dependencies: - "@babel/types": ^7.22.5 - checksum: 394ca191b4ac908a76e7c50ab52102669efe3a1c277033e49467913c7ed6f7c64d7eacbeabf3bed39ea1f41731e22993f763b1edce0f74ff8563fd1f380d92cc + "@babel/types": ^7.24.7 + checksum: 6cfdcf2289cd12185dcdbdf2435fa8d3447b797ac75851166de9fc8503e2fd0021db6baf8dfbecad3753e582c08e6a3f805c8d00cbed756060a877d705bd8d8d languageName: node linkType: hard @@ -2024,27 +2033,28 @@ __metadata: languageName: node linkType: hard -"@babel/helper-module-imports@npm:^7.0.0, @babel/helper-module-imports@npm:^7.16.0, @babel/helper-module-imports@npm:^7.16.7, @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" +"@babel/helper-module-imports@npm:^7.0.0, @babel/helper-module-imports@npm:^7.16.0, @babel/helper-module-imports@npm:^7.16.7, @babel/helper-module-imports@npm:^7.22.5, @babel/helper-module-imports@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-module-imports@npm:7.24.7" dependencies: - "@babel/types": ^7.22.15 - checksum: ecd7e457df0a46f889228f943ef9b4a47d485d82e030676767e6a2fdcbdaa63594d8124d4b55fd160b41c201025aec01fc27580352b1c87a37c9c6f33d116702 + "@babel/traverse": ^7.24.7 + "@babel/types": ^7.24.7 + checksum: 8ac15d96d262b8940bc469052a048e06430bba1296369be695fabdf6799f201dd0b00151762b56012a218464e706bc033f27c07f6cec20c6f8f5fd6543c67054 languageName: node linkType: hard -"@babel/helper-module-transforms@npm:^7.22.5, @babel/helper-module-transforms@npm:^7.22.9, @babel/helper-module-transforms@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/helper-module-transforms@npm:7.23.3" +"@babel/helper-module-transforms@npm:^7.22.5, @babel/helper-module-transforms@npm:^7.22.9, @babel/helper-module-transforms@npm:^7.23.3, @babel/helper-module-transforms@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-module-transforms@npm:7.24.7" dependencies: - "@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 + "@babel/helper-environment-visitor": ^7.24.7 + "@babel/helper-module-imports": ^7.24.7 + "@babel/helper-simple-access": ^7.24.7 + "@babel/helper-split-export-declaration": ^7.24.7 + "@babel/helper-validator-identifier": ^7.24.7 peerDependencies: "@babel/core": ^7.0.0 - checksum: 5d0895cfba0e16ae16f3aa92fee108517023ad89a855289c4eb1d46f7aef4519adf8e6f971e1d55ac20c5461610e17213f1144097a8f932e768a9132e2278d71 + checksum: ddff3b41c2667876b4e4e73d961168f48a5ec9560c95c8c2d109e6221f9ca36c6f90c6317eb7a47f2a3c99419c356e529a86b79174cad0d4f7a61960866b88ca languageName: node linkType: hard @@ -2057,10 +2067,10 @@ __metadata: languageName: node linkType: hard -"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.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 +"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.24.7, @babel/helper-plugin-utils@npm:^7.8.0, @babel/helper-plugin-utils@npm:^7.8.3": + version: 7.24.7 + resolution: "@babel/helper-plugin-utils@npm:7.24.7" + checksum: 81f2a15751d892e4a8fce25390f973363a5b27596167861d2d6eab0f61856eb2ba389b031a9f19f669c0bd4dd601185828d3cebafd25431be7a1696f2ce3ef68 languageName: node linkType: hard @@ -2090,12 +2100,13 @@ __metadata: languageName: node linkType: hard -"@babel/helper-simple-access@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-simple-access@npm:7.22.5" +"@babel/helper-simple-access@npm:^7.22.5, @babel/helper-simple-access@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-simple-access@npm:7.24.7" dependencies: - "@babel/types": ^7.22.5 - checksum: fe9686714caf7d70aedb46c3cce090f8b915b206e09225f1e4dbc416786c2fdbbee40b38b23c268b7ccef749dd2db35f255338fb4f2444429874d900dede5ad2 + "@babel/traverse": ^7.24.7 + "@babel/types": ^7.24.7 + checksum: ddbf55f9dea1900213f2a1a8500fabfd21c5a20f44dcfa957e4b0d8638c730f88751c77f678644f754f1a1dc73f4eb8b766c300deb45a9daad000e4247957819 languageName: node linkType: hard @@ -2108,33 +2119,33 @@ __metadata: languageName: node linkType: hard -"@babel/helper-split-export-declaration@npm:^7.22.6": - version: 7.22.6 - resolution: "@babel/helper-split-export-declaration@npm:7.22.6" +"@babel/helper-split-export-declaration@npm:^7.22.6, @babel/helper-split-export-declaration@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-split-export-declaration@npm:7.24.7" dependencies: - "@babel/types": ^7.22.5 - checksum: e141cace583b19d9195f9c2b8e17a3ae913b7ee9b8120246d0f9ca349ca6f03cb2c001fd5ec57488c544347c0bb584afec66c936511e447fd20a360e591ac921 + "@babel/types": ^7.24.7 + checksum: e3ddc91273e5da67c6953f4aa34154d005a00791dc7afa6f41894e768748540f6ebcac5d16e72541aea0c89bee4b89b4da6a3d65972a0ea8bfd2352eda5b7e22 languageName: node linkType: hard -"@babel/helper-string-parser@npm:^7.23.4": - version: 7.23.4 - resolution: "@babel/helper-string-parser@npm:7.23.4" - checksum: c0641144cf1a7e7dc93f3d5f16d5327465b6cf5d036b48be61ecba41e1eece161b48f46b7f960951b67f8c3533ce506b16dece576baef4d8b3b49f8c65410f90 +"@babel/helper-string-parser@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-string-parser@npm:7.24.7" + checksum: 09568193044a578743dd44bf7397940c27ea693f9812d24acb700890636b376847a611cdd0393a928544e79d7ad5b8b916bd8e6e772bc8a10c48a647a96e7b1a languageName: node linkType: hard -"@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 +"@babel/helper-validator-identifier@npm:^7.22.5, @babel/helper-validator-identifier@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-validator-identifier@npm:7.24.7" + checksum: 6799ab117cefc0ecd35cd0b40ead320c621a298ecac88686a14cffceaac89d80cdb3c178f969861bf5fa5e4f766648f9161ea0752ecfe080d8e89e3147270257 languageName: node linkType: hard -"@babel/helper-validator-option@npm:^7.22.15, @babel/helper-validator-option@npm:^7.22.5": - version: 7.22.15 - resolution: "@babel/helper-validator-option@npm:7.22.15" - checksum: 68da52b1e10002a543161494c4bc0f4d0398c8fdf361d5f7f4272e95c45d5b32d974896d44f6a0ea7378c9204988879d73613ca683e13bd1304e46d25ff67a8d +"@babel/helper-validator-option@npm:^7.22.15, @babel/helper-validator-option@npm:^7.22.5, @babel/helper-validator-option@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-validator-option@npm:7.24.7" + checksum: 9689166bf3f777dd424c026841c8cd651e41b21242dbfd4569a53086179a3e744c8eddd56e9d10b54142270141c91581b53af0d7c00c82d552d2540e2a919f7e languageName: node linkType: hard @@ -2149,34 +2160,34 @@ __metadata: languageName: node linkType: hard -"@babel/helpers@npm:^7.23.5": - version: 7.23.5 - resolution: "@babel/helpers@npm:7.23.5" +"@babel/helpers@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helpers@npm:7.24.7" dependencies: - "@babel/template": ^7.22.15 - "@babel/traverse": ^7.23.5 - "@babel/types": ^7.23.5 - checksum: c16dc8a3bb3d0e02c7ee1222d9d0865ed4b92de44fb8db43ff5afd37a0fc9ea5e2906efa31542c95b30c1a3a9540d66314663c9a23b5bb9b5ec76e8ebc896064 + "@babel/template": ^7.24.7 + "@babel/types": ^7.24.7 + checksum: 934da58098a3670ca7f9f42425b9c44d0ca4f8fad815c0f51d89fc7b64c5e0b4c7d5fec038599de691229ada737edeaf72fad3eba8e16dd5842e8ea447f76b66 languageName: node linkType: hard -"@babel/highlight@npm:^7.0.0, @babel/highlight@npm:^7.23.4": - version: 7.23.4 - resolution: "@babel/highlight@npm:7.23.4" +"@babel/highlight@npm:^7.0.0, @babel/highlight@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/highlight@npm:7.24.7" dependencies: - "@babel/helper-validator-identifier": ^7.22.20 + "@babel/helper-validator-identifier": ^7.24.7 chalk: ^2.4.2 js-tokens: ^4.0.0 - checksum: 643acecdc235f87d925979a979b539a5d7d1f31ae7db8d89047269082694122d11aa85351304c9c978ceeb6d250591ccadb06c366f358ccee08bb9c122476b89 + picocolors: ^1.0.0 + checksum: 5cd3a89f143671c4ac129960024ba678b669e6fc673ce078030f5175002d1d3d52bc10b22c5b916a6faf644b5028e9a4bd2bb264d053d9b05b6a98690f1d46f1 languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.23.0, @babel/parser@npm:^7.23.5": - version: 7.23.5 - resolution: "@babel/parser@npm:7.23.5" +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.0, @babel/parser@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/parser@npm:7.24.7" bin: parser: ./bin/babel-parser.js - checksum: ea763629310f71580c4a3ea9d3705195b7ba994ada2cc98f9a584ebfdacf54e92b2735d351672824c2c2b03c7f19206899f4d95650d85ce514a822b19a8734c7 + checksum: fc9d2c4c8712f89672edc55c0dc5cf640dcec715b56480f111f85c2bc1d507e251596e4110d65796690a96ac37a4b60432af90b3e97bb47e69d4ef83872dbbd6 languageName: node linkType: hard @@ -2955,25 +2966,25 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-react-jsx-self@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-react-jsx-self@npm:7.23.3" +"@babel/plugin-transform-react-jsx-self@npm:^7.24.5": + version: 7.24.7 + resolution: "@babel/plugin-transform-react-jsx-self@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-plugin-utils": ^7.24.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 882bf56bc932d015c2d83214133939ddcf342e5bcafa21f1a93b19f2e052145115e1e0351730897fd66e5f67cad7875b8a8d81ceb12b6e2a886ad0102cb4eb1f + checksum: 2d72c33664e614031b8a03fc2d4cfd185e99efb1d681cbde4b0b4ab379864b31d83ee923509892f6d94b2c5893c309f0217d33bcda3e470ed42297f958138381 languageName: node linkType: hard -"@babel/plugin-transform-react-jsx-source@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-react-jsx-source@npm:7.23.3" +"@babel/plugin-transform-react-jsx-source@npm:^7.24.1": + version: 7.24.7 + resolution: "@babel/plugin-transform-react-jsx-source@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-plugin-utils": ^7.24.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 92287fb797e522d99bdc77eaa573ce79ff0ad9f1cf4e7df374645e28e51dce0adad129f6f075430b129b5bac8dad843f65021970e12e992d6d6671f0d65bb1e0 + checksum: c9afcb2259dd124a2de76f8a578589c18bd2f24dbcf78fe02b53c5cbc20c493c4618369604720e4e699b52be10ba0751b97140e1ef8bc8f0de0a935280e9d5b7 languageName: node linkType: hard @@ -3313,13 +3324,13 @@ __metadata: languageName: node linkType: hard -"@babel/runtime-corejs3@npm:^7.20.7, @babel/runtime-corejs3@npm:^7.22.15, @babel/runtime-corejs3@npm:^7.24.4": - version: 7.24.4 - resolution: "@babel/runtime-corejs3@npm:7.24.4" +"@babel/runtime-corejs3@npm:^7.20.7, @babel/runtime-corejs3@npm:^7.22.15, @babel/runtime-corejs3@npm:^7.24.5": + version: 7.24.7 + resolution: "@babel/runtime-corejs3@npm:7.24.7" dependencies: core-js-pure: ^3.30.2 regenerator-runtime: ^0.14.0 - checksum: 0c2e7c477de3dbf5cc6f2434cee3d78a34d87e8f1e2ea65840eb948d00f7d6968e0ef055449adf372a39d6214f8b9b2532506149b9d0e7ea3d09b1b84678ae6c + checksum: fb5cae960a2d4cbcb2144059dfa9dbe5530d027fa210a5bc37c67c3014226c32390f221320066124872f3d6c4830af17a19da09c10ab114da9b6fa8ab4377cea languageName: node linkType: hard @@ -3332,43 +3343,43 @@ __metadata: languageName: node linkType: hard -"@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" +"@babel/template@npm:^7.22.5, @babel/template@npm:^7.24.7, @babel/template@npm:^7.3.3": + version: 7.24.7 + resolution: "@babel/template@npm:7.24.7" dependencies: - "@babel/code-frame": ^7.22.13 - "@babel/parser": ^7.22.15 - "@babel/types": ^7.22.15 - checksum: 1f3e7dcd6c44f5904c184b3f7fe280394b191f2fed819919ffa1e529c259d5b197da8981b6ca491c235aee8dbad4a50b7e31304aa531271cb823a4a24a0dd8fd + "@babel/code-frame": ^7.24.7 + "@babel/parser": ^7.24.7 + "@babel/types": ^7.24.7 + checksum: ea90792fae708ddf1632e54c25fe1a86643d8c0132311f81265d2bdbdd42f9f4fac65457056c1b6ca87f7aa0d6a795b549566774bba064bdcea2034ab3960ee9 languageName: node linkType: hard -"@babel/traverse@npm:^7.23.5, @babel/traverse@npm:^7.4.5": - version: 7.23.5 - resolution: "@babel/traverse@npm:7.23.5" +"@babel/traverse@npm:^7.24.7, @babel/traverse@npm:^7.4.5": + version: 7.24.7 + resolution: "@babel/traverse@npm:7.24.7" dependencies: - "@babel/code-frame": ^7.23.5 - "@babel/generator": ^7.23.5 - "@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.5 - "@babel/types": ^7.23.5 - debug: ^4.1.0 + "@babel/code-frame": ^7.24.7 + "@babel/generator": ^7.24.7 + "@babel/helper-environment-visitor": ^7.24.7 + "@babel/helper-function-name": ^7.24.7 + "@babel/helper-hoist-variables": ^7.24.7 + "@babel/helper-split-export-declaration": ^7.24.7 + "@babel/parser": ^7.24.7 + "@babel/types": ^7.24.7 + debug: ^4.3.1 globals: ^11.1.0 - checksum: 0558b05360850c3ad6384e85bd55092126a8d5f93e29a8e227dd58fa1f9e1a4c25fd337c07c7ae509f0983e7a2b1e761ffdcfaa77a1e1bedbc867058e1de5a7d + checksum: 7cd366afe9e7ee77e493779fdf24f67bf5595247289364f4689e29688572505eaeb886d7a8f20ebb9c29fc2de7d0895e4ff9e203e78e39ac67239724d45aa83b languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.10, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.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.23.5 - resolution: "@babel/types@npm:7.23.5" +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.10, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.24.7, @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.24.7 + resolution: "@babel/types@npm:7.24.7" dependencies: - "@babel/helper-string-parser": ^7.23.4 - "@babel/helper-validator-identifier": ^7.22.20 + "@babel/helper-string-parser": ^7.24.7 + "@babel/helper-validator-identifier": ^7.24.7 to-fast-properties: ^2.0.0 - checksum: 3d21774480a459ef13b41c2e32700d927af649e04b70c5d164814d8e04ab584af66a93330602c2925e1a6925c2b829cc153418a613a4e7d79d011be1f29ad4b2 + checksum: 3e4437fced97e02982972ce5bebd318c47d42c9be2152c0fd28c6f786cc74086cc0a8fb83b602b846e41df37f22c36254338eada1a47ef9d8a1ec92332ca3ea8 languageName: node linkType: hard @@ -3446,6 +3457,7 @@ __metadata: resolution: "@backstage/backend-app-api@workspace:packages/backend-app-api" dependencies: "@backstage/backend-common": "workspace:^" + "@backstage/backend-defaults": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-tasks": "workspace:^" "@backstage/backend-test-utils": "workspace:^" @@ -3485,6 +3497,7 @@ __metadata: minimist: ^1.2.5 morgan: ^1.10.0 msw: ^1.0.0 + node-fetch: ^2.6.7 node-forge: ^1.3.1 path-to-regexp: ^6.2.1 selfsigned: ^2.0.0 @@ -3507,7 +3520,6 @@ __metadata: "@aws-sdk/credential-providers": ^3.350.0 "@aws-sdk/types": ^3.347.0 "@aws-sdk/util-stream-node": ^3.350.0 - "@backstage/backend-app-api": "workspace:^" "@backstage/backend-dev-utils": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" @@ -3536,7 +3548,10 @@ __metadata: "@types/fs-extra": ^11.0.0 "@types/http-errors": ^2.0.0 "@types/luxon": ^3.0.0 + "@types/morgan": ^1.9.0 + "@types/node-forge": ^1.3.0 "@types/pg": ^8.6.6 + "@types/stoppable": ^1.1.0 "@types/supertest": ^2.0.8 "@types/tar": ^6.1.1 "@types/webpack-env": ^1.15.2 @@ -3563,14 +3578,21 @@ __metadata: logform: ^2.3.2 luxon: ^3.0.0 minimatch: ^9.0.0 + minimist: ^1.2.5 + morgan: ^1.10.0 msw: ^1.0.0 mysql2: ^3.0.0 node-fetch: ^2.6.7 + node-forge: ^1.3.1 p-limit: ^3.1.0 + path-to-regexp: ^6.2.1 pg: ^8.11.3 raw-body: ^2.4.1 + selfsigned: ^2.0.0 + stoppable: ^1.1.0 supertest: ^6.1.3 tar: ^6.1.12 + triple-beam: ^1.4.1 uuid: ^9.0.0 winston: ^3.2.1 winston-transport: ^4.5.0 @@ -3600,43 +3622,71 @@ __metadata: "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" + "@backstage/cli-common": "workspace:^" "@backstage/config": "workspace:^" "@backstage/config-loader": "workspace:^" "@backstage/errors": "workspace:^" "@backstage/integration": "workspace:^" "@backstage/integration-aws-node": "workspace:^" + "@backstage/plugin-auth-node": "workspace:^" "@backstage/plugin-events-node": "workspace:^" "@backstage/plugin-permission-node": "workspace:^" "@backstage/types": "workspace:^" "@google-cloud/storage": ^7.0.0 "@keyv/memcache": ^1.3.5 "@keyv/redis": ^2.5.3 + "@manypkg/get-packages": ^1.1.3 "@octokit/rest": ^19.0.3 "@opentelemetry/api": ^1.3.0 + "@types/cors": ^2.8.6 + "@types/express": ^4.17.6 + "@types/http-errors": ^2.0.0 + "@types/morgan": ^1.9.0 + "@types/node-forge": ^1.3.0 + "@types/stoppable": ^1.1.0 archiver: ^6.0.0 aws-sdk-client-mock: ^4.0.0 base64-stream: ^1.0.0 better-sqlite3: ^9.0.0 + compression: ^1.7.4 concat-stream: ^2.0.0 + cookie: ^0.6.0 + cors: ^2.8.5 cron: ^3.0.0 + express: ^4.17.1 + express-promise-router: ^4.1.0 fs-extra: ^11.2.0 git-url-parse: ^14.0.0 + helmet: ^6.0.0 + http-errors: ^2.0.0 isomorphic-git: ^1.23.0 + jose: ^5.0.0 keyv: ^4.5.2 knex: ^3.0.0 lodash: ^4.17.21 + logform: ^2.3.2 luxon: ^3.0.0 minimatch: ^9.0.0 + minimist: ^1.2.5 + morgan: ^1.10.0 msw: ^1.0.0 mysql2: ^3.0.0 node-fetch: ^2.6.7 + node-forge: ^1.3.1 p-limit: ^3.1.0 + path-to-regexp: ^6.2.1 pg: ^8.11.3 pg-connection-string: ^2.3.0 raw-body: ^2.4.1 + selfsigned: ^2.0.0 + stoppable: ^1.1.0 + supertest: ^6.1.3 tar: ^6.1.12 + triple-beam: ^1.4.1 uuid: ^9.0.0 wait-for-expect: ^3.0.2 + winston: ^3.2.1 + winston-transport: ^4.5.0 yauzl: ^3.0.0 yn: ^4.0.0 zod: ^3.22.4 @@ -3756,6 +3806,7 @@ __metadata: resolution: "@backstage/backend-test-utils@workspace:packages/backend-test-utils" dependencies: "@backstage/backend-app-api": "workspace:^" + "@backstage/backend-defaults": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" @@ -3920,7 +3971,7 @@ __metadata: ctrlc-windows: ^2.1.0 del: ^7.0.0 diff: ^5.0.0 - esbuild: ^0.20.0 + esbuild: ^0.21.0 esbuild-loader: ^4.0.0 eslint: ^8.6.0 eslint-config-prettier: ^9.0.0 @@ -3980,7 +4031,7 @@ __metadata: util: ^0.12.3 vite: ^4.4.9 vite-plugin-html: ^3.2.0 - vite-plugin-node-polyfills: ^0.21.0 + vite-plugin-node-polyfills: ^0.22.0 webpack: ^5.70.0 webpack-dev-server: ^5.0.0 webpack-node-externals: ^3.0.0 @@ -3992,7 +4043,7 @@ __metadata: "@vitejs/plugin-react": ^4.0.4 vite: ^4.4.9 vite-plugin-html: ^3.2.0 - vite-plugin-node-polyfills: ^0.21.0 + vite-plugin-node-polyfills: ^0.22.0 peerDependenciesMeta: "@vitejs/plugin-react": optional: true @@ -4175,14 +4226,14 @@ __metadata: languageName: node linkType: hard -"@backstage/core-components@npm:^0.14.4, @backstage/core-components@npm:^0.14.7": - version: 0.14.7 - resolution: "@backstage/core-components@npm:0.14.7" +"@backstage/core-components@npm:^0.14.4, @backstage/core-components@npm:^0.14.8": + version: 0.14.8 + resolution: "@backstage/core-components@npm:0.14.8" dependencies: "@backstage/config": ^1.2.0 - "@backstage/core-plugin-api": ^1.9.2 + "@backstage/core-plugin-api": ^1.9.3 "@backstage/errors": ^1.2.4 - "@backstage/theme": ^0.5.4 + "@backstage/theme": ^0.5.6 "@backstage/version-bridge": ^1.0.8 "@date-io/core": ^1.3.13 "@material-table/core": ^3.1.0 @@ -4220,7 +4271,7 @@ __metadata: react: ^16.13.1 || ^17.0.0 || ^18.0.0 react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 - checksum: e3906347c197d741dbff24d20af5cd0117e4bf1667c34a4a3a70d8c0f3c0c92bd768b53c417ca78f8b87560a3623f497938f531be86c8727f83822a11e9aa4e5 + checksum: b833e833c83f72e0cc695fe2726cbf01b58819ad062ed9ab1e604514bb398ade20e1abb208d2e39ab1f746fdbd4547486e3935bacb44b457a47070f9c77895dc languageName: node linkType: hard @@ -4295,25 +4346,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/core-plugin-api@npm:^1.8.2, @backstage/core-plugin-api@npm:^1.9.2": - version: 1.9.2 - resolution: "@backstage/core-plugin-api@npm:1.9.2" - dependencies: - "@backstage/config": ^1.2.0 - "@backstage/errors": ^1.2.4 - "@backstage/types": ^1.1.1 - "@backstage/version-bridge": ^1.0.8 - "@types/react": ^16.13.1 || ^17.0.0 || ^18.0.0 - history: ^5.0.0 - peerDependencies: - react: ^16.13.1 || ^17.0.0 || ^18.0.0 - react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 - react-router-dom: 6.0.0-beta.0 || ^6.3.0 - checksum: 2df505c14853b3b35b8644d66f3e58d235bc6ee7f7b81785ec163aa9f089fc03a6c03e3b191d001b247f19d97063e02e585d67661720a8b6a13ab67a2403c218 - languageName: node - linkType: hard - -"@backstage/core-plugin-api@workspace:^, @backstage/core-plugin-api@workspace:packages/core-plugin-api": +"@backstage/core-plugin-api@^1.8.2, @backstage/core-plugin-api@^1.9.2, @backstage/core-plugin-api@^1.9.3, @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: @@ -4460,12 +4493,12 @@ __metadata: languageName: unknown linkType: soft -"@backstage/frontend-plugin-api@npm:^0.6.5": - version: 0.6.5 - resolution: "@backstage/frontend-plugin-api@npm:0.6.5" +"@backstage/frontend-plugin-api@npm:^0.6.6": + version: 0.6.6 + resolution: "@backstage/frontend-plugin-api@npm:0.6.6" dependencies: - "@backstage/core-components": ^0.14.7 - "@backstage/core-plugin-api": ^1.9.2 + "@backstage/core-components": ^0.14.8 + "@backstage/core-plugin-api": ^1.9.3 "@backstage/types": ^1.1.1 "@backstage/version-bridge": ^1.0.8 "@material-ui/core": ^4.12.4 @@ -4476,7 +4509,7 @@ __metadata: peerDependencies: react: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 - checksum: be880b5a3bb86d4e2c32a90ca64265b529901dabcdcbf5a87b5cbdfd68fc347297359550da195034e671e074db9db7c659d663d4fd46ed3836896bd1878fae2f + checksum: c2af07bb73751f050937ba0f34941cc21639defdf13c6e219069ff4143324404229113874caef28f41b9a92a00121991da2a88782595e5221b48910e2f8be7c7 languageName: node linkType: hard @@ -4543,13 +4576,13 @@ __metadata: languageName: unknown linkType: soft -"@backstage/integration-react@npm:^1.1.27": - version: 1.1.27 - resolution: "@backstage/integration-react@npm:1.1.27" +"@backstage/integration-react@npm:^1.1.28": + version: 1.1.28 + resolution: "@backstage/integration-react@npm:1.1.28" dependencies: "@backstage/config": ^1.2.0 - "@backstage/core-plugin-api": ^1.9.2 - "@backstage/integration": ^1.11.0 + "@backstage/core-plugin-api": ^1.9.3 + "@backstage/integration": ^1.12.0 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@types/react": ^16.13.1 || ^17.0.0 @@ -4557,7 +4590,7 @@ __metadata: react: ^16.13.1 || ^17.0.0 || ^18.0.0 react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 - checksum: 136bdfeb7c4ba91eb2405a82ae99fd5d935056d7fe77064bf799a8d375a2b5c645e0df7deaee7e1e0ad6fb48dcac94c82e4b29e3d3a00f80555116b1902102b2 + checksum: 15443a7ebc457114715651e652a40472085ca18ec10da078bad1e71e3aa9cac33d10704b164d09108f6195a9cb4d2eae11751d853598ef0dd0e4c160858f782d languageName: node linkType: hard @@ -4585,9 +4618,9 @@ __metadata: languageName: unknown linkType: soft -"@backstage/integration@npm:^1.11.0": - version: 1.11.0 - resolution: "@backstage/integration@npm:1.11.0" +"@backstage/integration@npm:^1.12.0": + version: 1.12.0 + resolution: "@backstage/integration@npm:1.12.0" dependencies: "@azure/identity": ^4.0.0 "@backstage/config": ^1.2.0 @@ -4598,7 +4631,7 @@ __metadata: git-url-parse: ^14.0.0 lodash: ^4.17.21 luxon: ^3.0.0 - checksum: 57ea46e57da004cdab41e82f558105f78f84f65d58163e93363dc775d42ab29401d3a38390ace012bf388eec57350d432a415d8fed27e57419e21522044fcc33 + checksum: 603c08058dadfe54b5d1788db87bab951b53ea4d1b19f609873717e0ab514859cc8608d0d60755c91eaea000ad71f817c5dd50892a3215443d7eed5a1d24a849 languageName: node linkType: hard @@ -5511,6 +5544,19 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-catalog-backend-module-logs@workspace:plugins/catalog-backend-module-logs": + version: 0.0.0-use.local + resolution: "@backstage/plugin-catalog-backend-module-logs@workspace:plugins/catalog-backend-module-logs" + dependencies: + "@backstage/backend-plugin-api": "workspace:^" + "@backstage/backend-test-utils": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/plugin-catalog-backend": "workspace:^" + "@backstage/plugin-events-backend-test-utils": "workspace:^" + "@backstage/plugin-events-node": "workspace:^" + languageName: unknown + linkType: soft + "@backstage/plugin-catalog-backend-module-msgraph@workspace:plugins/catalog-backend-module-msgraph": version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-backend-module-msgraph@workspace:plugins/catalog-backend-module-msgraph" @@ -5674,7 +5720,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-catalog-common@^1.0.20, @backstage/plugin-catalog-common@^1.0.23, @backstage/plugin-catalog-common@workspace:^, @backstage/plugin-catalog-common@workspace:plugins/catalog-common": +"@backstage/plugin-catalog-common@^1.0.20, @backstage/plugin-catalog-common@^1.0.24, @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: @@ -5784,19 +5830,19 @@ __metadata: linkType: soft "@backstage/plugin-catalog-react@npm:^1.11.3, @backstage/plugin-catalog-react@npm:^1.9.3": - version: 1.12.0 - resolution: "@backstage/plugin-catalog-react@npm:1.12.0" + version: 1.12.1 + resolution: "@backstage/plugin-catalog-react@npm:1.12.1" dependencies: "@backstage/catalog-client": ^1.6.5 "@backstage/catalog-model": ^1.5.0 - "@backstage/core-components": ^0.14.7 - "@backstage/core-plugin-api": ^1.9.2 + "@backstage/core-components": ^0.14.8 + "@backstage/core-plugin-api": ^1.9.3 "@backstage/errors": ^1.2.4 - "@backstage/frontend-plugin-api": ^0.6.5 - "@backstage/integration-react": ^1.1.27 - "@backstage/plugin-catalog-common": ^1.0.23 - "@backstage/plugin-permission-common": ^0.7.13 - "@backstage/plugin-permission-react": ^0.4.22 + "@backstage/frontend-plugin-api": ^0.6.6 + "@backstage/integration-react": ^1.1.28 + "@backstage/plugin-catalog-common": ^1.0.24 + "@backstage/plugin-permission-common": ^0.7.14 + "@backstage/plugin-permission-react": ^0.4.23 "@backstage/types": ^1.1.1 "@backstage/version-bridge": ^1.0.8 "@material-ui/core": ^4.12.2 @@ -5815,7 +5861,7 @@ __metadata: react: ^16.13.1 || ^17.0.0 || ^18.0.0 react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 - checksum: 8079c6c1f4c5b07df5cfb2873f4c3ba16759a3a1ac36a1e1ff61fb428cece5baca40b5c2bc41a2d402ad9a60e73fd545c0a95eec274189423f40a04551a5f337 + checksum: adbf967e978fa6bb4798d0620853e41f64cc08c39dd0056fc01b2146ca427d1bfab401b8972d7b551d4188b90f80f69db9254799bca095608b7079cec73da9c5 languageName: node linkType: hard @@ -6177,7 +6223,7 @@ __metadata: "@backstage/core-plugin-api": "workspace:^" "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 - "@rjsf/utils": 5.18.2 + "@rjsf/utils": 5.18.4 "@types/react": ^16.13.1 || ^17.0.0 "@types/react-grid-layout": ^1.3.2 peerDependencies: @@ -6208,10 +6254,10 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@rjsf/core": 5.18.2 - "@rjsf/material-ui": 5.18.2 - "@rjsf/utils": 5.18.2 - "@rjsf/validator-ajv8": 5.18.2 + "@rjsf/core": 5.18.4 + "@rjsf/material-ui": 5.18.4 + "@rjsf/utils": 5.18.4 + "@rjsf/validator-ajv8": 5.18.4 "@testing-library/dom": ^10.0.0 "@testing-library/jest-dom": ^6.0.0 "@testing-library/react": ^15.0.0 @@ -6662,7 +6708,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-permission-common@^0.7.13, @backstage/plugin-permission-common@workspace:^, @backstage/plugin-permission-common@workspace:plugins/permission-common": +"@backstage/plugin-permission-common@^0.7.14, @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: @@ -6700,24 +6746,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-permission-react@npm:^0.4.22": - version: 0.4.22 - resolution: "@backstage/plugin-permission-react@npm:0.4.22" - dependencies: - "@backstage/config": ^1.2.0 - "@backstage/core-plugin-api": ^1.9.2 - "@backstage/plugin-permission-common": ^0.7.13 - "@types/react": ^16.13.1 || ^17.0.0 || ^18.0.0 - swr: ^2.0.0 - peerDependencies: - react: ^16.13.1 || ^17.0.0 || ^18.0.0 - react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 - react-router-dom: 6.0.0-beta.0 || ^6.3.0 - checksum: c91ad5a336358ae3a2e6030e7ea7a8584735544a14aa6ada061ca0c01ee32b2e16bd2fe24c9327cbdb959eec185bac045b1211b0a03a5c9d45b350f0a6c031ca - languageName: node - linkType: hard - -"@backstage/plugin-permission-react@workspace:^, @backstage/plugin-permission-react@workspace:plugins/permission-react": +"@backstage/plugin-permission-react@^0.4.23, @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" dependencies: @@ -6795,6 +6824,7 @@ __metadata: "@backstage/config": "workspace:^" "@backstage/errors": "workspace:^" "@backstage/integration": "workspace:^" + "@backstage/plugin-bitbucket-cloud-common": "workspace:^" "@backstage/plugin-scaffolder-node": "workspace:^" "@backstage/plugin-scaffolder-node-test-utils": "workspace:^" fs-extra: ^11.2.0 @@ -6889,6 +6919,22 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-scaffolder-backend-module-gcp@workspace:plugins/scaffolder-backend-module-gcp": + version: 0.0.0-use.local + resolution: "@backstage/plugin-scaffolder-backend-module-gcp@workspace:plugins/scaffolder-backend-module-gcp" + dependencies: + "@backstage/backend-plugin-api": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/config": "workspace:^" + "@backstage/errors": "workspace:^" + "@backstage/integration": "workspace:^" + "@backstage/plugin-scaffolder-node": "workspace:^" + "@backstage/plugin-scaffolder-node-test-utils": "workspace:^" + "@google-cloud/storage": ^7.0.0 + raw-body: ^2.4.1 + languageName: unknown + linkType: soft + "@backstage/plugin-scaffolder-backend-module-gerrit@workspace:^, @backstage/plugin-scaffolder-backend-module-gerrit@workspace:plugins/scaffolder-backend-module-gerrit": version: 0.0.0-use.local resolution: "@backstage/plugin-scaffolder-backend-module-gerrit@workspace:plugins/scaffolder-backend-module-gerrit" @@ -7048,6 +7094,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-scaffolder-backend@workspace:plugins/scaffolder-backend" dependencies: + "@backstage/backend-app-api": "workspace:^" "@backstage/backend-common": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-tasks": "workspace:^" @@ -7059,6 +7106,7 @@ __metadata: "@backstage/errors": "workspace:^" "@backstage/integration": "workspace:^" "@backstage/plugin-auth-node": "workspace:^" + "@backstage/plugin-bitbucket-cloud-common": "workspace:^" "@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "workspace:^" "@backstage/plugin-catalog-node": "workspace:^" "@backstage/plugin-permission-common": "workspace:^" @@ -7082,7 +7130,7 @@ __metadata: "@types/supertest": ^2.0.8 "@types/zen-observable": ^0.8.0 concat-stream: ^2.0.0 - esbuild: ^0.20.0 + esbuild: ^0.21.0 express: ^4.17.1 express-promise-router: ^4.1.0 fs-extra: ^11.2.0 @@ -7150,11 +7198,13 @@ __metadata: "@backstage/integration": "workspace:^" "@backstage/plugin-scaffolder-common": "workspace:^" "@backstage/types": "workspace:^" + concat-stream: ^2.0.0 fs-extra: ^11.2.0 globby: ^11.0.0 isomorphic-git: ^1.23.0 jsonschema: ^1.2.6 p-limit: ^3.1.0 + tar: ^6.1.12 winston: ^3.2.1 zod: ^3.22.4 zod-to-json-schema: ^3.20.4 @@ -7185,10 +7235,10 @@ __metadata: "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 "@react-hookz/web": ^24.0.0 - "@rjsf/core": 5.18.2 - "@rjsf/material-ui": 5.18.2 - "@rjsf/utils": 5.18.2 - "@rjsf/validator-ajv8": 5.18.2 + "@rjsf/core": 5.18.4 + "@rjsf/material-ui": 5.18.4 + "@rjsf/utils": 5.18.4 + "@rjsf/validator-ajv8": 5.18.4 "@testing-library/dom": ^10.0.0 "@testing-library/jest-dom": ^6.0.0 "@testing-library/react": ^15.0.0 @@ -7251,10 +7301,10 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@microsoft/fetch-event-source": ^2.0.1 "@react-hookz/web": ^24.0.0 - "@rjsf/core": 5.18.2 - "@rjsf/material-ui": 5.18.2 - "@rjsf/utils": 5.18.2 - "@rjsf/validator-ajv8": 5.18.2 + "@rjsf/core": 5.18.4 + "@rjsf/material-ui": 5.18.4 + "@rjsf/utils": 5.18.4 + "@rjsf/validator-ajv8": 5.18.4 "@testing-library/dom": ^10.0.0 "@testing-library/jest-dom": ^6.0.0 "@testing-library/react": ^15.0.0 @@ -7262,6 +7312,7 @@ __metadata: "@types/humanize-duration": ^3.18.1 "@types/json-schema": ^7.0.9 "@types/react": ^16.13.1 || ^17.0.0 || ^18.0.0 + "@types/react-window": ^1.8.8 "@uiw/react-codemirror": ^4.9.3 classnames: ^2.2.6 git-url-parse: ^14.0.0 @@ -7274,6 +7325,7 @@ __metadata: msw: ^1.0.0 qs: ^6.9.4 react-use: ^17.2.4 + react-window: ^1.8.10 swr: ^2.0.0 yaml: ^2.0.0 zen-observable: ^0.10.0 @@ -7683,9 +7735,7 @@ __metadata: "@backstage/plugin-permission-common": "workspace:^" "@backstage/plugin-search-backend-module-techdocs": "workspace:^" "@backstage/plugin-techdocs-node": "workspace:^" - "@types/dockerode": ^3.3.0 "@types/express": ^4.17.6 - dockerode: ^4.0.0 express: ^4.17.1 express-promise-router: ^4.1.0 fs-extra: ^11.2.0 @@ -7757,6 +7807,7 @@ __metadata: "@types/recursive-readdir": ^2.2.0 "@types/supertest": ^2.0.8 aws-sdk-client-mock: ^4.0.0 + dockerode: ^4.0.0 express: ^4.17.1 fs-extra: ^11.2.0 git-url-parse: ^14.0.0 @@ -8016,23 +8067,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/theme@npm:^0.5.0, @backstage/theme@npm:^0.5.4": - version: 0.5.5 - resolution: "@backstage/theme@npm:0.5.5" - dependencies: - "@emotion/react": ^11.10.5 - "@emotion/styled": ^11.10.5 - "@mui/material": ^5.12.2 - peerDependencies: - "@material-ui/core": ^4.12.2 - "@types/react": ^16.13.1 || ^17.0.0 || ^18.0.0 - react: ^16.13.1 || ^17.0.0 || ^18.0.0 - react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 - checksum: a5ba7b39d41773a4a73a07d1a9a6bcf0815835a196a31c1ec1d5eac61ec801bfe875f31823a6ae6aa5033b21bd04b4fa692fd3fddc71a12e2126b1d222738b34 - languageName: node - linkType: hard - -"@backstage/theme@workspace:^, @backstage/theme@workspace:packages/theme": +"@backstage/theme@^0.5.0, @backstage/theme@^0.5.6, @backstage/theme@workspace:^, @backstage/theme@workspace:packages/theme": version: 0.0.0-use.local resolution: "@backstage/theme@workspace:packages/theme" dependencies: @@ -8092,10 +8127,10 @@ __metadata: languageName: node linkType: hard -"@braintree/sanitize-url@npm:=7.0.1": - version: 7.0.1 - resolution: "@braintree/sanitize-url@npm:7.0.1" - checksum: 793a3b01c5e06152b197c73cccee2db99e921b36d944fc0738e732b5da068709da8844eb8e1489ea360c34b00a100c8b9b3065d5e2030ba5252cdd5d2a6a9a28 +"@braintree/sanitize-url@npm:=7.0.2": + version: 7.0.2 + resolution: "@braintree/sanitize-url@npm:7.0.2" + checksum: d90baf41220e2c6a53005ab89d01abd2ab007ba341ee77af6f0cc7e30f0fd9c1e8b78b19f7e60ba8c0befe4ecb772dcedb464bd5d768236d7fd8c373d236c169 languageName: node linkType: hard @@ -8733,15 +8768,13 @@ __metadata: languageName: node linkType: hard -"@ericcornelissen/bash-parser@npm:0.5.2": - version: 0.5.2 - resolution: "@ericcornelissen/bash-parser@npm:0.5.2" +"@ericcornelissen/bash-parser@npm:0.5.3": + version: 0.5.3 + resolution: "@ericcornelissen/bash-parser@npm:0.5.3" dependencies: array-last: ^1.1.1 babylon: ^6.9.1 compose-function: ^3.0.3 - deep-freeze: 0.0.1 - filter-iterator: 0.0.1 filter-obj: ^1.1.0 has-own-property: ^0.1.0 identity-function: ^1.0.0 @@ -8756,7 +8789,7 @@ __metadata: shell-quote-word: ^1.0.1 to-pascal-case: ^1.0.0 unescape-js: ^1.0.5 - checksum: ed6feb775a45e529e36b8ab01cfe2ba39446d8403f30022d4c00f009a45ae47e9c2fd43d5607b7120366c29c42aaf4c5b0bc202066e71d543f3cde235240a87b + checksum: b3f6c899ea3240000b83674d37c744e2ae06e776b2f76129db9fcd397d77f2cb84c1c560ce318395fffc6a2b5edb1ec513a8c67514f4ea0229d9d87095955ac5 languageName: node linkType: hard @@ -8767,6 +8800,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/aix-ppc64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/aix-ppc64@npm:0.21.5" + conditions: os=aix & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/android-arm64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/android-arm64@npm:0.18.20" @@ -8781,6 +8821,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/android-arm64@npm:0.21.5" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/android-arm@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/android-arm@npm:0.18.20" @@ -8795,6 +8842,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/android-arm@npm:0.21.5" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + "@esbuild/android-x64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/android-x64@npm:0.18.20" @@ -8809,6 +8863,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/android-x64@npm:0.21.5" + conditions: os=android & cpu=x64 + languageName: node + linkType: hard + "@esbuild/darwin-arm64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/darwin-arm64@npm:0.18.20" @@ -8823,6 +8884,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/darwin-arm64@npm:0.21.5" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/darwin-x64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/darwin-x64@npm:0.18.20" @@ -8837,6 +8905,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/darwin-x64@npm:0.21.5" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@esbuild/freebsd-arm64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/freebsd-arm64@npm:0.18.20" @@ -8851,6 +8926,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/freebsd-arm64@npm:0.21.5" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/freebsd-x64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/freebsd-x64@npm:0.18.20" @@ -8865,6 +8947,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/freebsd-x64@npm:0.21.5" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/linux-arm64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/linux-arm64@npm:0.18.20" @@ -8879,6 +8968,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-arm64@npm:0.21.5" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/linux-arm@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/linux-arm@npm:0.18.20" @@ -8893,6 +8989,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-arm@npm:0.21.5" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + "@esbuild/linux-ia32@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/linux-ia32@npm:0.18.20" @@ -8907,6 +9010,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ia32@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-ia32@npm:0.21.5" + conditions: os=linux & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/linux-loong64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/linux-loong64@npm:0.18.20" @@ -8921,6 +9031,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-loong64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-loong64@npm:0.21.5" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + "@esbuild/linux-mips64el@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/linux-mips64el@npm:0.18.20" @@ -8935,6 +9052,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-mips64el@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-mips64el@npm:0.21.5" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + "@esbuild/linux-ppc64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/linux-ppc64@npm:0.18.20" @@ -8949,6 +9073,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ppc64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-ppc64@npm:0.21.5" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/linux-riscv64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/linux-riscv64@npm:0.18.20" @@ -8963,6 +9094,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-riscv64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-riscv64@npm:0.21.5" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + "@esbuild/linux-s390x@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/linux-s390x@npm:0.18.20" @@ -8977,6 +9115,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-s390x@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-s390x@npm:0.21.5" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + "@esbuild/linux-x64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/linux-x64@npm:0.18.20" @@ -8991,6 +9136,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-x64@npm:0.21.5" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + "@esbuild/netbsd-x64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/netbsd-x64@npm:0.18.20" @@ -9005,6 +9157,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/netbsd-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/netbsd-x64@npm:0.21.5" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/openbsd-x64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/openbsd-x64@npm:0.18.20" @@ -9019,6 +9178,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/openbsd-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/openbsd-x64@npm:0.21.5" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/sunos-x64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/sunos-x64@npm:0.18.20" @@ -9033,6 +9199,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/sunos-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/sunos-x64@npm:0.21.5" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + "@esbuild/win32-arm64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/win32-arm64@npm:0.18.20" @@ -9047,6 +9220,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/win32-arm64@npm:0.21.5" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/win32-ia32@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/win32-ia32@npm:0.18.20" @@ -9061,6 +9241,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-ia32@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/win32-ia32@npm:0.21.5" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/win32-x64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/win32-x64@npm:0.18.20" @@ -9075,6 +9262,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/win32-x64@npm:0.21.5" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@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" @@ -9319,8 +9513,8 @@ __metadata: linkType: hard "@google-cloud/storage@npm:^7.0.0": - version: 7.10.1 - resolution: "@google-cloud/storage@npm:7.10.1" + version: 7.11.2 + resolution: "@google-cloud/storage@npm:7.11.2" dependencies: "@google-cloud/paginator": ^5.0.0 "@google-cloud/projectify": ^4.0.0 @@ -9328,16 +9522,16 @@ __metadata: abort-controller: ^3.0.0 async-retry: ^1.3.3 duplexify: ^4.1.3 - ent: ^2.2.0 fast-xml-parser: ^4.3.0 gaxios: ^6.0.2 google-auth-library: ^9.6.3 + html-entities: ^2.5.2 mime: ^3.0.0 p-limit: ^3.0.1 retry-request: ^7.0.0 teeny-request: ^9.0.0 uuid: ^8.0.0 - checksum: 0605f8abf67cde98bc48b05c749b569416af821fcc3eb8ed3fac6dc5ade9c1f2f3210404c85e30525260ea4f34785d7436f7684e6eacd083613237669badff25 + checksum: 763cd560245006e11a060fdbd5edff5d6bfe22b0c0b06dfe88af43b7b14458598c00a71c4e1b079e9ab09096d7d262bdc27fa77d76a8969af0765f23c93f8405 languageName: node linkType: hard @@ -10278,14 +10472,14 @@ __metadata: languageName: node linkType: hard -"@jridgewell/gen-mapping@npm:^0.3.0, @jridgewell/gen-mapping@npm:^0.3.2": - version: 0.3.2 - resolution: "@jridgewell/gen-mapping@npm:0.3.2" +"@jridgewell/gen-mapping@npm:^0.3.0, @jridgewell/gen-mapping@npm:^0.3.2, @jridgewell/gen-mapping@npm:^0.3.5": + version: 0.3.5 + resolution: "@jridgewell/gen-mapping@npm:0.3.5" dependencies: - "@jridgewell/set-array": ^1.0.1 + "@jridgewell/set-array": ^1.2.1 "@jridgewell/sourcemap-codec": ^1.4.10 - "@jridgewell/trace-mapping": ^0.3.9 - checksum: 1832707a1c476afebe4d0fbbd4b9434fdb51a4c3e009ab1e9938648e21b7a97049fa6009393bdf05cab7504108413441df26d8a3c12193996e65493a4efb6882 + "@jridgewell/trace-mapping": ^0.3.24 + checksum: ff7a1764ebd76a5e129c8890aa3e2f46045109dabde62b0b6c6a250152227647178ff2069ea234753a690d8f3c4ac8b5e7b267bbee272bffb7f3b0a370ab6e52 languageName: node linkType: hard @@ -10296,10 +10490,10 @@ __metadata: languageName: node linkType: hard -"@jridgewell/set-array@npm:^1.0.1": - version: 1.1.2 - resolution: "@jridgewell/set-array@npm:1.1.2" - checksum: 69a84d5980385f396ff60a175f7177af0b8da4ddb81824cb7016a9ef914eee9806c72b6b65942003c63f7983d4f39a5c6c27185bbca88eb4690b62075602e28e +"@jridgewell/set-array@npm:^1.2.1": + version: 1.2.1 + resolution: "@jridgewell/set-array@npm:1.2.1" + checksum: 832e513a85a588f8ed4f27d1279420d8547743cc37fcad5a5a76fc74bb895b013dfe614d0eed9cb860048e6546b798f8f2652020b4b2ba0561b05caa8c654b10 languageName: node linkType: hard @@ -10330,13 +10524,13 @@ __metadata: languageName: node linkType: hard -"@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.17, @jridgewell/trace-mapping@npm:^0.3.18, @jridgewell/trace-mapping@npm:^0.3.20, @jridgewell/trace-mapping@npm:^0.3.9": - version: 0.3.20 - resolution: "@jridgewell/trace-mapping@npm:0.3.20" +"@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.18, @jridgewell/trace-mapping@npm:^0.3.20, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25, @jridgewell/trace-mapping@npm:^0.3.9": + version: 0.3.25 + resolution: "@jridgewell/trace-mapping@npm:0.3.25" dependencies: "@jridgewell/resolve-uri": ^3.1.0 "@jridgewell/sourcemap-codec": ^1.4.14 - checksum: cd1a7353135f385909468ff0cf20bdd37e59f2ee49a13a966dedf921943e222082c583ade2b579ff6cd0d8faafcb5461f253e1bf2a9f48fec439211fdbe788f5 + checksum: 9d3c40d225e139987b50c48988f8717a54a8c994d8a948ee42e1412e08988761d0754d7d10b803061cc3aebf35f92a5dbbab493bd0e1a9ef9e89a2130e83ba34 languageName: node linkType: hard @@ -10399,36 +10593,36 @@ __metadata: linkType: hard "@kubernetes-models/apimachinery@npm:^1.1.0, @kubernetes-models/apimachinery@npm:^1.2.1": - version: 1.2.1 - resolution: "@kubernetes-models/apimachinery@npm:1.2.1" + version: 1.2.2 + resolution: "@kubernetes-models/apimachinery@npm:1.2.2" dependencies: - "@kubernetes-models/base": ^4.0.3 - "@kubernetes-models/validate": ^3.1.1 + "@kubernetes-models/base": ^4.0.4 + "@kubernetes-models/validate": ^3.1.2 tslib: ^2.4.0 - checksum: 69145452a2f1b9314aa33326d236e1829905bbdc48727927d065570e2fe95c3895e7117e54f394823c06f5811c7de689f7df1f8010f49d6b89d59241c8704a02 + checksum: 57387bb8a1f43b740506877d2557a188122512dd2f05c54e3076e0d6cf9a2112f7c5cbbba762c8f4fee22845fcf1302b97537a9e24cfd18b6a99d51a1360136a languageName: node linkType: hard -"@kubernetes-models/base@npm:^4.0.1, @kubernetes-models/base@npm:^4.0.3": - version: 4.0.3 - resolution: "@kubernetes-models/base@npm:4.0.3" +"@kubernetes-models/base@npm:^4.0.1, @kubernetes-models/base@npm:^4.0.3, @kubernetes-models/base@npm:^4.0.4": + version: 4.0.4 + resolution: "@kubernetes-models/base@npm:4.0.4" dependencies: - "@kubernetes-models/validate": ^3.1.1 + "@kubernetes-models/validate": ^3.1.2 is-plain-object: ^5.0.0 tslib: ^2.4.0 - checksum: 0f1f333d7e70ba87c322c0bfc9497c4d51e7c7063f0530106daac2e7eac328477df1bf48e255ddf595fb1b49ae0d5214e4f9b5df91d7f67892a0db047d05995f + checksum: 15d531118e8a85eda8fd9602de4ba0e61e794d52218df7acb9842fe3c2fad5e788f3468768e8287405c6228625cce5cb1d91d923499e401a1a0f55287b2e6b5a languageName: node linkType: hard -"@kubernetes-models/validate@npm:^3.1.1": - version: 3.1.1 - resolution: "@kubernetes-models/validate@npm:3.1.1" +"@kubernetes-models/validate@npm:^3.1.1, @kubernetes-models/validate@npm:^3.1.2": + version: 3.1.2 + resolution: "@kubernetes-models/validate@npm:3.1.2" dependencies: ajv: ^8.12.0 ajv-formats: ^2.1.1 ajv-formats-draft2019: ^1.6.1 tslib: ^2.4.0 - checksum: cb5be259a0b5cead73b98648a69785a5e04c2fa3ce199033604c4551b6c4786435c9e5f926cff2d63f50a6fbd2c0ad1199550cb0cbea781e64673b29c4d85345 + checksum: 44bd7e45aa9716448532f5afc6510398a7eed77c23df67acd94acde4e940c3284a879cc62372fb3dcb67c12d2d10e43900bdd98bc39d1177492c9f2d48b63d4e languageName: node linkType: hard @@ -10941,9 +11135,9 @@ __metadata: languageName: node linkType: hard -"@mswjs/interceptors@npm:^0.26.14": - version: 0.26.15 - resolution: "@mswjs/interceptors@npm:0.26.15" +"@mswjs/interceptors@npm:^0.29.0": + version: 0.29.1 + resolution: "@mswjs/interceptors@npm:0.29.1" dependencies: "@open-draft/deferred-promise": ^2.2.0 "@open-draft/logger": ^0.3.0 @@ -10951,7 +11145,7 @@ __metadata: is-node-process: ^1.2.0 outvariant: ^1.2.1 strict-event-emitter: ^0.5.1 - checksum: 6087ba7049c73af8d0d60344976950ec65c733b73dddcd1ed18b5bd91d013f5f364a09583bb70f8a82558391c125b2e1ff38eb4076f2bdc21d7833134bd4f7dd + checksum: c217f922c68024f6a8b526fb7df00bbfccb71e432bfb270322976dd40a9d312698e40bfd105b74df7aeb5a46276531a56ca5b8e3e9b0112f1577eb0d8d289e1f languageName: node linkType: hard @@ -11151,15 +11345,14 @@ __metadata: languageName: node linkType: hard -"@nestjs/axios@npm:3.0.1": - version: 3.0.1 - resolution: "@nestjs/axios@npm:3.0.1" +"@nestjs/axios@npm:3.0.2": + version: 3.0.2 + resolution: "@nestjs/axios@npm:3.0.2" peerDependencies: "@nestjs/common": ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 axios: ^1.3.1 - reflect-metadata: ^0.1.12 rxjs: ^6.0.0 || ^7.0.0 - checksum: 01cebc64efa7a1d9df7a9053fbc5124986a95078789a0f280a2a61c31601a70a35745e07fc385497b4f85c7bdb6216a3575728646f1e6e684c038ac31900129c + checksum: 285a735fb5db602b63aa4a37e161f609b2cec05b69f4bffe983617c2136ac29c0a33bb96e6276d22a656907bed5d53460e740310bc05c043dcd39c37db7cda29 languageName: node linkType: hard @@ -11399,22 +11592,6 @@ __metadata: languageName: node linkType: hard -"@npmcli/git@npm:^5.0.0": - version: 5.0.4 - resolution: "@npmcli/git@npm:5.0.4" - dependencies: - "@npmcli/promise-spawn": ^7.0.0 - lru-cache: ^10.0.1 - npm-pick-manifest: ^9.0.0 - proc-log: ^3.0.0 - promise-inflight: ^1.0.1 - promise-retry: ^2.0.1 - semver: ^7.3.5 - which: ^4.0.0 - checksum: 3c4adb7294eb7562cb0d908f36e1967ae6bde438192affd7f103cdeebbd9b2d83cd6b41b7db2278c9acd934c4af138baa094544e8e8a530b515c4084438d0170 - languageName: node - linkType: hard - "@npmcli/installed-package-contents@npm:^1.0.6, @npmcli/installed-package-contents@npm:^1.0.7": version: 1.0.7 resolution: "@npmcli/installed-package-contents@npm:1.0.7" @@ -11439,18 +11616,6 @@ __metadata: languageName: node linkType: hard -"@npmcli/map-workspaces@npm:^3.0.4": - version: 3.0.6 - resolution: "@npmcli/map-workspaces@npm:3.0.6" - dependencies: - "@npmcli/name-from-folder": ^2.0.0 - glob: ^10.2.2 - minimatch: ^9.0.0 - read-package-json-fast: ^3.0.0 - checksum: bdb09ee1d044bb9b2857d9e2d7ca82f40783a8549b5a7e150e25f874ee354cdbc8109ad7c3df42ec412f7057d95baa05920c4d361c868a93a42146b8e4390d3d - languageName: node - linkType: hard - "@npmcli/metavuln-calculator@npm:^2.0.0": version: 2.0.0 resolution: "@npmcli/metavuln-calculator@npm:2.0.0" @@ -11490,13 +11655,6 @@ __metadata: languageName: node linkType: hard -"@npmcli/name-from-folder@npm:^2.0.0": - version: 2.0.0 - resolution: "@npmcli/name-from-folder@npm:2.0.0" - checksum: fb3ef891aa57315fb6171866847f298577c8bda98a028e93e458048477133e142b4eb45ce9f3b80454f7c257612cb01754ee782d608507698dd712164436f5bd - languageName: node - linkType: hard - "@npmcli/node-gyp@npm:^1.0.2, @npmcli/node-gyp@npm:^1.0.3": version: 1.0.3 resolution: "@npmcli/node-gyp@npm:1.0.3" @@ -11513,21 +11671,6 @@ __metadata: languageName: node linkType: hard -"@npmcli/package-json@npm:^5.0.0": - version: 5.0.2 - resolution: "@npmcli/package-json@npm:5.0.2" - dependencies: - "@npmcli/git": ^5.0.0 - glob: ^10.2.2 - hosted-git-info: ^7.0.0 - json-parse-even-better-errors: ^3.0.0 - normalize-package-data: ^6.0.0 - proc-log: ^3.0.0 - semver: ^7.5.3 - checksum: f0e69d093a5733c7d31ce45098e2ce059f01d09b79329a7f3e975baf91d87f4bf3171fadc27442f4f540dc546954259f178be40ca632b87cfe16bcfe04f00dd3 - languageName: node - linkType: hard - "@npmcli/promise-spawn@npm:^1.2.0, @npmcli/promise-spawn@npm:^1.3.2": version: 1.3.2 resolution: "@npmcli/promise-spawn@npm:1.3.2" @@ -11537,15 +11680,6 @@ __metadata: languageName: node linkType: hard -"@npmcli/promise-spawn@npm:^7.0.0": - version: 7.0.1 - resolution: "@npmcli/promise-spawn@npm:7.0.1" - dependencies: - which: ^4.0.0 - checksum: a2b25d66d4dc835c69593bdf56588d66299fde3e80be4978347e686f24647007b794ce4da4cfcfcc569c67112720b746c4e7bf18ce45c096712d8b75fed19ec7 - languageName: node - linkType: hard - "@npmcli/run-script@npm:^2.0.0": version: 2.0.0 resolution: "@npmcli/run-script@npm:2.0.0" @@ -12291,14 +12425,14 @@ __metadata: linkType: hard "@openapitools/openapi-generator-cli@npm:^2.4.26, @openapitools/openapi-generator-cli@npm:^2.7.0": - version: 2.13.2 - resolution: "@openapitools/openapi-generator-cli@npm:2.13.2" + version: 2.13.4 + resolution: "@openapitools/openapi-generator-cli@npm:2.13.4" dependencies: - "@nestjs/axios": 3.0.1 + "@nestjs/axios": 3.0.2 "@nestjs/common": 10.3.0 "@nestjs/core": 10.3.0 "@nuxtjs/opencollective": 0.3.2 - axios: 1.6.5 + axios: 1.6.8 chalk: 4.1.2 commander: 8.3.0 compare-versions: 4.1.4 @@ -12314,7 +12448,7 @@ __metadata: tslib: 2.6.2 bin: openapi-generator-cli: main.js - checksum: 553458ffface4090f117ec488352f664bb4656b645ef51faf5be35f27e739ac5c8931adf401309dfa0aad7ceefa39fb267d452b72d7a22f0fdb26d988d73b642 + checksum: 825a49ff86632767d318fa860d9d251984b9b3e8f386cf8298430005f20611d7b535c6e87e370edd19ff824a5c68cf65efc93cbb64d7a2f1649e46a8887cf5d2 languageName: node linkType: hard @@ -13602,13 +13736,13 @@ __metadata: linkType: hard "@playwright/test@npm:^1.32.3": - version: 1.43.1 - resolution: "@playwright/test@npm:1.43.1" + version: 1.44.1 + resolution: "@playwright/test@npm:1.44.1" dependencies: - playwright: 1.43.1 + playwright: 1.44.1 bin: playwright: cli.js - checksum: f9db387b488a03125e5dc22dd7ffed9c661d1f2428188912a35a2235b3bd9d826b390e7600d04998639994f5a96695b9dc9034ca9cb59e261d2fdee93a60df3f + checksum: 90507b77e388aa984deb92db56f7bb3b305c6be441e1d0087ca046989cfdda068bbc26d75bd29c20ad3dbb2434e69a8ff0d6b30003b88c9234cd3aa6a9f7deb9 languageName: node linkType: hard @@ -13649,141 +13783,6 @@ __metadata: languageName: node linkType: hard -"@pnpm/constants@npm:7.1.1": - version: 7.1.1 - resolution: "@pnpm/constants@npm:7.1.1" - checksum: a8b6a8c633ba2099ee844a3dd7934352a2135872e86f8fe497d599837b8be7eac374839598b70030e63cb3a32f945e881d6c0e1542f0be2b74ec52d78f891649 - languageName: node - linkType: hard - -"@pnpm/core-loggers@npm:9.0.6": - version: 9.0.6 - resolution: "@pnpm/core-loggers@npm:9.0.6" - dependencies: - "@pnpm/types": 9.4.2 - peerDependencies: - "@pnpm/logger": ^5.0.0 - checksum: ab0656839c873f5954109d540ca2a7b144626036c7f78ef4a7717e755449f9c7acda3a425b83ebc1349ad5ce295f2b6e9b133be14294b11c5df6a0f8b4feaea1 - languageName: node - linkType: hard - -"@pnpm/error@npm:5.0.2": - version: 5.0.2 - resolution: "@pnpm/error@npm:5.0.2" - dependencies: - "@pnpm/constants": 7.1.1 - checksum: 490e90b3a6fa6527a5a2b07dfd46982e005d8834036871a30cf03fcb389497b9828ed01c0d39e88b6352a340556de316eae9dbefcb3246f368815a03241576e6 - languageName: node - linkType: hard - -"@pnpm/fetching-types@npm:5.0.0": - version: 5.0.0 - resolution: "@pnpm/fetching-types@npm:5.0.0" - dependencies: - "@zkochan/retry": ^0.2.0 - node-fetch: 3.0.0-beta.9 - checksum: 845c1597be6246f484477c3badce5573a1ab35c741f59e297813faf195d07e4c03ca871beb10d614a987a4dff78bd72265c0bd56c40cbf941e416b1f3ea6231c - languageName: node - linkType: hard - -"@pnpm/graceful-fs@npm:3.2.0": - version: 3.2.0 - resolution: "@pnpm/graceful-fs@npm:3.2.0" - dependencies: - graceful-fs: ^4.2.11 - checksum: b31bad77530101d27044d2d712ecf09684398cc72311fbb079675f393219fff002a9ab8e3ea91014e79f1586a861a100ac9b4881d72156383aca6e85cf9855be - languageName: node - linkType: hard - -"@pnpm/logger@npm:5.0.0": - version: 5.0.0 - resolution: "@pnpm/logger@npm:5.0.0" - dependencies: - bole: ^5.0.0 - ndjson: ^2.0.0 - checksum: 6ea91cb3a539351371147b6f051489a01630538327bb3773105e91b9b35ec689b6fc1d112d484726deffe6953b738318e1a86205362baf9fb49fad27084b8f74 - languageName: node - linkType: hard - -"@pnpm/npm-package-arg@npm:^1.0.0": - version: 1.0.0 - resolution: "@pnpm/npm-package-arg@npm:1.0.0" - dependencies: - hosted-git-info: ^4.0.1 - semver: ^7.3.5 - validate-npm-package-name: ^4.0.0 - checksum: e3dbcb605b6c86e0d29854aab00af086fd922211c9c2ed4f4923a70947c10d563b5e9adc8441d7ec0a23d074edb9cd1f0c334b506c4ecc549b07b60700f3639a - languageName: node - linkType: hard - -"@pnpm/npm-resolver@npm:18.1.0": - version: 18.1.0 - resolution: "@pnpm/npm-resolver@npm:18.1.0" - dependencies: - "@pnpm/core-loggers": 9.0.6 - "@pnpm/error": 5.0.2 - "@pnpm/fetching-types": 5.0.0 - "@pnpm/graceful-fs": 3.2.0 - "@pnpm/resolve-workspace-range": 5.0.1 - "@pnpm/resolver-base": 11.1.0 - "@pnpm/types": 9.4.2 - "@zkochan/retry": ^0.2.0 - encode-registry: ^3.0.1 - load-json-file: ^6.2.0 - lru-cache: ^10.0.2 - normalize-path: ^3.0.0 - p-limit: ^3.1.0 - p-memoize: 4.0.1 - parse-npm-tarball-url: ^3.0.0 - path-temp: ^2.1.0 - ramda: "npm:@pnpm/ramda@0.28.1" - rename-overwrite: ^5.0.0 - semver: ^7.5.4 - ssri: 10.0.5 - version-selector-type: ^3.0.0 - peerDependencies: - "@pnpm/logger": ^5.0.0 - checksum: 81b0dd97a0062374db7aecd68a94e7e52dd19c9675bd052c7fa7a2b5edb6219dc525e71dccb70bf4bae90faf44f6e1cd0d4f155606bc754ffcec4f9ab6852c08 - languageName: node - linkType: hard - -"@pnpm/resolve-workspace-range@npm:5.0.1": - version: 5.0.1 - resolution: "@pnpm/resolve-workspace-range@npm:5.0.1" - dependencies: - semver: ^7.4.0 - checksum: 4c6a853b1f6d8030e5458d1d88891932e209ed35daa3032919802e6005a4beca5fa31ffd2769be1353a9f0367971afebd51493ab187ac675a73a35640a82aaa1 - languageName: node - linkType: hard - -"@pnpm/resolver-base@npm:11.1.0": - version: 11.1.0 - resolution: "@pnpm/resolver-base@npm:11.1.0" - dependencies: - "@pnpm/types": 9.4.2 - checksum: ff42d6f1bd3cfef46ab644709de13795af682c04575d782ec8cf32ef4b114486f22f3d758b1d94423ee8969fbb786a81d3a7b6fa52054af8e403b19f15a40b3f - languageName: node - linkType: hard - -"@pnpm/types@npm:9.4.2": - version: 9.4.2 - resolution: "@pnpm/types@npm:9.4.2" - checksum: a499e5442c53c38820730e626eb75b67305c838d486e2544527a1dd7bc2666ac75e91db8bc8b6ee7776927593297339468e212d239f27b0d0520ee972ab8b0b9 - languageName: node - linkType: hard - -"@pnpm/workspace.pkgs-graph@npm:2.0.14": - version: 2.0.14 - resolution: "@pnpm/workspace.pkgs-graph@npm:2.0.14" - dependencies: - "@pnpm/npm-package-arg": ^1.0.0 - "@pnpm/npm-resolver": 18.1.0 - "@pnpm/resolve-workspace-range": 5.0.1 - ramda: "npm:@pnpm/ramda@0.28.1" - checksum: ff3b5234611da1ec4b636616554abcb4720c4fcd3db33bcb7b4b1e4ed5ebd091a854163876c1b1f7d56d2ec6e4f344c22eaf02054f2963d9a50a49462412793d - languageName: node - linkType: hard - "@popperjs/core@npm:^2.11.8": version: 2.11.8 resolution: "@popperjs/core@npm:2.11.8" @@ -14482,9 +14481,9 @@ __metadata: languageName: node linkType: hard -"@rjsf/core@npm:5.18.2": - version: 5.18.2 - resolution: "@rjsf/core@npm:5.18.2" +"@rjsf/core@npm:5.18.4": + version: 5.18.4 + resolution: "@rjsf/core@npm:5.18.4" dependencies: lodash: ^4.17.21 lodash-es: ^4.17.21 @@ -14494,26 +14493,26 @@ __metadata: peerDependencies: "@rjsf/utils": ^5.18.x react: ^16.14.0 || >=17 - checksum: b8b20bd75090b15b19e176aa766c037f3a7f1a27dbbde07ab095376a85e0027fd441b6e37355c8d3b389393db1f1b27699769034146040864c63a8f110d5e2d7 + checksum: 8c3f49914be396595ce67dc4c36ac25c5cb6673917ec82c47f79321f5bb78d02741e8dca39287d0435270e7c9ccb06f7d40e396bdf71a3e9eb1371ef16954817 languageName: node linkType: hard -"@rjsf/material-ui@npm:5.18.2": - version: 5.18.2 - resolution: "@rjsf/material-ui@npm:5.18.2" +"@rjsf/material-ui@npm:5.18.4": + version: 5.18.4 + resolution: "@rjsf/material-ui@npm:5.18.4" peerDependencies: "@material-ui/core": ^4.12.3 "@material-ui/icons": ^4.11.2 "@rjsf/core": ^5.18.x "@rjsf/utils": ^5.18.x react: ^16.14.0 || >=17 - checksum: fc898efa7834e32c59e9f607c8650e39689252c6bc7e84f081ab131c90b92c28787288c647b81841b2cfab40231660324b8cc35bf7d05649f31bf70e207d4a7e + checksum: 2bb0eeb0603bd11b034785ac1902cfcf3630cb4d04161728adff86b2629ca4d21bbb42beb9e6acdd4c9a6a4d84cce1ca325413a9bd1fd94eda47f58d62eb3164 languageName: node linkType: hard -"@rjsf/utils@npm:5.18.2": - version: 5.18.2 - resolution: "@rjsf/utils@npm:5.18.2" +"@rjsf/utils@npm:5.18.4": + version: 5.18.4 + resolution: "@rjsf/utils@npm:5.18.4" dependencies: json-schema-merge-allof: ^0.8.1 jsonpointer: ^5.0.1 @@ -14522,13 +14521,13 @@ __metadata: react-is: ^18.2.0 peerDependencies: react: ^16.14.0 || >=17 - checksum: 19342ce160f5f2ff1b1448bc61b0767c9b19a3c365fe3dca221c9178dff6b54123bdfe9dd4b0314aa7965011edb0e76029f7e76226936066bfacbaaa619546b4 + checksum: d7cf514527ec50a94751c5ec1f9e5eafd89d0c56441a22ae28a4e667aaa7c60447e1e1ccf8355c5be5b97e9a1163853c116816b13307e3463433d50f6b89bb3e languageName: node linkType: hard -"@rjsf/validator-ajv8@npm:5.18.2": - version: 5.18.2 - resolution: "@rjsf/validator-ajv8@npm:5.18.2" +"@rjsf/validator-ajv8@npm:5.18.4": + version: 5.18.4 + resolution: "@rjsf/validator-ajv8@npm:5.18.4" dependencies: ajv: ^8.12.0 ajv-formats: ^2.1.1 @@ -14536,7 +14535,7 @@ __metadata: lodash-es: ^4.17.21 peerDependencies: "@rjsf/utils": ^5.18.x - checksum: 0ed953615b0619a376edfa95ccb891f1aa701e1915a09de562fb1c13a69a4902887359dcf68597f78ffc0a9be9c402c1488ef8ae552be8c8f48aeb7d59d3eae3 + checksum: edf3b24e07babe972e57645d396467c6404ff3f95a79118667f2d62082aa28e4ee7df5fad81e28071cd24b5455fe687a9f9bcf714718d4fd6036912b04c69a84 languageName: node linkType: hard @@ -16083,453 +16082,453 @@ __metadata: languageName: node linkType: hard -"@swagger-api/apidom-ast@npm:^0.99.1": - version: 0.99.1 - resolution: "@swagger-api/apidom-ast@npm:0.99.1" +"@swagger-api/apidom-ast@npm:^1.0.0-alpha.5": + version: 1.0.0-alpha.5 + resolution: "@swagger-api/apidom-ast@npm:1.0.0-alpha.5" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-error": ^0.99.0 - "@types/ramda": ~0.29.6 - ramda: ~0.29.1 - ramda-adjunct: ^4.1.1 + "@swagger-api/apidom-error": ^1.0.0-alpha.5 + "@types/ramda": ~0.30.0 + ramda: ~0.30.0 + ramda-adjunct: ^5.0.0 unraw: ^3.0.0 - checksum: 48288eb46edb03040e9afec47762d826d8c343ee6a3216d54d65f21ad3e62daade6c8edf228d1ab9bff8f23163841f9ce8170951cf211bf1a2c08e52137293b0 + checksum: c56354ed83a10f8f1770e93b7b284108440ec77dd7b79c63bccc6109ea8734a48b86c582676fb40e27995e231e821192eecf9893fea4c8c24568655e11f95ad6 languageName: node linkType: hard -"@swagger-api/apidom-core@npm:>=0.99.1 <1.0.0, @swagger-api/apidom-core@npm:^0.99.1": - version: 0.99.1 - resolution: "@swagger-api/apidom-core@npm:0.99.1" +"@swagger-api/apidom-core@npm:>=1.0.0-alpha.5 <1.0.0-beta.0, @swagger-api/apidom-core@npm:^1.0.0-alpha.5": + version: 1.0.0-alpha.5 + resolution: "@swagger-api/apidom-core@npm:1.0.0-alpha.5" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-ast": ^0.99.1 - "@swagger-api/apidom-error": ^0.99.0 - "@types/ramda": ~0.29.6 + "@swagger-api/apidom-ast": ^1.0.0-alpha.5 + "@swagger-api/apidom-error": ^1.0.0-alpha.5 + "@types/ramda": ~0.30.0 minim: ~0.23.8 - ramda: ~0.29.1 - ramda-adjunct: ^4.1.1 + ramda: ~0.30.0 + ramda-adjunct: ^5.0.0 short-unique-id: ^5.0.2 - stampit: ^4.3.2 - checksum: f4313d6971e65feeaa6581a82dc3e720af87358e470c6dde0d11d8ae5b7d251cc430a2f70a88eebd251dd6c454a5708b61b9daf9f5d00fcbb1ce9d280874d5cc - languageName: node - linkType: hard - -"@swagger-api/apidom-error@npm:>=0.99.0 <1.0.0, @swagger-api/apidom-error@npm:^0.99.0": - version: 0.99.0 - resolution: "@swagger-api/apidom-error@npm:0.99.0" - dependencies: - "@babel/runtime-corejs3": ^7.20.7 - checksum: 06d3da38ff9501376d2de3240d1a5023110482e053766c389f734a587dfd4c10b6ba695268edc58ce649284fd8e04a1f57484ae49dba210dcc5764df33fd52a0 - languageName: node - linkType: hard - -"@swagger-api/apidom-json-pointer@npm:>=0.99.1 <1.0.0, @swagger-api/apidom-json-pointer@npm:^0.99.1": - version: 0.99.1 - resolution: "@swagger-api/apidom-json-pointer@npm:0.99.1" - dependencies: - "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.99.1 - "@swagger-api/apidom-error": ^0.99.0 - "@types/ramda": ~0.29.6 - ramda: ~0.29.1 - ramda-adjunct: ^4.0.0 - checksum: d566f7410d3600766f7130a23da811b4c7a3a1542ab173f2b0b6578b01dcb531c61d1d43da5e944ef1d4059c47b6f472ee3ad55da625e672c1c1dd7315941689 - languageName: node - linkType: hard - -"@swagger-api/apidom-ns-api-design-systems@npm:^0.99.1": - version: 0.99.1 - resolution: "@swagger-api/apidom-ns-api-design-systems@npm:0.99.1" - dependencies: - "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.99.1 - "@swagger-api/apidom-error": ^0.99.0 - "@swagger-api/apidom-ns-openapi-3-1": ^0.99.1 - "@types/ramda": ~0.29.6 - ramda: ~0.29.1 - ramda-adjunct: ^4.1.1 ts-mixer: ^6.0.3 - checksum: 22ce1af89437b104005158ded9b8237511f1d6dae9f564fb1c336e6f842898fde9dca8549aa94dc0724c03df51b4a33b7e081f79b5c44e68ab625d76a4589d47 + checksum: 57e7fac92e6e0d636de2b964488491cfe6ebdafeed22b75a67e668477c0ab642364e2d1cd6ae7e9d4fc334b4f45b5e205ff9c0c9f09d20297ad200d2bc740c22 languageName: node linkType: hard -"@swagger-api/apidom-ns-asyncapi-2@npm:^0.99.1": - version: 0.99.1 - resolution: "@swagger-api/apidom-ns-asyncapi-2@npm:0.99.1" +"@swagger-api/apidom-error@npm:>=1.0.0-alpha.5 <1.0.0-beta.0, @swagger-api/apidom-error@npm:^1.0.0-alpha.1, @swagger-api/apidom-error@npm:^1.0.0-alpha.5": + version: 1.0.0-alpha.5 + resolution: "@swagger-api/apidom-error@npm:1.0.0-alpha.5" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.99.1 - "@swagger-api/apidom-ns-json-schema-draft-7": ^0.99.1 - "@types/ramda": ~0.29.6 - ramda: ~0.29.1 - ramda-adjunct: ^4.1.1 + checksum: c1a710786c0553a37aa7fbec5d233a86978a77fa91879cd7186139d939096d4ee15e8eb02ea8886e201d7c2a0602a699c0cb5ec8ef8f04da30841d5018edb489 + languageName: node + linkType: hard + +"@swagger-api/apidom-json-pointer@npm:>=1.0.0-alpha.5 <1.0.0-beta.0, @swagger-api/apidom-json-pointer@npm:^1.0.0-alpha.1, @swagger-api/apidom-json-pointer@npm:^1.0.0-alpha.5": + version: 1.0.0-alpha.5 + resolution: "@swagger-api/apidom-json-pointer@npm:1.0.0-alpha.5" + dependencies: + "@babel/runtime-corejs3": ^7.20.7 + "@swagger-api/apidom-core": ^1.0.0-alpha.5 + "@swagger-api/apidom-error": ^1.0.0-alpha.5 + "@types/ramda": ~0.30.0 + ramda: ~0.30.0 + ramda-adjunct: ^5.0.0 + checksum: dc2a5215c9d7978a4b24f04fedcd9a95d0e043b6ef333e96aee0072071e4b2ed3ffcf1969bdfa07573916f968743f92124a315ab9cc75d26f0e8c9279b2ba9d9 + languageName: node + linkType: hard + +"@swagger-api/apidom-ns-api-design-systems@npm:^1.0.0-alpha.5": + version: 1.0.0-alpha.5 + resolution: "@swagger-api/apidom-ns-api-design-systems@npm:1.0.0-alpha.5" + dependencies: + "@babel/runtime-corejs3": ^7.20.7 + "@swagger-api/apidom-core": ^1.0.0-alpha.5 + "@swagger-api/apidom-error": ^1.0.0-alpha.5 + "@swagger-api/apidom-ns-openapi-3-1": ^1.0.0-alpha.5 + "@types/ramda": ~0.30.0 + ramda: ~0.30.0 + ramda-adjunct: ^5.0.0 ts-mixer: ^6.0.3 - checksum: d1759ca24f238ae833a34128e8672f972f8cca61ddbd9660e277bc8ad3d78b835e1b7406a97e8eed4946e526ce7ec8ed1debd79edaaf504fae86c92534cb0875 + checksum: 8f90e1c432723779b6a8e7cda18cc7b779744b970d1c2eebf13d413b291fec12c08125d6b03895c8423a17f7c4e53a1b22c0364af7c80b4f947589408a92d9ee languageName: node linkType: hard -"@swagger-api/apidom-ns-json-schema-draft-4@npm:^0.99.1": - version: 0.99.1 - resolution: "@swagger-api/apidom-ns-json-schema-draft-4@npm:0.99.1" +"@swagger-api/apidom-ns-asyncapi-2@npm:^1.0.0-alpha.1, @swagger-api/apidom-ns-asyncapi-2@npm:^1.0.0-alpha.5": + version: 1.0.0-alpha.5 + resolution: "@swagger-api/apidom-ns-asyncapi-2@npm:1.0.0-alpha.5" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-ast": ^0.99.1 - "@swagger-api/apidom-core": ^0.99.1 - "@types/ramda": ~0.29.6 - ramda: ~0.29.1 - ramda-adjunct: ^4.1.1 - stampit: ^4.3.2 - checksum: 1b6c034e94287de0bea11a5f1c62de7b833436918cf961f38a12d877cf6de3caf3080fd38f0244905ea3b2fe8bb178a26c29ec631b4638ac46b597b992c7640a - languageName: node - linkType: hard - -"@swagger-api/apidom-ns-json-schema-draft-6@npm:^0.99.1": - version: 0.99.1 - resolution: "@swagger-api/apidom-ns-json-schema-draft-6@npm:0.99.1" - dependencies: - "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.99.1 - "@swagger-api/apidom-error": ^0.99.0 - "@swagger-api/apidom-ns-json-schema-draft-4": ^0.99.1 - "@types/ramda": ~0.29.6 - ramda: ~0.29.1 - ramda-adjunct: ^4.1.1 - stampit: ^4.3.2 - checksum: e521ac3aec57f4239cce89641c7dc3555b2986ef23c6e9a15462d0b3015e54d89b0802546c313f5a91a2e5f94c8c570c417fe22034da57049bf49c61fc4e3592 - languageName: node - linkType: hard - -"@swagger-api/apidom-ns-json-schema-draft-7@npm:^0.99.1": - version: 0.99.1 - resolution: "@swagger-api/apidom-ns-json-schema-draft-7@npm:0.99.1" - dependencies: - "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.99.1 - "@swagger-api/apidom-error": ^0.99.0 - "@swagger-api/apidom-ns-json-schema-draft-6": ^0.99.1 - "@types/ramda": ~0.29.6 - ramda: ~0.29.1 - ramda-adjunct: ^4.1.1 - stampit: ^4.3.2 - checksum: 791df6981518d239fdee2ae76bd9abf2542322e36785d2153fe2d4dcc1e6b2fdbb430ac9becb55734fc7968f77570895d5c9113f5aa59f0cc3c59ed3ed604b41 - languageName: node - linkType: hard - -"@swagger-api/apidom-ns-openapi-2@npm:^0.99.1": - version: 0.99.1 - resolution: "@swagger-api/apidom-ns-openapi-2@npm:0.99.1" - dependencies: - "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.99.1 - "@swagger-api/apidom-error": ^0.99.0 - "@swagger-api/apidom-ns-json-schema-draft-4": ^0.99.1 - "@types/ramda": ~0.29.6 - ramda: ~0.29.1 - ramda-adjunct: ^4.1.1 + "@swagger-api/apidom-core": ^1.0.0-alpha.5 + "@swagger-api/apidom-ns-json-schema-draft-7": ^1.0.0-alpha.5 + "@types/ramda": ~0.30.0 + ramda: ~0.30.0 + ramda-adjunct: ^5.0.0 ts-mixer: ^6.0.3 - checksum: 8222aaffa9d1472ca2f876a361bbb888bc39b888d4600d9bd06ada7d9b516104391fbba9f51305ea0f522d0ae44370134631fc9492461483fad3cf757fa70b75 + checksum: 74c99ed370ce93675d2987be5956daae9a8f6e360af9eb3d28b8df44063f50e23741356195fdccd9b7da233ab2498e76833626ca37ad129a9bd0be059b66ff20 languageName: node linkType: hard -"@swagger-api/apidom-ns-openapi-3-0@npm:^0.99.1": - version: 0.99.1 - resolution: "@swagger-api/apidom-ns-openapi-3-0@npm:0.99.1" +"@swagger-api/apidom-ns-json-schema-draft-4@npm:^1.0.0-alpha.5": + version: 1.0.0-alpha.5 + resolution: "@swagger-api/apidom-ns-json-schema-draft-4@npm:1.0.0-alpha.5" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.99.1 - "@swagger-api/apidom-error": ^0.99.0 - "@swagger-api/apidom-ns-json-schema-draft-4": ^0.99.1 - "@types/ramda": ~0.29.6 - ramda: ~0.29.1 - ramda-adjunct: ^4.1.1 + "@swagger-api/apidom-ast": ^1.0.0-alpha.5 + "@swagger-api/apidom-core": ^1.0.0-alpha.5 + "@types/ramda": ~0.30.0 + ramda: ~0.30.0 + ramda-adjunct: ^5.0.0 + ts-mixer: ^6.0.4 + checksum: f9bd2dfc9f17ffbcdd97502a2bfb2ae4da93382b09a93d145a463f73bb73f0d45d8333aa3cea5b5ec7f3cbc41764b70ff9d90b60e1ed1ff5c009573734e7a2f6 + languageName: node + linkType: hard + +"@swagger-api/apidom-ns-json-schema-draft-6@npm:^1.0.0-alpha.5": + version: 1.0.0-alpha.5 + resolution: "@swagger-api/apidom-ns-json-schema-draft-6@npm:1.0.0-alpha.5" + dependencies: + "@babel/runtime-corejs3": ^7.20.7 + "@swagger-api/apidom-core": ^1.0.0-alpha.5 + "@swagger-api/apidom-error": ^1.0.0-alpha.5 + "@swagger-api/apidom-ns-json-schema-draft-4": ^1.0.0-alpha.5 + "@types/ramda": ~0.30.0 + ramda: ~0.30.0 + ramda-adjunct: ^5.0.0 + ts-mixer: ^6.0.4 + checksum: 4830854843eaeff10ed06d687f7cf844ffa74df86dbb65812c34cd1ba56614e07602be0bd8edb372b286f24ca2228ebfe04f2b86728fc86207eb6762d2a73cd8 + languageName: node + linkType: hard + +"@swagger-api/apidom-ns-json-schema-draft-7@npm:^1.0.0-alpha.5": + version: 1.0.0-alpha.5 + resolution: "@swagger-api/apidom-ns-json-schema-draft-7@npm:1.0.0-alpha.5" + dependencies: + "@babel/runtime-corejs3": ^7.20.7 + "@swagger-api/apidom-core": ^1.0.0-alpha.5 + "@swagger-api/apidom-error": ^1.0.0-alpha.5 + "@swagger-api/apidom-ns-json-schema-draft-6": ^1.0.0-alpha.5 + "@types/ramda": ~0.30.0 + ramda: ~0.30.0 + ramda-adjunct: ^5.0.0 + ts-mixer: ^6.0.4 + checksum: fb05b7cc0c451f7dac94f5ea306df91b53d8c3c595f8a92fe7130b6e03039a7e622c26a7659050243c9dd3f549b63aa69d7cd49c8b36e51539dfff96c8d7b98b + languageName: node + linkType: hard + +"@swagger-api/apidom-ns-openapi-2@npm:^1.0.0-alpha.1, @swagger-api/apidom-ns-openapi-2@npm:^1.0.0-alpha.5": + version: 1.0.0-alpha.5 + resolution: "@swagger-api/apidom-ns-openapi-2@npm:1.0.0-alpha.5" + dependencies: + "@babel/runtime-corejs3": ^7.20.7 + "@swagger-api/apidom-core": ^1.0.0-alpha.5 + "@swagger-api/apidom-error": ^1.0.0-alpha.5 + "@swagger-api/apidom-ns-json-schema-draft-4": ^1.0.0-alpha.5 + "@types/ramda": ~0.30.0 + ramda: ~0.30.0 + ramda-adjunct: ^5.0.0 ts-mixer: ^6.0.3 - checksum: 8b5150e317e79795bc73a4a0c53860de4ab50e9e8fd9895d21d4a204e6ecee626477107e06df51aaef0e3651fdb2e48f197b5c8a0c33464b38d74abdffda0b60 + checksum: 46bd04283494af26f64baf693493724b7799cc3c312d1e6899f28197c3eeb36eb7344566d1dbb3640a4284757aa21b9e206c7efe23b00920154a870365d818c1 languageName: node linkType: hard -"@swagger-api/apidom-ns-openapi-3-1@npm:>=0.99.1 <1.0.0, @swagger-api/apidom-ns-openapi-3-1@npm:^0.99.1": - version: 0.99.1 - resolution: "@swagger-api/apidom-ns-openapi-3-1@npm:0.99.1" +"@swagger-api/apidom-ns-openapi-3-0@npm:^1.0.0-alpha.1, @swagger-api/apidom-ns-openapi-3-0@npm:^1.0.0-alpha.5": + version: 1.0.0-alpha.5 + resolution: "@swagger-api/apidom-ns-openapi-3-0@npm:1.0.0-alpha.5" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-ast": ^0.99.1 - "@swagger-api/apidom-core": ^0.99.1 - "@swagger-api/apidom-ns-openapi-3-0": ^0.99.1 - "@types/ramda": ~0.29.6 - ramda: ~0.29.1 - ramda-adjunct: ^4.1.1 + "@swagger-api/apidom-core": ^1.0.0-alpha.5 + "@swagger-api/apidom-error": ^1.0.0-alpha.5 + "@swagger-api/apidom-ns-json-schema-draft-4": ^1.0.0-alpha.5 + "@types/ramda": ~0.30.0 + ramda: ~0.30.0 + ramda-adjunct: ^5.0.0 ts-mixer: ^6.0.3 - checksum: 64d97f6569c68982af5e2933e52060a5b404a270ad45689209f57e049776a4d3e2062f89474eb26a2689bc08014a6d69d45c6d48c496e67b2664e7bf80356232 + checksum: adcb1aa410800d6205460ce421cf8d70f171886a8812a04062a0d6af28a434394e0a1f5d10a02a89677f59a2323c7843ee34cbf022b9979c1d3ca07685b87916 languageName: node linkType: hard -"@swagger-api/apidom-ns-workflows-1@npm:^0.99.1": - version: 0.99.1 - resolution: "@swagger-api/apidom-ns-workflows-1@npm:0.99.1" +"@swagger-api/apidom-ns-openapi-3-1@npm:>=1.0.0-alpha.5 <1.0.0-beta.0, @swagger-api/apidom-ns-openapi-3-1@npm:^1.0.0-alpha.1, @swagger-api/apidom-ns-openapi-3-1@npm:^1.0.0-alpha.5": + version: 1.0.0-alpha.5 + resolution: "@swagger-api/apidom-ns-openapi-3-1@npm:1.0.0-alpha.5" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.99.1 - "@swagger-api/apidom-ns-openapi-3-1": ^0.99.1 - "@types/ramda": ~0.29.6 - ramda: ~0.29.1 - ramda-adjunct: ^4.1.1 + "@swagger-api/apidom-ast": ^1.0.0-alpha.5 + "@swagger-api/apidom-core": ^1.0.0-alpha.5 + "@swagger-api/apidom-json-pointer": ^1.0.0-alpha.5 + "@swagger-api/apidom-ns-openapi-3-0": ^1.0.0-alpha.5 + "@types/ramda": ~0.30.0 + ramda: ~0.30.0 + ramda-adjunct: ^5.0.0 ts-mixer: ^6.0.3 - checksum: 53ab8bd15d382648c701bb1e374d0ccc8e9d90a1aeb0106631d77846b765e3dd282e7b3d7f2b748f2eaccaf0d16ec02a49e3319078e298b1c228d22625934e1b + checksum: 34dff7a4c8cd9fa78ec1efc927bfd1a5ca6f796e786359c7b0899d98ba4efaaa28b9c6f1a4abfcb708cd36a560fa12429c86c55aaa8594d94cb712bfc83cca74 languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-api-design-systems-json@npm:^0.99.1": - version: 0.99.1 - resolution: "@swagger-api/apidom-parser-adapter-api-design-systems-json@npm:0.99.1" +"@swagger-api/apidom-ns-workflows-1@npm:^1.0.0-alpha.1, @swagger-api/apidom-ns-workflows-1@npm:^1.0.0-alpha.5": + version: 1.0.0-alpha.5 + resolution: "@swagger-api/apidom-ns-workflows-1@npm:1.0.0-alpha.5" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.99.1 - "@swagger-api/apidom-ns-api-design-systems": ^0.99.1 - "@swagger-api/apidom-parser-adapter-json": ^0.99.1 - "@types/ramda": ~0.29.6 - ramda: ~0.29.1 - ramda-adjunct: ^4.0.0 - checksum: 406e4168c09e8907ac8983aecdc18429cded4db2b9793d2eb56a8e8494cae96d4309787c6316e3b584ad9c71434c0b31a933ee91d5b610b6fac72880692cfa3a + "@swagger-api/apidom-core": ^1.0.0-alpha.5 + "@swagger-api/apidom-ns-openapi-3-1": ^1.0.0-alpha.5 + "@types/ramda": ~0.30.0 + ramda: ~0.30.0 + ramda-adjunct: ^5.0.0 + ts-mixer: ^6.0.3 + checksum: a69da0674172309ff171f7a52826e781051ba10df713bba89a5c15f5a846c1100dc9e9ac695682fd44483c02fab1ee6174abe692fe7615d3969ea01c788a7736 languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-api-design-systems-yaml@npm:^0.99.1": - version: 0.99.1 - resolution: "@swagger-api/apidom-parser-adapter-api-design-systems-yaml@npm:0.99.1" +"@swagger-api/apidom-parser-adapter-api-design-systems-json@npm:^1.0.0-alpha.1": + version: 1.0.0-alpha.5 + resolution: "@swagger-api/apidom-parser-adapter-api-design-systems-json@npm:1.0.0-alpha.5" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.99.1 - "@swagger-api/apidom-ns-api-design-systems": ^0.99.1 - "@swagger-api/apidom-parser-adapter-yaml-1-2": ^0.99.1 - "@types/ramda": ~0.29.6 - ramda: ~0.29.1 - ramda-adjunct: ^4.0.0 - checksum: 899d2181efd0afdfda5eb9d678b7ae4e1f4710b2d56a05272751aec86510c0e48d681d8cb16388b8e88f225fbb63c9a0b49aa79b94589a82c1bdb41d66d77012 + "@swagger-api/apidom-core": ^1.0.0-alpha.5 + "@swagger-api/apidom-ns-api-design-systems": ^1.0.0-alpha.5 + "@swagger-api/apidom-parser-adapter-json": ^1.0.0-alpha.5 + "@types/ramda": ~0.30.0 + ramda: ~0.30.0 + ramda-adjunct: ^5.0.0 + checksum: 53946807d3c4599d0439a7347ee4c6392a07c80b1328b09b23c752dd93d8c3227a32553be309ded5d7270d6fc493467433f199a42179c92d5cf3d01d4a538c67 languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-asyncapi-json-2@npm:^0.99.1": - version: 0.99.1 - resolution: "@swagger-api/apidom-parser-adapter-asyncapi-json-2@npm:0.99.1" +"@swagger-api/apidom-parser-adapter-api-design-systems-yaml@npm:^1.0.0-alpha.1": + version: 1.0.0-alpha.5 + resolution: "@swagger-api/apidom-parser-adapter-api-design-systems-yaml@npm:1.0.0-alpha.5" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.99.1 - "@swagger-api/apidom-ns-asyncapi-2": ^0.99.1 - "@swagger-api/apidom-parser-adapter-json": ^0.99.1 - "@types/ramda": ~0.29.6 - ramda: ~0.29.1 - ramda-adjunct: ^4.0.0 - checksum: e2b2d38769a11ad5c578a501acb8a015c8c359f7623ad37226d14845c96efd8d50d8d0bda417789402e74d52cbaf75c5e659936380b444f26dcfa5bb8c5df2df + "@swagger-api/apidom-core": ^1.0.0-alpha.5 + "@swagger-api/apidom-ns-api-design-systems": ^1.0.0-alpha.5 + "@swagger-api/apidom-parser-adapter-yaml-1-2": ^1.0.0-alpha.5 + "@types/ramda": ~0.30.0 + ramda: ~0.30.0 + ramda-adjunct: ^5.0.0 + checksum: 488b8491a9936619a011330feb4b9394d4337c32d13e4c2b175e16415ac15eb09247b5325948f5957bc2ea0beef255d39ef9ec86ad9a80bfbf7b41f69e999d7f languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-asyncapi-yaml-2@npm:^0.99.1": - version: 0.99.1 - resolution: "@swagger-api/apidom-parser-adapter-asyncapi-yaml-2@npm:0.99.1" +"@swagger-api/apidom-parser-adapter-asyncapi-json-2@npm:^1.0.0-alpha.1": + version: 1.0.0-alpha.5 + resolution: "@swagger-api/apidom-parser-adapter-asyncapi-json-2@npm:1.0.0-alpha.5" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.99.1 - "@swagger-api/apidom-ns-asyncapi-2": ^0.99.1 - "@swagger-api/apidom-parser-adapter-yaml-1-2": ^0.99.1 - "@types/ramda": ~0.29.6 - ramda: ~0.29.1 - ramda-adjunct: ^4.0.0 - checksum: 27f8e1486f41074b679dd0016fd8b764ba2ec11fd589438e10f6c712f9d816b9b45edb3de02315fe43dcbbafdd68f392e217855109919b9b75d5065885691e7e + "@swagger-api/apidom-core": ^1.0.0-alpha.5 + "@swagger-api/apidom-ns-asyncapi-2": ^1.0.0-alpha.5 + "@swagger-api/apidom-parser-adapter-json": ^1.0.0-alpha.5 + "@types/ramda": ~0.30.0 + ramda: ~0.30.0 + ramda-adjunct: ^5.0.0 + checksum: 3079f33fd5c03ce8d506a8a5bcfb5f582b303280b168395b5617a8f498953575e4c41fbc33ca08f195620f9a6e8bd569baca0900f30d00d556397f923c5eeaa4 languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-json@npm:^0.99.1": - version: 0.99.1 - resolution: "@swagger-api/apidom-parser-adapter-json@npm:0.99.1" +"@swagger-api/apidom-parser-adapter-asyncapi-yaml-2@npm:^1.0.0-alpha.1": + version: 1.0.0-alpha.5 + resolution: "@swagger-api/apidom-parser-adapter-asyncapi-yaml-2@npm:1.0.0-alpha.5" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-ast": ^0.99.1 - "@swagger-api/apidom-core": ^0.99.1 - "@swagger-api/apidom-error": ^0.99.0 - "@types/ramda": ~0.29.6 + "@swagger-api/apidom-core": ^1.0.0-alpha.5 + "@swagger-api/apidom-ns-asyncapi-2": ^1.0.0-alpha.5 + "@swagger-api/apidom-parser-adapter-yaml-1-2": ^1.0.0-alpha.5 + "@types/ramda": ~0.30.0 + ramda: ~0.30.0 + ramda-adjunct: ^5.0.0 + checksum: 75d563566df0690cd27c8e464924e33c73266b633109cc8c0ee3915d3e94ceb192f833a50e7fbb42c354b7fdf6e2edfacda994cae4a82f6abc44f149a74ab8b5 + languageName: node + linkType: hard + +"@swagger-api/apidom-parser-adapter-json@npm:^1.0.0-alpha.1, @swagger-api/apidom-parser-adapter-json@npm:^1.0.0-alpha.5": + version: 1.0.0-alpha.5 + resolution: "@swagger-api/apidom-parser-adapter-json@npm:1.0.0-alpha.5" + dependencies: + "@babel/runtime-corejs3": ^7.20.7 + "@swagger-api/apidom-ast": ^1.0.0-alpha.5 + "@swagger-api/apidom-core": ^1.0.0-alpha.5 + "@swagger-api/apidom-error": ^1.0.0-alpha.5 + "@types/ramda": ~0.30.0 node-gyp: latest - ramda: ~0.29.1 - ramda-adjunct: ^4.1.1 + ramda: ~0.30.0 + ramda-adjunct: ^5.0.0 tree-sitter: =0.20.4 tree-sitter-json: =0.20.2 web-tree-sitter: =0.20.3 - checksum: eb8383965c866a60b06ea3da8f7a25a18fde35ae0455df8ce2a5a537b95424fba01cb3dd4f403869a3ba14d685388dc6f0b1362e5cf95ad6cdd1c65bd31dfa49 + checksum: c02a478c578d2f98b82c1f920240e22f856ae5b2c92b8f4b85fd80337c8112ca5b6b82b4a4a51a0cf0fc364a32af5deb1856d4a6bcdc27b07a2ba14f3255e3fa languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-openapi-json-2@npm:^0.99.1": - version: 0.99.1 - resolution: "@swagger-api/apidom-parser-adapter-openapi-json-2@npm:0.99.1" +"@swagger-api/apidom-parser-adapter-openapi-json-2@npm:^1.0.0-alpha.1": + version: 1.0.0-alpha.5 + resolution: "@swagger-api/apidom-parser-adapter-openapi-json-2@npm:1.0.0-alpha.5" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.99.1 - "@swagger-api/apidom-ns-openapi-2": ^0.99.1 - "@swagger-api/apidom-parser-adapter-json": ^0.99.1 - "@types/ramda": ~0.29.6 - ramda: ~0.29.1 - ramda-adjunct: ^4.0.0 - checksum: 4711cc0c42c7e31c82a45e15c118ddec5a8c0da628e1bc43c8096b849f2f56ff45e96d9ae32efb3f6d586b094cba1e068a5c42ff4bb99ffeba99389d4d865458 + "@swagger-api/apidom-core": ^1.0.0-alpha.5 + "@swagger-api/apidom-ns-openapi-2": ^1.0.0-alpha.5 + "@swagger-api/apidom-parser-adapter-json": ^1.0.0-alpha.5 + "@types/ramda": ~0.30.0 + ramda: ~0.30.0 + ramda-adjunct: ^5.0.0 + checksum: 273172f3a2b5aaf685b0fa5cdff28b026d4825018f0b24b3e3e942773037240a2e328c77a18df3e8e96a549d33f880033474bac90ac0ad1ad9ee643b7f4230b6 languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-openapi-json-3-0@npm:^0.99.1": - version: 0.99.1 - resolution: "@swagger-api/apidom-parser-adapter-openapi-json-3-0@npm:0.99.1" +"@swagger-api/apidom-parser-adapter-openapi-json-3-0@npm:^1.0.0-alpha.1": + version: 1.0.0-alpha.5 + resolution: "@swagger-api/apidom-parser-adapter-openapi-json-3-0@npm:1.0.0-alpha.5" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.99.1 - "@swagger-api/apidom-ns-openapi-3-0": ^0.99.1 - "@swagger-api/apidom-parser-adapter-json": ^0.99.1 - "@types/ramda": ~0.29.6 - ramda: ~0.29.1 - ramda-adjunct: ^4.0.0 - checksum: 0e5146fcd49c5aae257b148420358bd136863df7261cfb5a338bb12bd86503c71bcb12cb510e5bff9a3dd84783ce8ed6776ac9300bc0c4e795c1ecb45fac91d0 + "@swagger-api/apidom-core": ^1.0.0-alpha.5 + "@swagger-api/apidom-ns-openapi-3-0": ^1.0.0-alpha.5 + "@swagger-api/apidom-parser-adapter-json": ^1.0.0-alpha.5 + "@types/ramda": ~0.30.0 + ramda: ~0.30.0 + ramda-adjunct: ^5.0.0 + checksum: 962c6c0ee03303f205bec71c02b39736aad9e02e27a7edfdf3666b7f4375e51193f650077f884c04858682776cdc0f1f9427277e2f62e676ef0a877b7fa5af43 languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-openapi-json-3-1@npm:^0.99.1": - version: 0.99.1 - resolution: "@swagger-api/apidom-parser-adapter-openapi-json-3-1@npm:0.99.1" +"@swagger-api/apidom-parser-adapter-openapi-json-3-1@npm:^1.0.0-alpha.1": + version: 1.0.0-alpha.5 + resolution: "@swagger-api/apidom-parser-adapter-openapi-json-3-1@npm:1.0.0-alpha.5" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.99.1 - "@swagger-api/apidom-ns-openapi-3-1": ^0.99.1 - "@swagger-api/apidom-parser-adapter-json": ^0.99.1 - "@types/ramda": ~0.29.6 - ramda: ~0.29.1 - ramda-adjunct: ^4.0.0 - checksum: e36e808ce1d79279cc495327e0223922071be3856603a485980f9a237af37dc3488c96e20b0b0d4f364b8a0247574185d61be1b6d536f06e49a8e91a3b262a1e + "@swagger-api/apidom-core": ^1.0.0-alpha.5 + "@swagger-api/apidom-ns-openapi-3-1": ^1.0.0-alpha.5 + "@swagger-api/apidom-parser-adapter-json": ^1.0.0-alpha.5 + "@types/ramda": ~0.30.0 + ramda: ~0.30.0 + ramda-adjunct: ^5.0.0 + checksum: 1eef1d3682478f18668cf7dc13fbfd13be7931e8c94042a3916c73653685cd79d916c93d00d4ce44478bee6a59616fabf0cd76ca4decdd78e283caa1660112a7 languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-openapi-yaml-2@npm:^0.99.1": - version: 0.99.1 - resolution: "@swagger-api/apidom-parser-adapter-openapi-yaml-2@npm:0.99.1" +"@swagger-api/apidom-parser-adapter-openapi-yaml-2@npm:^1.0.0-alpha.1": + version: 1.0.0-alpha.5 + resolution: "@swagger-api/apidom-parser-adapter-openapi-yaml-2@npm:1.0.0-alpha.5" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.99.1 - "@swagger-api/apidom-ns-openapi-2": ^0.99.1 - "@swagger-api/apidom-parser-adapter-yaml-1-2": ^0.99.1 - "@types/ramda": ~0.29.6 - ramda: ~0.29.1 - ramda-adjunct: ^4.0.0 - checksum: ec0156285810a76148f16bcb525ac8267ea99bc7c7a3ded7bb5dfdef987ab11c5d9fe20f5e1d43e35e0de777b68a0fd38633247bbe2ee66d05d76753f25f61e9 + "@swagger-api/apidom-core": ^1.0.0-alpha.5 + "@swagger-api/apidom-ns-openapi-2": ^1.0.0-alpha.5 + "@swagger-api/apidom-parser-adapter-yaml-1-2": ^1.0.0-alpha.5 + "@types/ramda": ~0.30.0 + ramda: ~0.30.0 + ramda-adjunct: ^5.0.0 + checksum: 61da4b37175c7ebc45447b95f1d67837d2a9a97a22c9067e7be38b41e86c7ccd9367260031fa1e22f256f1e6f9fa2ba58a486cd70823f3aa1e683fa8981ef657 languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-openapi-yaml-3-0@npm:^0.99.1": - version: 0.99.1 - resolution: "@swagger-api/apidom-parser-adapter-openapi-yaml-3-0@npm:0.99.1" +"@swagger-api/apidom-parser-adapter-openapi-yaml-3-0@npm:^1.0.0-alpha.1": + version: 1.0.0-alpha.5 + resolution: "@swagger-api/apidom-parser-adapter-openapi-yaml-3-0@npm:1.0.0-alpha.5" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.99.1 - "@swagger-api/apidom-ns-openapi-3-0": ^0.99.1 - "@swagger-api/apidom-parser-adapter-yaml-1-2": ^0.99.1 - "@types/ramda": ~0.29.6 - ramda: ~0.29.1 - ramda-adjunct: ^4.0.0 - checksum: 397cf17638246ce6b4b4a7ddb315d78dfa50c565b399ff73f929ed64c6d8d991f3a4e38aa2b0ae70af6e5fa6fef06bae9205e9547649a957f3b5e4696ff0a050 + "@swagger-api/apidom-core": ^1.0.0-alpha.5 + "@swagger-api/apidom-ns-openapi-3-0": ^1.0.0-alpha.5 + "@swagger-api/apidom-parser-adapter-yaml-1-2": ^1.0.0-alpha.5 + "@types/ramda": ~0.30.0 + ramda: ~0.30.0 + ramda-adjunct: ^5.0.0 + checksum: 1a2d48ef31d4331259c55e49c30abbf9c45e488a5df0084da716492aff94b8c0f5d20619189783792f8964f6a2a4731e442ea693389e86069a7c5d3bae106465 languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-openapi-yaml-3-1@npm:^0.99.1": - version: 0.99.1 - resolution: "@swagger-api/apidom-parser-adapter-openapi-yaml-3-1@npm:0.99.1" +"@swagger-api/apidom-parser-adapter-openapi-yaml-3-1@npm:^1.0.0-alpha.1": + version: 1.0.0-alpha.5 + resolution: "@swagger-api/apidom-parser-adapter-openapi-yaml-3-1@npm:1.0.0-alpha.5" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.99.1 - "@swagger-api/apidom-ns-openapi-3-1": ^0.99.1 - "@swagger-api/apidom-parser-adapter-yaml-1-2": ^0.99.1 - "@types/ramda": ~0.29.6 - ramda: ~0.29.1 - ramda-adjunct: ^4.0.0 - checksum: 186f37d84758adcd02ba2d7734b5c99cc97f57dd102d1f2c82991bb7b68380a1a9d632656389262dfd20b53234a55ca8fa17e800c0401544abb90ace174bf1cf + "@swagger-api/apidom-core": ^1.0.0-alpha.5 + "@swagger-api/apidom-ns-openapi-3-1": ^1.0.0-alpha.5 + "@swagger-api/apidom-parser-adapter-yaml-1-2": ^1.0.0-alpha.5 + "@types/ramda": ~0.30.0 + ramda: ~0.30.0 + ramda-adjunct: ^5.0.0 + checksum: 6e74a5db37f834b43c2c9f26371183b5cdd5ef692c301e9d59345a2abbf81ae2813d75e3aed3eb4dcd2310cca81fc8e876731149925e13671fe058a761b5bba5 languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-workflows-json-1@npm:^0.99.1": - version: 0.99.1 - resolution: "@swagger-api/apidom-parser-adapter-workflows-json-1@npm:0.99.1" +"@swagger-api/apidom-parser-adapter-workflows-json-1@npm:^1.0.0-alpha.1": + version: 1.0.0-alpha.5 + resolution: "@swagger-api/apidom-parser-adapter-workflows-json-1@npm:1.0.0-alpha.5" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.99.1 - "@swagger-api/apidom-ns-workflows-1": ^0.99.1 - "@swagger-api/apidom-parser-adapter-json": ^0.99.1 - "@types/ramda": ~0.29.6 - ramda: ~0.29.1 - ramda-adjunct: ^4.0.0 - checksum: 3a2e928be611461a9533eb69eebabd8bf59381e82507725c938e36dd77fead3c260d27cd287d92f884323928683e518c47361889c52720a58294c0b3eb2a7b55 + "@swagger-api/apidom-core": ^1.0.0-alpha.5 + "@swagger-api/apidom-ns-workflows-1": ^1.0.0-alpha.5 + "@swagger-api/apidom-parser-adapter-json": ^1.0.0-alpha.5 + "@types/ramda": ~0.30.0 + ramda: ~0.30.0 + ramda-adjunct: ^5.0.0 + checksum: fcdd06da2f9e78b665135fcb194aec7de68d788ce81aab4b3025a3991cc5b393b36a48b1314cfc7a7107143988da3362da4f2ce17631bbef6afb049c30f39455 languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-workflows-yaml-1@npm:^0.99.1": - version: 0.99.1 - resolution: "@swagger-api/apidom-parser-adapter-workflows-yaml-1@npm:0.99.1" +"@swagger-api/apidom-parser-adapter-workflows-yaml-1@npm:^1.0.0-alpha.1": + version: 1.0.0-alpha.5 + resolution: "@swagger-api/apidom-parser-adapter-workflows-yaml-1@npm:1.0.0-alpha.5" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.99.1 - "@swagger-api/apidom-ns-workflows-1": ^0.99.1 - "@swagger-api/apidom-parser-adapter-yaml-1-2": ^0.99.1 - "@types/ramda": ~0.29.6 - ramda: ~0.29.1 - ramda-adjunct: ^4.0.0 - checksum: 7869ba27343a8936ff2def5570b41b9abb2618afa8ee0fbecbb0a0213031dbbc28bb5692e486350748099fadd22578928f8d5a420f11769247044a026c8138e5 + "@swagger-api/apidom-core": ^1.0.0-alpha.5 + "@swagger-api/apidom-ns-workflows-1": ^1.0.0-alpha.5 + "@swagger-api/apidom-parser-adapter-yaml-1-2": ^1.0.0-alpha.5 + "@types/ramda": ~0.30.0 + ramda: ~0.30.0 + ramda-adjunct: ^5.0.0 + checksum: ebce7c54a0081dbda5cc4156af0ab4593e4fa61273079cb9a3b5416cad470e9df6b6964dfd494e372825052a51b42b4142201305dc9a0a1a72b3e4ebac16b665 languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-yaml-1-2@npm:^0.99.1": - version: 0.99.1 - resolution: "@swagger-api/apidom-parser-adapter-yaml-1-2@npm:0.99.1" +"@swagger-api/apidom-parser-adapter-yaml-1-2@npm:^1.0.0-alpha.1, @swagger-api/apidom-parser-adapter-yaml-1-2@npm:^1.0.0-alpha.5": + version: 1.0.0-alpha.5 + resolution: "@swagger-api/apidom-parser-adapter-yaml-1-2@npm:1.0.0-alpha.5" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-ast": ^0.99.1 - "@swagger-api/apidom-core": ^0.99.1 - "@swagger-api/apidom-error": ^0.99.0 - "@types/ramda": ~0.29.6 + "@swagger-api/apidom-ast": ^1.0.0-alpha.5 + "@swagger-api/apidom-core": ^1.0.0-alpha.5 + "@swagger-api/apidom-error": ^1.0.0-alpha.5 + "@types/ramda": ~0.30.0 node-gyp: latest - ramda: ~0.29.1 - ramda-adjunct: ^4.1.1 + ramda: ~0.30.0 + ramda-adjunct: ^5.0.0 tree-sitter: =0.20.4 tree-sitter-yaml: =0.5.0 web-tree-sitter: =0.20.3 - checksum: c10237864c4a99a319f5b19bb6c4234e32b422c03fc358350e9c9106a8612839abcc68e3e06e58ee2f9b450e1d7ab0288f8b89ee8b5338735170af1b48b2112a + checksum: 8738abe67da0d38b519b4c60eb3081e219060ad5164eb85d455020e3b28d64e89390300c3bc162f05a182447aa7ca8c9c6af2ad2581aa2318ccb4bc133de902b languageName: node linkType: hard -"@swagger-api/apidom-reference@npm:>=0.99.1 <1.0.0": - version: 0.99.1 - resolution: "@swagger-api/apidom-reference@npm:0.99.1" +"@swagger-api/apidom-reference@npm:>=1.0.0-alpha.5 <1.0.0-beta.0": + version: 1.0.0-alpha.5 + resolution: "@swagger-api/apidom-reference@npm:1.0.0-alpha.5" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.99.1 - "@swagger-api/apidom-error": ^0.99.0 - "@swagger-api/apidom-json-pointer": ^0.99.1 - "@swagger-api/apidom-ns-asyncapi-2": ^0.99.1 - "@swagger-api/apidom-ns-openapi-2": ^0.99.1 - "@swagger-api/apidom-ns-openapi-3-0": ^0.99.1 - "@swagger-api/apidom-ns-openapi-3-1": ^0.99.1 - "@swagger-api/apidom-ns-workflows-1": ^0.99.1 - "@swagger-api/apidom-parser-adapter-api-design-systems-json": ^0.99.1 - "@swagger-api/apidom-parser-adapter-api-design-systems-yaml": ^0.99.1 - "@swagger-api/apidom-parser-adapter-asyncapi-json-2": ^0.99.1 - "@swagger-api/apidom-parser-adapter-asyncapi-yaml-2": ^0.99.1 - "@swagger-api/apidom-parser-adapter-json": ^0.99.1 - "@swagger-api/apidom-parser-adapter-openapi-json-2": ^0.99.1 - "@swagger-api/apidom-parser-adapter-openapi-json-3-0": ^0.99.1 - "@swagger-api/apidom-parser-adapter-openapi-json-3-1": ^0.99.1 - "@swagger-api/apidom-parser-adapter-openapi-yaml-2": ^0.99.1 - "@swagger-api/apidom-parser-adapter-openapi-yaml-3-0": ^0.99.1 - "@swagger-api/apidom-parser-adapter-openapi-yaml-3-1": ^0.99.1 - "@swagger-api/apidom-parser-adapter-workflows-json-1": ^0.99.1 - "@swagger-api/apidom-parser-adapter-workflows-yaml-1": ^0.99.1 - "@swagger-api/apidom-parser-adapter-yaml-1-2": ^0.99.1 - "@types/ramda": ~0.29.6 + "@swagger-api/apidom-core": ^1.0.0-alpha.5 + "@swagger-api/apidom-error": ^1.0.0-alpha.1 + "@swagger-api/apidom-json-pointer": ^1.0.0-alpha.1 + "@swagger-api/apidom-ns-asyncapi-2": ^1.0.0-alpha.1 + "@swagger-api/apidom-ns-openapi-2": ^1.0.0-alpha.1 + "@swagger-api/apidom-ns-openapi-3-0": ^1.0.0-alpha.1 + "@swagger-api/apidom-ns-openapi-3-1": ^1.0.0-alpha.1 + "@swagger-api/apidom-ns-workflows-1": ^1.0.0-alpha.1 + "@swagger-api/apidom-parser-adapter-api-design-systems-json": ^1.0.0-alpha.1 + "@swagger-api/apidom-parser-adapter-api-design-systems-yaml": ^1.0.0-alpha.1 + "@swagger-api/apidom-parser-adapter-asyncapi-json-2": ^1.0.0-alpha.1 + "@swagger-api/apidom-parser-adapter-asyncapi-yaml-2": ^1.0.0-alpha.1 + "@swagger-api/apidom-parser-adapter-json": ^1.0.0-alpha.1 + "@swagger-api/apidom-parser-adapter-openapi-json-2": ^1.0.0-alpha.1 + "@swagger-api/apidom-parser-adapter-openapi-json-3-0": ^1.0.0-alpha.1 + "@swagger-api/apidom-parser-adapter-openapi-json-3-1": ^1.0.0-alpha.1 + "@swagger-api/apidom-parser-adapter-openapi-yaml-2": ^1.0.0-alpha.1 + "@swagger-api/apidom-parser-adapter-openapi-yaml-3-0": ^1.0.0-alpha.1 + "@swagger-api/apidom-parser-adapter-openapi-yaml-3-1": ^1.0.0-alpha.1 + "@swagger-api/apidom-parser-adapter-workflows-json-1": ^1.0.0-alpha.1 + "@swagger-api/apidom-parser-adapter-workflows-yaml-1": ^1.0.0-alpha.1 + "@swagger-api/apidom-parser-adapter-yaml-1-2": ^1.0.0-alpha.1 + "@types/ramda": ~0.30.0 axios: ^1.4.0 minimatch: ^7.4.3 process: ^0.11.10 - ramda: ~0.29.1 - ramda-adjunct: ^4.1.1 - stampit: ^4.3.2 + ramda: ~0.30.0 + ramda-adjunct: ^5.0.0 dependenciesMeta: "@swagger-api/apidom-error": optional: true @@ -16573,98 +16572,98 @@ __metadata: optional: true "@swagger-api/apidom-parser-adapter-yaml-1-2": optional: true - checksum: 2131dc3df89c1670d8f5fde91f524a240afc253cf4fa8cf3c4b0ed2a35671b20b44fe944c7f3149fecd17e0cce3502f9d333df982d01ca999149a05bd9d9fc12 + checksum: abf5636636197780bad9a5f4b3397a03152fdf55d47d61d1b694ffc119f105606e06ffb757519fc459a7d9e00c2862b2e0844f1f64c713f290c3b8ff3470faf4 languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.5.0": - version: 1.5.0 - resolution: "@swc/core-darwin-arm64@npm:1.5.0" +"@swc/core-darwin-arm64@npm:1.5.29": + version: 1.5.29 + resolution: "@swc/core-darwin-arm64@npm:1.5.29" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.5.0": - version: 1.5.0 - resolution: "@swc/core-darwin-x64@npm:1.5.0" +"@swc/core-darwin-x64@npm:1.5.29": + version: 1.5.29 + resolution: "@swc/core-darwin-x64@npm:1.5.29" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.5.0": - version: 1.5.0 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.5.0" +"@swc/core-linux-arm-gnueabihf@npm:1.5.29": + version: 1.5.29 + resolution: "@swc/core-linux-arm-gnueabihf@npm:1.5.29" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@swc/core-linux-arm64-gnu@npm:1.5.0": - version: 1.5.0 - resolution: "@swc/core-linux-arm64-gnu@npm:1.5.0" +"@swc/core-linux-arm64-gnu@npm:1.5.29": + version: 1.5.29 + resolution: "@swc/core-linux-arm64-gnu@npm:1.5.29" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.5.0": - version: 1.5.0 - resolution: "@swc/core-linux-arm64-musl@npm:1.5.0" +"@swc/core-linux-arm64-musl@npm:1.5.29": + version: 1.5.29 + resolution: "@swc/core-linux-arm64-musl@npm:1.5.29" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.5.0": - version: 1.5.0 - resolution: "@swc/core-linux-x64-gnu@npm:1.5.0" +"@swc/core-linux-x64-gnu@npm:1.5.29": + version: 1.5.29 + resolution: "@swc/core-linux-x64-gnu@npm:1.5.29" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.5.0": - version: 1.5.0 - resolution: "@swc/core-linux-x64-musl@npm:1.5.0" +"@swc/core-linux-x64-musl@npm:1.5.29": + version: 1.5.29 + resolution: "@swc/core-linux-x64-musl@npm:1.5.29" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.5.0": - version: 1.5.0 - resolution: "@swc/core-win32-arm64-msvc@npm:1.5.0" +"@swc/core-win32-arm64-msvc@npm:1.5.29": + version: 1.5.29 + resolution: "@swc/core-win32-arm64-msvc@npm:1.5.29" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.5.0": - version: 1.5.0 - resolution: "@swc/core-win32-ia32-msvc@npm:1.5.0" +"@swc/core-win32-ia32-msvc@npm:1.5.29": + version: 1.5.29 + resolution: "@swc/core-win32-ia32-msvc@npm:1.5.29" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.5.0": - version: 1.5.0 - resolution: "@swc/core-win32-x64-msvc@npm:1.5.0" +"@swc/core-win32-x64-msvc@npm:1.5.29": + version: 1.5.29 + resolution: "@swc/core-win32-x64-msvc@npm:1.5.29" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "@swc/core@npm:^1.3.46": - version: 1.5.0 - resolution: "@swc/core@npm:1.5.0" + version: 1.5.29 + resolution: "@swc/core@npm:1.5.29" dependencies: - "@swc/core-darwin-arm64": 1.5.0 - "@swc/core-darwin-x64": 1.5.0 - "@swc/core-linux-arm-gnueabihf": 1.5.0 - "@swc/core-linux-arm64-gnu": 1.5.0 - "@swc/core-linux-arm64-musl": 1.5.0 - "@swc/core-linux-x64-gnu": 1.5.0 - "@swc/core-linux-x64-musl": 1.5.0 - "@swc/core-win32-arm64-msvc": 1.5.0 - "@swc/core-win32-ia32-msvc": 1.5.0 - "@swc/core-win32-x64-msvc": 1.5.0 - "@swc/counter": ^0.1.2 - "@swc/types": ^0.1.5 + "@swc/core-darwin-arm64": 1.5.29 + "@swc/core-darwin-x64": 1.5.29 + "@swc/core-linux-arm-gnueabihf": 1.5.29 + "@swc/core-linux-arm64-gnu": 1.5.29 + "@swc/core-linux-arm64-musl": 1.5.29 + "@swc/core-linux-x64-gnu": 1.5.29 + "@swc/core-linux-x64-musl": 1.5.29 + "@swc/core-win32-arm64-msvc": 1.5.29 + "@swc/core-win32-ia32-msvc": 1.5.29 + "@swc/core-win32-x64-msvc": 1.5.29 + "@swc/counter": ^0.1.3 + "@swc/types": ^0.1.8 peerDependencies: - "@swc/helpers": ^0.5.0 + "@swc/helpers": "*" dependenciesMeta: "@swc/core-darwin-arm64": optional: true @@ -16689,11 +16688,11 @@ __metadata: peerDependenciesMeta: "@swc/helpers": optional: true - checksum: 1abab0b57755020b60ebf2557629c23c65c3546e4cd80f9d02fbdf208d4169c9300a0229c088081b43a01e630c9d86d02f8c240c9fc2842eaed2a517770fcd1d + checksum: 19e3f8525ce4f4d9f6f3f62825b1f13e1e76146390930b6d5e663c0bb2c5e95ef3bf30268110d1444ea92b99dd95bfe5a3c6e2a3c0dd79291505dc7da1ed3dab languageName: node linkType: hard -"@swc/counter@npm:^0.1.2, @swc/counter@npm:^0.1.3": +"@swc/counter@npm:^0.1.3": version: 0.1.3 resolution: "@swc/counter@npm:0.1.3" checksum: df8f9cfba9904d3d60f511664c70d23bb323b3a0803ec9890f60133954173047ba9bdeabce28cd70ba89ccd3fd6c71c7b0bd58be85f611e1ffbe5d5c18616598 @@ -16701,11 +16700,11 @@ __metadata: linkType: hard "@swc/helpers@npm:^0.5.0": - version: 0.5.10 - resolution: "@swc/helpers@npm:0.5.10" + version: 0.5.11 + resolution: "@swc/helpers@npm:0.5.11" dependencies: tslib: ^2.4.0 - checksum: 7a202710e494ff8e6f74b92cc12f2ce226c4d75c0f82c7c4fb911173d27744def1b3a8274fb3820f4161403182acb06ee553eb6e8e5b77b0d0ed7132a9e85bc2 + checksum: 5d85e641d993264f38871bf53e7509da959cdff7646a40d876153291146b9d0aa701518546e5bfef18fa17c5944333bbeb66c2f0d7a570e8c5535d0937d76bd9 languageName: node linkType: hard @@ -16722,10 +16721,12 @@ __metadata: languageName: node linkType: hard -"@swc/types@npm:^0.1.5": - version: 0.1.5 - resolution: "@swc/types@npm:0.1.5" - checksum: 6aee11f62d3d805a64848e0bd5f0e0e615f958e327a9e1260056c368d7d28764d89e38bd8005a536c9bf18afbcd303edd84099d60df34a2975d62540f61df13b +"@swc/types@npm:^0.1.8": + version: 0.1.8 + resolution: "@swc/types@npm:0.1.8" + dependencies: + "@swc/counter": ^0.1.3 + checksum: e564d0e37b0e28546973c6d50c7a179395912a97168d695cfe9cf1051199c8b828680cdafcb8d43948f76d3703873bafb88dfb5bc2dfe0596b4ad18fcaf90c80 languageName: node linkType: hard @@ -16751,21 +16752,19 @@ __metadata: version: 0.0.0-use.local resolution: "@techdocs/cli@workspace:packages/techdocs-cli" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-defaults": "workspace:^" "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/cli-common": "workspace:^" "@backstage/config": "workspace:^" "@backstage/plugin-techdocs-node": "workspace:^" "@types/commander": ^2.12.2 - "@types/dockerode": ^3.3.0 "@types/fs-extra": ^11.0.0 "@types/http-proxy": ^1.17.4 "@types/node": ^18.17.8 "@types/serve-handler": ^6.1.0 "@types/webpack-env": ^1.15.3 commander: ^12.0.0 - dockerode: ^4.0.0 find-process: ^1.4.5 fs-extra: ^11.0.0 global-agent: ^3.0.0 @@ -17452,14 +17451,14 @@ __metadata: linkType: hard "@types/express-serve-static-core@npm:*, @types/express-serve-static-core@npm:^4.17.33, @types/express-serve-static-core@npm:^4.17.5": - version: 4.19.0 - resolution: "@types/express-serve-static-core@npm:4.19.0" + version: 4.19.3 + resolution: "@types/express-serve-static-core@npm:4.19.3" dependencies: "@types/node": "*" "@types/qs": "*" "@types/range-parser": "*" "@types/send": "*" - checksum: 39c09fcb3f61de96ed56d97273874cafe50e6675ac254af4d77014e569e4fdc29d1d0d1dd12e11f008cb9a52785b07c2801c6ba91397965392b20c75ee01fb4e + checksum: fff38a7f43baeb6a62380682d39846c9d92047e0dce1737d76ebd944528619abc18addc4f0548bf43dbf4514090a1bd5140ba36695024656f941a87424b8ed7d languageName: node linkType: hard @@ -17511,6 +17510,13 @@ __metadata: languageName: node linkType: hard +"@types/global-agent@npm:^2.1.3": + version: 2.1.3 + resolution: "@types/global-agent@npm:2.1.3" + checksum: 6129b6d5ba871b9d111ddf91e6f9a1725d3f28bf2aa6869ec83bebd14c688cde4275ebea6fa45b0b1c00d78109d022c935f952e9e4876d76289d4706484776c3 + languageName: node + linkType: hard + "@types/google-protobuf@npm:^3.7.2": version: 3.15.12 resolution: "@types/google-protobuf@npm:3.15.12" @@ -17894,9 +17900,9 @@ __metadata: linkType: hard "@types/lodash@npm:^4.14.151": - version: 4.17.4 - resolution: "@types/lodash@npm:4.17.4" - checksum: 268e652fd52d49189f155bc89b49bd4535aa44f0b6b0ed9ce7e50318307bda58147c49539d2047f39ca37cf5b5ea38dfb801d0dbcdbc8b019c95c1afc346b05a + version: 4.17.5 + resolution: "@types/lodash@npm:4.17.5" + checksum: 3c9bb15772509f0ecb40428531863dbc3f064f2bf34bbccc2ce2b2923c69fb0868aec7e357b1d97fd0d7f7e435a014ea5c1adef8a64715529887179c97a5a823 languageName: node linkType: hard @@ -18201,13 +18207,13 @@ __metadata: linkType: hard "@types/passport-oauth2@npm:*, @types/passport-oauth2@npm:^1.4.11, @types/passport-oauth2@npm:^1.4.15": - version: 1.4.16 - resolution: "@types/passport-oauth2@npm:1.4.16" + version: 1.4.17 + resolution: "@types/passport-oauth2@npm:1.4.17" dependencies: "@types/express": "*" "@types/oauth": "*" "@types/passport": "*" - checksum: a590d3fcdf93dbe4498c636de139dc22a723bbf12a7f248f432085a47ec1b76b2e1201336ee26cd65c400d7ce6fb30ae0b151f40067267942c8a5b3c708cc23d + checksum: 4c5d2d6f717bb0b3d049669e47ca27cb166cbbef2073dccd302b10e62936c9e392074acabe6cb593f7eeb37a6a3cf81b9d3a4f35a46018a6645ac37d0f1706cb languageName: node linkType: hard @@ -18271,13 +18277,6 @@ __metadata: languageName: node linkType: hard -"@types/picomatch@npm:2.3.3": - version: 2.3.3 - resolution: "@types/picomatch@npm:2.3.3" - checksum: 1bf1a1d80296a585d3310c97be87e67e16da6f5c168e01ce27eef835abfc5bcca8e395afd6ae8b2b73eb72540d1587da7a468e4dfe7277ea208cf43cae096854 - languageName: node - linkType: hard - "@types/ping@npm:^0.4.1": version: 0.4.4 resolution: "@types/ping@npm:0.4.4" @@ -18322,12 +18321,12 @@ __metadata: languageName: node linkType: hard -"@types/ramda@npm:~0.29.6": - version: 0.29.8 - resolution: "@types/ramda@npm:0.29.8" +"@types/ramda@npm:~0.30.0": + version: 0.30.0 + resolution: "@types/ramda@npm:0.30.0" dependencies: - types-ramda: ^0.29.5 - checksum: 9883baa6b19290822753332af90aaa8c0f612c87c740b1a64067524b2afee1871200d85b5ae4ae3b10627435fa045c314a615fec3e53d222c99f0aa6193cd271 + types-ramda: ^0.30.0 + checksum: abe9d9c872778d2598298a0c4805fa715618fe79a4d7e203c71076bc72e28c97f04ffb108274cbfc33b0407a5aa3c2c37f609705a175d4102418e292e4e55a22 languageName: node linkType: hard @@ -18422,7 +18421,7 @@ __metadata: languageName: node linkType: hard -"@types/react-window@npm:^1.8.5": +"@types/react-window@npm:^1.8.5, @types/react-window@npm:^1.8.8": version: 1.8.8 resolution: "@types/react-window@npm:1.8.8" dependencies: @@ -19392,17 +19391,17 @@ __metadata: linkType: hard "@vitejs/plugin-react@npm:^4.0.4": - version: 4.2.1 - resolution: "@vitejs/plugin-react@npm:4.2.1" + version: 4.3.1 + resolution: "@vitejs/plugin-react@npm:4.3.1" dependencies: - "@babel/core": ^7.23.5 - "@babel/plugin-transform-react-jsx-self": ^7.23.3 - "@babel/plugin-transform-react-jsx-source": ^7.23.3 + "@babel/core": ^7.24.5 + "@babel/plugin-transform-react-jsx-self": ^7.24.5 + "@babel/plugin-transform-react-jsx-source": ^7.24.1 "@types/babel__core": ^7.20.5 - react-refresh: ^0.14.0 + react-refresh: ^0.14.2 peerDependencies: vite: ^4.2.0 || ^5.0.0 - checksum: 08d227d27ff2304e395e746bd2d4b5fee40587f69d7e2fcd6beb7d91163c1f1dc26d843bc48e2ffb8f38c6b8a1b9445fb07840e3dcc841f97b56bbb8205346aa + checksum: 57872e0193c7e545c5ef4852cbe1adf17a6b35406a2aba4b3acce06c173a9dabbf6ff4c72701abc11bb3cbe24a056f5054f39018f7034c9aa57133a3a7770237 languageName: node linkType: hard @@ -20189,22 +20188,6 @@ __metadata: languageName: node linkType: hard -"@zkochan/retry@npm:^0.2.0": - version: 0.2.0 - resolution: "@zkochan/retry@npm:0.2.0" - checksum: 268e77e4f2254e608fdb79396ab6947e7c302ebe3df90696ad6cda4f09417845ca13ad4e6bfe813fab1839f1e66b14294ceb5591fb4dacd0999927aa6fe55826 - languageName: node - linkType: hard - -"@zkochan/rimraf@npm:^2.1.2": - version: 2.1.3 - resolution: "@zkochan/rimraf@npm:2.1.3" - dependencies: - rimraf: ^3.0.2 - checksum: 81cf488065b3b3fcb49980d35dc49a59f8961887c7ed589250ea233f7b91a30c3b9d3ec0b7700829062e7c514c5f07afdcf5f811a4f1a06227daa69c0638f32a - languageName: node - linkType: hard - "@zxing/text-encoding@npm:0.9.0": version: 0.9.0 resolution: "@zxing/text-encoding@npm:0.9.0" @@ -20634,6 +20617,13 @@ __metadata: languageName: node linkType: hard +"apg-lite@npm:^1.0.3": + version: 1.0.3 + resolution: "apg-lite@npm:1.0.3" + checksum: 69b2aaac4e479eb1afba6376802666ccc2384d9846474ebdd86f8ca9bd5754eea9d13038766bf67696f892e157fb577101ae40a69175c2d679c2898c0eaab5d8 + languageName: node + linkType: hard + "app-next-example-plugin@workspace:packages/app-next-example-plugin": version: 0.0.0-use.local resolution: "app-next-example-plugin@workspace:packages/app-next-example-plugin" @@ -20831,16 +20821,17 @@ __metadata: languageName: node linkType: hard -"array-includes@npm:^3.1.6, array-includes@npm:^3.1.7": - version: 3.1.7 - resolution: "array-includes@npm:3.1.7" +"array-includes@npm:^3.1.6, array-includes@npm:^3.1.7, array-includes@npm:^3.1.8": + version: 3.1.8 + resolution: "array-includes@npm:3.1.8" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - get-intrinsic: ^1.2.1 + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + es-object-atoms: ^1.0.0 + get-intrinsic: ^1.2.4 is-string: ^1.0.7 - checksum: 06f9e4598fac12a919f7c59a3f04f010ea07f0b7f0585465ed12ef528a60e45f374e79d1bddbb34cdd4338357d00023ddbd0ac18b0be36964f5e726e8965d7fc + checksum: eb39ba5530f64e4d8acab39297c11c1c5be2a4ea188ab2b34aba5fb7224d918f77717a9d57a3e2900caaa8440e59431bdaf5c974d5212ef65d97f132e38e2d91 languageName: node linkType: hard @@ -20867,16 +20858,17 @@ __metadata: languageName: node linkType: hard -"array.prototype.findlast@npm:^1.2.4": - version: 1.2.4 - resolution: "array.prototype.findlast@npm:1.2.4" +"array.prototype.findlast@npm:^1.2.5": + version: 1.2.5 + resolution: "array.prototype.findlast@npm:1.2.5" dependencies: - call-bind: ^1.0.5 + call-bind: ^1.0.7 define-properties: ^1.2.1 - es-abstract: ^1.22.3 + es-abstract: ^1.23.2 es-errors: ^1.3.0 + es-object-atoms: ^1.0.0 es-shim-unscopables: ^1.0.2 - checksum: b4c76571adf6c3cffbbbb8acd7ac39d94af6b120dd388dcf44637c22d77ba3ae13dd43d1be25d90956848fae5a01191fbdebe48ce4c0aa0989d7ee269a94a5a4 + checksum: 83ce4ad95bae07f136d316f5a7c3a5b911ac3296c3476abe60225bc4a17938bf37541972fcc37dd5adbc99cbb9c928c70bbbfc1c1ce549d41a415144030bb446 languageName: node linkType: hard @@ -21086,7 +21078,7 @@ __metadata: languageName: node linkType: hard -"async-lock@npm:^1.1.0, async-lock@npm:^1.4.1": +"async-lock@npm:^1.4.1": version: 1.4.1 resolution: "async-lock@npm:1.4.1" checksum: 29e70cd892932b7c202437786cedc39ff62123cb6941014739bd3cabd6106326416e9e7c21285a5d1dc042cad239a0f7ec9c44658491ee4a615fd36a21c1d10a @@ -21262,14 +21254,14 @@ __metadata: languageName: node linkType: hard -"axios@npm:1.6.5": - version: 1.6.5 - resolution: "axios@npm:1.6.5" +"axios@npm:1.6.8, axios@npm:^1.0.0, axios@npm:^1.4.0, axios@npm:^1.6.0": + version: 1.6.8 + resolution: "axios@npm:1.6.8" dependencies: - follow-redirects: ^1.15.4 + follow-redirects: ^1.15.6 form-data: ^4.0.0 proxy-from-env: ^1.1.0 - checksum: e28d67b2d9134cb4608c44d8068b0678cfdccc652742e619006f27264a30c7aba13b2cd19c6f1f52ae195b5232734925928fb192d5c85feea7edd2f273df206d + checksum: bf007fa4b207d102459300698620b3b0873503c6d47bf5a8f6e43c0c64c90035a4f698b55027ca1958f61ab43723df2781c38a99711848d232cad7accbcdfcdd languageName: node linkType: hard @@ -21283,17 +21275,6 @@ __metadata: languageName: node linkType: hard -"axios@npm:^1.0.0, axios@npm:^1.4.0, axios@npm:^1.6.0": - version: 1.6.8 - resolution: "axios@npm:1.6.8" - dependencies: - follow-redirects: ^1.15.6 - form-data: ^4.0.0 - proxy-from-env: ^1.1.0 - checksum: bf007fa4b207d102459300698620b3b0873503c6d47bf5a8f6e43c0c64c90035a4f698b55027ca1958f61ab43723df2781c38a99711848d232cad7accbcdfcdd - languageName: node - linkType: hard - "axobject-query@npm:^3.2.1": version: 3.2.1 resolution: "axobject-query@npm:3.2.1" @@ -21653,13 +21634,13 @@ __metadata: linkType: hard "better-sqlite3@npm:^9.0.0": - version: 9.5.0 - resolution: "better-sqlite3@npm:9.5.0" + version: 9.6.0 + resolution: "better-sqlite3@npm:9.6.0" dependencies: bindings: ^1.5.0 node-gyp: latest prebuild-install: ^7.1.1 - checksum: cfa56519755d6dd29ef8361c872c6f29392fcfcc44a435099eb61729aae23c4f18057972592a0b9ff0fcedc98e43db4ee7a1a2de21ab2868f8dcec4f8272ad9d + checksum: be3a1d2a3f6f9b5141be6607a38c0a51fa5849495b071955e507bc0c2a2fb08430852c1bf03796eec1a53344b25645807db48dcb51c71b0662b74c5a70420bb0 languageName: node linkType: hard @@ -21793,16 +21774,6 @@ __metadata: languageName: node linkType: hard -"bole@npm:^5.0.0": - version: 5.0.11 - resolution: "bole@npm:5.0.11" - dependencies: - fast-safe-stringify: ^2.0.7 - individual: ^3.0.0 - checksum: de8d478613d032db781652942055b29e9daeb57be1df06067e2e840d5ce4f3d2cbabfbc01b6f8698f3e054564569f2910b8f5b1161387f031517d4b064d2ea01 - languageName: node - linkType: hard - "bonjour-service@npm:^1.2.1": version: 1.2.1 resolution: "bonjour-service@npm:1.2.1" @@ -21876,7 +21847,7 @@ __metadata: languageName: node linkType: hard -"braces@npm:^3.0.2, braces@npm:^3.0.3, braces@npm:~3.0.2": +"braces@npm:^3.0.3, braces@npm:~3.0.2": version: 3.0.3 resolution: "braces@npm:3.0.3" dependencies: @@ -22004,17 +21975,17 @@ __metadata: languageName: node linkType: hard -"browserslist@npm:^4.0.0, browserslist@npm:^4.16.0, browserslist@npm:^4.16.6, browserslist@npm:^4.18.1, browserslist@npm:^4.21.10, browserslist@npm:^4.21.9": - version: 4.21.10 - resolution: "browserslist@npm:4.21.10" +"browserslist@npm:^4.0.0, browserslist@npm:^4.16.0, browserslist@npm:^4.16.6, browserslist@npm:^4.18.1, browserslist@npm:^4.21.10, browserslist@npm:^4.22.2": + version: 4.23.1 + resolution: "browserslist@npm:4.23.1" dependencies: - caniuse-lite: ^1.0.30001517 - electron-to-chromium: ^1.4.477 - node-releases: ^2.0.13 - update-browserslist-db: ^1.0.11 + caniuse-lite: ^1.0.30001629 + electron-to-chromium: ^1.4.796 + node-releases: ^2.0.14 + update-browserslist-db: ^1.0.16 bin: browserslist: cli.js - checksum: 1e27c0f111a35d1dd0e8fc2c61781b0daefabc2c9471b0b10537ce54843014bceb2a1ce4571af1a82b2bf1e6e6e05d38865916689a158f03bc2c7a4ec2577db8 + checksum: 06189e2d6666a203ce097cc0e713a40477d08420927b79af139211e5712f3cf676fdc4dd6af3aa493d47c09206a344b3420a8315577dbe88c58903132de9b0f5 languageName: node linkType: hard @@ -22131,15 +22102,6 @@ __metadata: languageName: node linkType: hard -"builtins@npm:^5.0.0": - version: 5.0.1 - resolution: "builtins@npm:5.0.1" - dependencies: - semver: ^7.0.0 - checksum: 66d204657fe36522822a95b288943ad11b58f5eaede235b11d8c4edaa28ce4800087d44a2681524c340494aadb120a0068011acabe99d30e8f11a7d826d83515 - languageName: node - linkType: hard - "bundle-name@npm:^4.1.0": version: 4.1.0 resolution: "bundle-name@npm:4.1.0" @@ -22383,10 +22345,10 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001517": - version: 1.0.30001523 - resolution: "caniuse-lite@npm:1.0.30001523" - checksum: 3a007dc8147d4b5a6c22661d424e6d4e4e9595d0dcb279d25b93161cc7d54363eb12d053f40a186ba7e42a8bc4f59e6e121474b7aa339bf7ec200258400d39bc +"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001629": + version: 1.0.30001632 + resolution: "caniuse-lite@npm:1.0.30001632" + checksum: 95be155501650ac36a8c3bdf60886bc8f7c419e7715cdaf1c04941f8676c0bd75355aeda62563092585fbe6f9d50d2eb6dea6bd063d7f6a58004ec62d8f8fe49 languageName: node linkType: hard @@ -24336,13 +24298,6 @@ __metadata: languageName: node linkType: hard -"data-uri-to-buffer@npm:^3.0.1": - version: 3.0.1 - resolution: "data-uri-to-buffer@npm:3.0.1" - checksum: c59c3009686a78c071806b72f4810856ec28222f0f4e252aa495ec027ed9732298ceea99c50328cf59b151dd34cbc3ad6150bbb43e41fc56fa19f48c99e9fc30 - languageName: node - linkType: hard - "data-uri-to-buffer@npm:^6.0.0": version: 6.0.1 resolution: "data-uri-to-buffer@npm:6.0.1" @@ -24574,13 +24529,6 @@ __metadata: languageName: node linkType: hard -"deep-freeze@npm:0.0.1": - version: 0.0.1 - resolution: "deep-freeze@npm:0.0.1" - checksum: 1e43c98e44c7849382d9f896e679d48a1b5bf40993f7cc858e3730ef4e2ba387b9b7b7fe722cac34febe7f6a564cd242c27bbc319e8df793c2a287f21e5ba038 - languageName: node - linkType: hard - "deep-is@npm:^0.1.3, deep-is@npm:~0.1.3": version: 0.1.3 resolution: "deep-is@npm:0.1.3" @@ -25117,17 +25065,24 @@ __metadata: languageName: node linkType: hard -"dompurify@npm:=3.1.0, dompurify@npm:^3.0.0": - version: 3.1.0 - resolution: "dompurify@npm:3.1.0" - checksum: 06fc76607cd076e394b2ea5479ab6f0407b8fedb6877ae95e94207b878365e5e1cd914055dacce152a5f419818afb8d4cd284b780246cf35363f0747c179a0ba +"dompurify@npm:=3.1.4": + version: 3.1.4 + resolution: "dompurify@npm:3.1.4" + checksum: 7b8d55d6e091c69cccfef73d066bd1bc82de32c81bc050b2c396b502afda0c853152760553aeb4d7ef86e7cf46bf49720fcb0c42a49ce939125cf40d7720ebb8 languageName: node linkType: hard "dompurify@npm:^2.2.7": - version: 2.5.0 - resolution: "dompurify@npm:2.5.0" - checksum: 9eab7be868ddb5a43fa634898605681e7b6b18dc5b89f5d143afc9ec63bb4d2c113a15900d5ee363859aa8722e8534da346486997eafbb29e3178cbb89077e15 + version: 2.5.5 + resolution: "dompurify@npm:2.5.5" + checksum: 9d6dace3fd619a64955f844b46ea12f83b101b0ed567241715f3f730b627038d391819b8868f2e53eebf4e231c3168429d49a5d0f01f96fcc23a794eb72b2a06 + languageName: node + linkType: hard + +"dompurify@npm:^3.0.0": + version: 3.1.5 + resolution: "dompurify@npm:3.1.5" + checksum: 18ae2930cba3c260889b99e312c382c344d219bd113bc39fbb665a61987d25849021768f490395e6954aab94448a24b3c3721c160b53550547110c37cebe9feb languageName: node linkType: hard @@ -25375,10 +25330,10 @@ __metadata: languageName: node linkType: hard -"electron-to-chromium@npm:^1.4.477": - version: 1.4.502 - resolution: "electron-to-chromium@npm:1.4.502" - checksum: 69b63eaed50c951c371b1bd907c6775275d170adbdc6b6091b961a78766f5e223b17823afbbc5984c843addac06a5348d3b14acbcf5a746f871ca8cdee6caeba +"electron-to-chromium@npm:^1.4.796": + version: 1.4.801 + resolution: "electron-to-chromium@npm:1.4.801" + checksum: fe2a75afefc08a03b7f077782ef7ab0a755d5f10dfdac981a13910e9257ed149d8a81477c16a4b2e4396ec698f3ad98c339155772f69d2f8f7907b5ee4d57b07 languageName: node linkType: hard @@ -25439,15 +25394,6 @@ __metadata: languageName: node linkType: hard -"encode-registry@npm:^3.0.1": - version: 3.0.1 - resolution: "encode-registry@npm:3.0.1" - dependencies: - mem: ^8.0.0 - checksum: 4e7cb234704782ef3e9e0c1941cb90de9b2421da8b87a21c968609e59b931c0316b15ea0e9b5280338a831dcb8e91362f8a54f712b10c70e28598f2dfb97da4a - languageName: node - linkType: hard - "encodeurl@npm:~1.0.2": version: 1.0.2 resolution: "encodeurl@npm:1.0.2" @@ -25493,13 +25439,6 @@ __metadata: languageName: node linkType: hard -"ent@npm:^2.2.0": - version: 2.2.0 - resolution: "ent@npm:2.2.0" - checksum: f588b5707d6fef36011ea10d530645912a69530a1eb0831f8708c498ac028363a7009f45cfadd28ceb4dafd9ac17ec15213f88d09ce239cd033cfe1328dd7d7d - languageName: node - linkType: hard - "entities@npm:^2.0.0": version: 2.2.0 resolution: "entities@npm:2.2.0" @@ -25560,9 +25499,9 @@ __metadata: languageName: node linkType: hard -"es-abstract@npm:^1.20.4, es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3, es-abstract@npm:^1.23.0": - version: 1.23.1 - resolution: "es-abstract@npm:1.23.1" +"es-abstract@npm:^1.20.4, es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3, es-abstract@npm:^1.23.0, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3": + version: 1.23.3 + resolution: "es-abstract@npm:1.23.3" dependencies: array-buffer-byte-length: ^1.0.1 arraybuffer.prototype.slice: ^1.0.3 @@ -25601,16 +25540,16 @@ __metadata: regexp.prototype.flags: ^1.5.2 safe-array-concat: ^1.1.2 safe-regex-test: ^1.0.3 - string.prototype.trim: ^1.2.8 - string.prototype.trimend: ^1.0.7 - string.prototype.trimstart: ^1.0.7 + string.prototype.trim: ^1.2.9 + string.prototype.trimend: ^1.0.8 + string.prototype.trimstart: ^1.0.8 typed-array-buffer: ^1.0.2 typed-array-byte-length: ^1.0.1 typed-array-byte-offset: ^1.0.2 - typed-array-length: ^1.0.5 + typed-array-length: ^1.0.6 unbox-primitive: ^1.0.2 which-typed-array: ^1.1.15 - checksum: a55b01af616898bfb1167fc567f3a6e22bb2800811a7f41f1c037f10bdc653894fc4c7000cce3a01e852628fd85044dff51d6d41f65f356a2ea847de3178b6ec + checksum: f840cf161224252512f9527306b57117192696571e07920f777cb893454e32999206198b4f075516112af6459daca282826d1735c450528470356d09eff3a9ae languageName: node linkType: hard @@ -25645,13 +25584,13 @@ __metadata: languageName: node linkType: hard -"es-iterator-helpers@npm:^1.0.15, es-iterator-helpers@npm:^1.0.17": - version: 1.0.18 - resolution: "es-iterator-helpers@npm:1.0.18" +"es-iterator-helpers@npm:^1.0.15, es-iterator-helpers@npm:^1.0.19": + version: 1.0.19 + resolution: "es-iterator-helpers@npm:1.0.19" dependencies: call-bind: ^1.0.7 define-properties: ^1.2.1 - es-abstract: ^1.23.0 + es-abstract: ^1.23.3 es-errors: ^1.3.0 es-set-tostringtag: ^2.0.3 function-bind: ^1.1.2 @@ -25663,7 +25602,7 @@ __metadata: internal-slot: ^1.0.7 iterator.prototype: ^1.1.2 safe-array-concat: ^1.1.2 - checksum: 1594324ff3ca8890fe30c98b2419d3007d2b14b35f9773f188114408ff973e13c526f6045d88209e932f58dc0c55fc9a4ae1554636f8938ed7d926ffc27d3e1a + checksum: 7ae112b88359fbaf4b9d7d1d1358ae57c5138768c57ba3a8fb930393662653b0512bfd7917c15890d1471577fb012fee8b73b4465e59b331739e6ee94f961683 languageName: node linkType: hard @@ -25944,6 +25883,86 @@ __metadata: languageName: node linkType: hard +"esbuild@npm:^0.21.0": + version: 0.21.5 + resolution: "esbuild@npm:0.21.5" + dependencies: + "@esbuild/aix-ppc64": 0.21.5 + "@esbuild/android-arm": 0.21.5 + "@esbuild/android-arm64": 0.21.5 + "@esbuild/android-x64": 0.21.5 + "@esbuild/darwin-arm64": 0.21.5 + "@esbuild/darwin-x64": 0.21.5 + "@esbuild/freebsd-arm64": 0.21.5 + "@esbuild/freebsd-x64": 0.21.5 + "@esbuild/linux-arm": 0.21.5 + "@esbuild/linux-arm64": 0.21.5 + "@esbuild/linux-ia32": 0.21.5 + "@esbuild/linux-loong64": 0.21.5 + "@esbuild/linux-mips64el": 0.21.5 + "@esbuild/linux-ppc64": 0.21.5 + "@esbuild/linux-riscv64": 0.21.5 + "@esbuild/linux-s390x": 0.21.5 + "@esbuild/linux-x64": 0.21.5 + "@esbuild/netbsd-x64": 0.21.5 + "@esbuild/openbsd-x64": 0.21.5 + "@esbuild/sunos-x64": 0.21.5 + "@esbuild/win32-arm64": 0.21.5 + "@esbuild/win32-ia32": 0.21.5 + "@esbuild/win32-x64": 0.21.5 + dependenciesMeta: + "@esbuild/aix-ppc64": + optional: true + "@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/linux-mips64el": + optional: true + "@esbuild/linux-ppc64": + optional: true + "@esbuild/linux-riscv64": + optional: true + "@esbuild/linux-s390x": + optional: true + "@esbuild/linux-x64": + optional: true + "@esbuild/netbsd-x64": + optional: true + "@esbuild/openbsd-x64": + optional: true + "@esbuild/sunos-x64": + optional: true + "@esbuild/win32-arm64": + optional: true + "@esbuild/win32-ia32": + optional: true + "@esbuild/win32-x64": + optional: true + bin: + esbuild: bin/esbuild + checksum: 2911c7b50b23a9df59a7d6d4cdd3a4f85855787f374dce751148dbb13305e0ce7e880dde1608c2ab7a927fc6cec3587b80995f7fc87a64b455f8b70b55fd8ec1 + languageName: node + linkType: hard + "esbuild@npm:esbuild-wasm@^0.15.15": version: 0.15.18 resolution: "esbuild-wasm@npm:0.15.18" @@ -25953,10 +25972,10 @@ __metadata: languageName: node linkType: hard -"escalade@npm:^3.1.1": - version: 3.1.1 - resolution: "escalade@npm:3.1.1" - checksum: a3e2a99f07acb74b3ad4989c48ca0c3140f69f923e56d0cba0526240ee470b91010f9d39001f2a4a313841d237ede70a729e92125191ba5d21e74b106800b133 +"escalade@npm:^3.1.1, escalade@npm:^3.1.2": + version: 3.1.2 + resolution: "escalade@npm:3.1.2" + checksum: 1ec0977aa2772075493002bdbd549d595ff6e9393b1cb0d7d6fcaf78c750da0c158f180938365486f75cb69fba20294351caddfce1b46552a7b6c3cde52eaa02 languageName: node linkType: hard @@ -26194,30 +26213,30 @@ __metadata: linkType: hard "eslint-plugin-react@npm:^7.28.0": - version: 7.34.1 - resolution: "eslint-plugin-react@npm:7.34.1" + version: 7.34.2 + resolution: "eslint-plugin-react@npm:7.34.2" dependencies: - array-includes: ^3.1.7 - array.prototype.findlast: ^1.2.4 + array-includes: ^3.1.8 + array.prototype.findlast: ^1.2.5 array.prototype.flatmap: ^1.3.2 array.prototype.toreversed: ^1.1.2 array.prototype.tosorted: ^1.1.3 doctrine: ^2.1.0 - es-iterator-helpers: ^1.0.17 + es-iterator-helpers: ^1.0.19 estraverse: ^5.3.0 jsx-ast-utils: ^2.4.1 || ^3.0.0 minimatch: ^3.1.2 - object.entries: ^1.1.7 - object.fromentries: ^2.0.7 - object.hasown: ^1.1.3 - object.values: ^1.1.7 + object.entries: ^1.1.8 + object.fromentries: ^2.0.8 + object.hasown: ^1.1.4 + object.values: ^1.2.0 prop-types: ^15.8.1 resolve: ^2.0.0-next.5 semver: ^6.3.1 - string.prototype.matchall: ^4.0.10 + string.prototype.matchall: ^4.0.11 peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - checksum: 82f391c5a093235c3bc2f664c54e009c49460778ee7d1b86c1536df9ac4d2a80d1dedc9241ac797df4a9dced936e955d9c89042fb3ac8d017b5359d1320d3c0f + checksum: aed331239f3a64fcd884380534ece4b8716f1eca4899c8636d04306879e6b4e7339e28e427bdd571d372b78b713025e0767e5f5b5486a8d19bff82616ebe8959 languageName: node linkType: hard @@ -26575,7 +26594,7 @@ __metadata: react-use: ^17.2.4 vite: ^4.4.9 vite-plugin-html: ^3.2.0 - vite-plugin-node-polyfills: ^0.21.0 + vite-plugin-node-polyfills: ^0.22.0 zen-observable: ^0.10.0 languageName: unknown linkType: soft @@ -26649,7 +26668,7 @@ __metadata: react-use: ^17.2.4 vite: ^4.4.9 vite-plugin-html: ^3.2.0 - vite-plugin-node-polyfills: ^0.21.0 + vite-plugin-node-polyfills: ^0.22.0 zen-observable: ^0.10.0 languageName: unknown linkType: soft @@ -27054,7 +27073,7 @@ __metadata: languageName: node linkType: hard -"fast-glob@npm:3.3.2, fast-glob@npm:^3.2.11, fast-glob@npm:^3.2.12, fast-glob@npm:^3.2.2, fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.2": +"fast-glob@npm:^3.2.11, fast-glob@npm:^3.2.12, fast-glob@npm:^3.2.2, fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.2": version: 3.3.2 resolution: "fast-glob@npm:3.3.2" dependencies: @@ -27251,16 +27270,6 @@ __metadata: languageName: node linkType: hard -"fetch-blob@npm:^2.1.1": - version: 2.1.2 - resolution: "fetch-blob@npm:2.1.2" - peerDependenciesMeta: - domexception: - optional: true - checksum: 22d4487ce78ea4e52b432b0057d8d42922d5d93c0374b0bc2692cebdcb11bf8fac4f6d141b31f1633db1e9212effd38385adbd765a2c7412a621307058499214 - languageName: node - linkType: hard - "figgy-pudding@npm:^3.5.1": version: 3.5.2 resolution: "figgy-pudding@npm:3.5.2" @@ -27336,13 +27345,6 @@ __metadata: languageName: node linkType: hard -"filter-iterator@npm:0.0.1": - version: 0.0.1 - resolution: "filter-iterator@npm:0.0.1" - checksum: 1dd34e0728183b3cc69d45c57ec58cbdd21c5160d53e70592e2db049ed4da81ba551b7bfaccb11731011ce5b07ee09961b09fa4573fe906145ce63d9a1813db0 - languageName: node - linkType: hard - "filter-obj@npm:^1.1.0": version: 1.1.0 resolution: "filter-obj@npm:1.1.0" @@ -27462,15 +27464,6 @@ __metadata: languageName: node linkType: hard -"find-yarn-workspace-root@npm:^2.0.0": - version: 2.0.0 - resolution: "find-yarn-workspace-root@npm:2.0.0" - dependencies: - micromatch: ^4.0.2 - checksum: fa5ca8f9d08fe7a54ce7c0a5931ff9b7e36f9ee7b9475fb13752bcea80ec6b5f180fa5102d60b376d5526ce924ea3fc6b19301262efa0a5d248dd710f3644242 - languageName: node - linkType: hard - "first-chunk-stream@npm:^2.0.0": version: 2.0.0 resolution: "first-chunk-stream@npm:2.0.0" @@ -27530,7 +27523,7 @@ __metadata: languageName: node linkType: hard -"follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.14.9, follow-redirects@npm:^1.15.4, follow-redirects@npm:^1.15.6": +"follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.14.9, follow-redirects@npm:^1.15.6": version: 1.15.6 resolution: "follow-redirects@npm:1.15.6" peerDependenciesMeta: @@ -28457,7 +28450,7 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.15, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.5, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.10, graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": +"graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.5, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.10, graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" checksum: ac85f94da92d8eb6b7f5a8b20ce65e43d66761c55ce85ac96df6865308390da45a8d3f0296dd3a663de65d30ba497bd46c696cc1e248c72b13d6d567138a4fc7 @@ -28935,15 +28928,6 @@ __metadata: languageName: node linkType: hard -"hosted-git-info@npm:^7.0.0": - version: 7.0.1 - resolution: "hosted-git-info@npm:7.0.1" - dependencies: - lru-cache: ^10.0.1 - checksum: be5280f0a20d6153b47e1ab578e09f5ae8ad734301b3ed7e547dc88a6814d7347a4888db1b4f9635cc738e3c0ef1fbff02272aba7d07c75d4c5a50ff8d618db6 - languageName: node - linkType: hard - "hpack.js@npm:^2.1.6": version: 2.1.6 resolution: "hpack.js@npm:2.1.6" @@ -28988,10 +28972,10 @@ __metadata: languageName: node linkType: hard -"html-entities@npm:^2.1.0, html-entities@npm:^2.4.0": - version: 2.4.0 - resolution: "html-entities@npm:2.4.0" - checksum: 25bea32642ce9ebd0eedc4d24381883ecb0335ccb8ac26379a0958b9b16652fdbaa725d70207ce54a51db24103436a698a8e454397d3ba8ad81460224751f1dc +"html-entities@npm:^2.1.0, html-entities@npm:^2.4.0, html-entities@npm:^2.5.2": + version: 2.5.2 + resolution: "html-entities@npm:2.5.2" + checksum: b23f4a07d33d49ade1994069af4e13d31650e3fb62621e92ae10ecdf01d1a98065c78fd20fdc92b4c7881612210b37c275f2c9fba9777650ab0d6f2ceb3b99b6 languageName: node linkType: hard @@ -29271,9 +29255,9 @@ __metadata: linkType: hard "humanize-duration@npm:^3.25.1": - version: 3.32.0 - resolution: "humanize-duration@npm:3.32.0" - checksum: fd12af03045278c24542d2222d46831f74d21a2132bba053d4847ff8c8f6799840db6ff8a14ce24cc920f69633970fbde4f83d7cbcfed26806ed21804e72a03a + version: 3.32.1 + resolution: "humanize-duration@npm:3.32.1" + checksum: 17f6f2ec09a931eb0bf7de1fc8ac01f90174f366f60390289bd0797c6e4545255bd5d770dd18909c9b21685d76cc190b3a8ec880d2ecc088a1ad032e0d2f57cb languageName: node linkType: hard @@ -29508,13 +29492,6 @@ __metadata: languageName: node linkType: hard -"individual@npm:^3.0.0": - version: 3.0.0 - resolution: "individual@npm:3.0.0" - checksum: 49f69cff2791f09d1364b39723cc03d8d48ae425b15b23c8f618ac81f8d76160dae9c2abde5fb885a6bfbce939017ba2a5c84cf3d8051d0804fca0ee79138aa2 - languageName: node - linkType: hard - "infer-owner@npm:^1.0.4": version: 1.0.4 resolution: "infer-owner@npm:1.0.4" @@ -29657,7 +29634,7 @@ __metadata: languageName: node linkType: hard -"internal-slot@npm:^1.0.5, internal-slot@npm:^1.0.7": +"internal-slot@npm:^1.0.7": version: 1.0.7 resolution: "internal-slot@npm:1.0.7" dependencies: @@ -29908,7 +29885,7 @@ __metadata: languageName: node linkType: hard -"is-core-module@npm:^2.1.0, is-core-module@npm:^2.13.0, is-core-module@npm:^2.13.1, is-core-module@npm:^2.8.1": +"is-core-module@npm:^2.1.0, is-core-module@npm:^2.13.0, is-core-module@npm:^2.13.1": version: 2.13.1 resolution: "is-core-module@npm:2.13.1" dependencies: @@ -30471,7 +30448,7 @@ __metadata: languageName: node linkType: hard -"is-wsl@npm:^2.1.1, is-wsl@npm:^2.2.0": +"is-wsl@npm:^2.2.0": version: 2.2.0 resolution: "is-wsl@npm:2.2.0" dependencies: @@ -30583,10 +30560,10 @@ __metadata: linkType: hard "isomorphic-git@npm:^1.23.0": - version: 1.25.7 - resolution: "isomorphic-git@npm:1.25.7" + version: 1.25.10 + resolution: "isomorphic-git@npm:1.25.10" dependencies: - async-lock: ^1.1.0 + async-lock: ^1.4.1 clean-git-ref: ^2.0.1 crc-32: ^1.2.0 diff3: 0.0.3 @@ -30599,7 +30576,7 @@ __metadata: simple-get: ^4.0.1 bin: isogit: cli.cjs - checksum: 6655c70c8c9974c907f6ca864ca16b0aed113ca8b6f50de4858a624b2ed66633a83ce64ca8935f370e328a29bc37811447eb7494be379388123feb811e867459 + checksum: 69e358e47a3677e1251ae3becf56ec7b2dd63e191516800647c341b101f4d40f42d185cb80acc1f8c71b4d6bf417b44b75233d2581a63c3eda69dd2c1a33886f languageName: node linkType: hard @@ -31283,12 +31260,12 @@ __metadata: languageName: node linkType: hard -"jiti@npm:1.21.0, jiti@npm:^1.18.2": - version: 1.21.0 - resolution: "jiti@npm:1.21.0" +"jiti@npm:^1.18.2, jiti@npm:^1.21.0": + version: 1.21.6 + resolution: "jiti@npm:1.21.6" bin: jiti: bin/jiti.js - checksum: a7bd5d63921c170eaec91eecd686388181c7828e1fa0657ab374b9372bfc1f383cf4b039e6b272383d5cb25607509880af814a39abdff967322459cca41f2961 + checksum: 9ea4a70a7bb950794824683ed1c632e2ede26949fbd348e2ba5ec8dc5efa54dc42022d85ae229cadaa60d4b95012e80ea07d625797199b688cc22ab0e8891d32 languageName: node linkType: hard @@ -31375,7 +31352,7 @@ __metadata: languageName: node linkType: hard -"js-yaml@npm:4.1.0, js-yaml@npm:=4.1.0, js-yaml@npm:^4.0.0, js-yaml@npm:^4.1.0": +"js-yaml@npm:=4.1.0, js-yaml@npm:^4.0.0, js-yaml@npm:^4.1.0": version: 4.1.0 resolution: "js-yaml@npm:4.1.0" dependencies: @@ -31608,13 +31585,6 @@ __metadata: languageName: node linkType: hard -"json-parse-even-better-errors@npm:^3.0.0": - version: 3.0.1 - resolution: "json-parse-even-better-errors@npm:3.0.1" - checksum: bf74fa3f715e56699ccd68b80a7d20908de432a3fae2d5aa2ed530a148e9d9ccdf8e6983b93d9966a553aa70dcf003ce3a7ffec2c0ce74d2a6173e3691a426f0 - languageName: node - linkType: hard - "json-pointer@npm:0.6.2": version: 0.6.2 resolution: "json-pointer@npm:0.6.2" @@ -31634,8 +31604,8 @@ __metadata: linkType: hard "json-schema-library@npm:^9.0.0": - version: 9.3.4 - resolution: "json-schema-library@npm:9.3.4" + version: 9.3.5 + resolution: "json-schema-library@npm:9.3.5" dependencies: "@sagold/json-pointer": ^5.1.2 "@sagold/json-query": ^6.1.3 @@ -31644,7 +31614,7 @@ __metadata: fast-deep-equal: ^3.1.3 smtp-address-parser: 1.0.10 valid-url: ^1.0.9 - checksum: 6e3accc45bdf0fe4831c8b2a560d8feaa9402bd6c5833a0c7e11ee78c316b17a389a3368a7ee2c989d4aac36018742d7dcc83c66b11170c54800b0e56418638f + checksum: 8c8a8c993f998a3485d5675781a0330f4e5abc43781f1fa03b709dd5a5157fb2a524c704966f8c4fc31873c5816d4a07058214873b78b1d54f8b4a0cf6737bcf languageName: node linkType: hard @@ -31704,7 +31674,7 @@ __metadata: languageName: node linkType: hard -"json-stable-stringify@npm:^1.0.1, json-stable-stringify@npm:^1.0.2": +"json-stable-stringify@npm:^1.0.1": version: 1.0.2 resolution: "json-stable-stringify@npm:1.0.2" dependencies: @@ -31738,7 +31708,7 @@ __metadata: languageName: node linkType: hard -"json5@npm:^2.1.2, json5@npm:^2.1.3, json5@npm:^2.2.3": +"json5@npm:^2.1.2, json5@npm:^2.1.3, json5@npm:^2.2.2, json5@npm:^2.2.3": version: 2.2.3 resolution: "json5@npm:2.2.3" bin: @@ -32068,15 +32038,6 @@ __metadata: languageName: node linkType: hard -"klaw-sync@npm:^6.0.0": - version: 6.0.0 - resolution: "klaw-sync@npm:6.0.0" - dependencies: - graceful-fs: ^4.1.11 - checksum: 0da397f8961313c3ef8f79fb63af9002cde5a8fb2aeb1a37351feff0dd6006129c790400c3f5c3b4e757bedcabb13d21ec0a5eaef5a593d59515d4f2c291e475 - languageName: node - linkType: hard - "kleur@npm:^3.0.3": version: 3.0.3 resolution: "kleur@npm:3.0.3" @@ -32131,30 +32092,25 @@ __metadata: linkType: hard "knip@npm:^5.0.0": - version: 5.9.4 - resolution: "knip@npm:5.9.4" + version: 5.22.2 + resolution: "knip@npm:5.22.2" dependencies: - "@ericcornelissen/bash-parser": 0.5.2 + "@ericcornelissen/bash-parser": 0.5.3 "@nodelib/fs.walk": 2.0.0 - "@npmcli/map-workspaces": ^3.0.4 - "@npmcli/package-json": ^5.0.0 - "@pnpm/logger": 5.0.0 - "@pnpm/workspace.pkgs-graph": 2.0.14 "@snyk/github-codeowners": 1.1.0 - "@types/picomatch": 2.3.3 easy-table: 1.2.0 - fast-glob: 3.3.2 - jiti: 1.21.0 - js-yaml: 4.1.0 - micromatch: 4.0.5 - minimist: 1.2.8 - picocolors: 1.0.0 + fast-glob: ^3.3.2 + jiti: ^1.21.0 + js-yaml: ^4.1.0 + minimist: ^1.2.8 + picocolors: ^1.0.0 picomatch: ^4.0.1 - pretty-ms: 9.0.0 - resolve: 1.22.8 - smol-toml: 1.1.4 + pretty-ms: ^9.0.0 + resolve: ^1.22.8 + smol-toml: ^1.1.4 strip-json-comments: 5.0.1 summary: 2.1.0 + tsconfig-paths: ^4.2.0 zod: ^3.22.4 zod-validation-error: ^3.0.3 peerDependencies: @@ -32162,7 +32118,8 @@ __metadata: typescript: ">=5.0.4" bin: knip: bin/knip.js - checksum: 112f93982090c8947bd28904ad835b4b2793f9ee23fcb895ba0815e759d6b644e9d6ff6d6661af56ecbebb2f6bff21e4e3afcccce93df778aadf9c6d52ca9541 + knip-bun: bin/knip-bun.js + checksum: 995924973618391af39ba6bfb324f1f4dac427879a944eeecbcf48b61ec165f10f18196f27a7d079076f351223ed067bb917bc863e0424153c3fae2dd65582d6 languageName: node linkType: hard @@ -32368,8 +32325,8 @@ __metadata: linkType: hard "lint-staged@npm:^15.0.0": - version: 15.2.5 - resolution: "lint-staged@npm:15.2.5" + version: 15.2.7 + resolution: "lint-staged@npm:15.2.7" dependencies: chalk: ~5.3.0 commander: ~12.1.0 @@ -32383,7 +32340,7 @@ __metadata: yaml: ~2.4.2 bin: lint-staged: bin/lint-staged.js - checksum: 3025868d965eb401a5ebd903abd70cfebb8dbeb41eea1020c316f9c8c79083ea203f6cef95d32bfa8c9ec5486392b4ed08632ace6a5347b69cf238ba00e178f0 + checksum: 0f21d1b44c046fcfc0388dab66d45d244818afdb24bdf57e7593640c7ca82cc55be7d75e086708e453fac0c0d9ab8760b2cde053944f7b2121c2dd65f6367ffe languageName: node linkType: hard @@ -32408,18 +32365,6 @@ __metadata: languageName: node linkType: hard -"load-json-file@npm:^6.2.0": - version: 6.2.0 - resolution: "load-json-file@npm:6.2.0" - dependencies: - graceful-fs: ^4.1.15 - parse-json: ^5.0.0 - strip-bom: ^4.0.0 - type-fest: ^0.6.0 - checksum: 4429e430ebb99375fc7cd936348e4f7ba729486080ced4272091c1e386a7f5f738ea3337d8ffd4b01c2f5bc3ddde92f2c780045b66838fe98bdb79f901884643 - languageName: node - linkType: hard - "load-yaml-file@npm:^0.2.0": version: 0.2.0 resolution: "load-yaml-file@npm:0.2.0" @@ -32862,7 +32807,7 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^10.0.0, lru-cache@npm:^10.0.1, lru-cache@npm:^10.0.2, lru-cache@npm:^9.1.1 || ^10.0.0": +"lru-cache@npm:^10.0.0, lru-cache@npm:^10.0.1, lru-cache@npm:^9.1.1 || ^10.0.0": version: 10.2.0 resolution: "lru-cache@npm:10.2.0" checksum: eee7ddda4a7475deac51ac81d7dd78709095c6fa46e8350dc2d22462559a1faa3b81ed931d5464b13d48cbd7e08b46100b6f768c76833912bc444b99c37e25db @@ -32975,12 +32920,12 @@ __metadata: languageName: node linkType: hard -"magic-string@npm:^0.30.3, magic-string@npm:^0.30.4": - version: 0.30.8 - resolution: "magic-string@npm:0.30.8" +"magic-string@npm:^0.30.10, magic-string@npm:^0.30.3": + version: 0.30.10 + resolution: "magic-string@npm:0.30.10" dependencies: "@jridgewell/sourcemap-codec": ^1.4.15 - checksum: 79922f4500d3932bb587a04440d98d040170decf432edc0f91c0bf8d41db16d364189bf800e334170ac740918feda62cd39dcc170c337dc18050cfcf00a5f232 + checksum: 456fd47c39b296c47dff967e1965121ace35417eab7f45a99e681e725b8661b48e1573c366ee67a27715025b3740773c46b088f115421c7365ea4ea6fa10d399 languageName: node linkType: hard @@ -33086,15 +33031,6 @@ __metadata: languageName: node linkType: hard -"map-age-cleaner@npm:^0.1.3": - version: 0.1.3 - resolution: "map-age-cleaner@npm:0.1.3" - dependencies: - p-defer: ^1.0.0 - checksum: cb2804a5bcb3cbdfe4b59066ea6d19f5e7c8c196cd55795ea4c28f792b192e4c442426ae52524e5e1acbccf393d3bddacefc3d41f803e66453f6c4eda3650bc1 - languageName: node - linkType: hard - "map-age-cleaner@npm:^0.2.0": version: 0.2.0 resolution: "map-age-cleaner@npm:0.2.0" @@ -33175,13 +33111,13 @@ __metadata: linkType: hard "material-ui-confirm@npm:^3.0.12": - version: 3.0.12 - resolution: "material-ui-confirm@npm:3.0.12" + version: 3.0.16 + resolution: "material-ui-confirm@npm:3.0.16" peerDependencies: "@mui/material": ">= 5.0.0" react: ^17.0.0 || ^18.0.0 react-dom: ^17.0.0 || ^18.0.0 - checksum: de1092fdc4ab8104fbfdb5034921aeb2a5db5854ad5e31fb24dc4c204c6fb5b66a33ad377abf7adda390c432aefe96a2188ef1b8a3b9c1a80a9a28af63833458 + checksum: 10114de3ac1dfd25cd46d151fa011bf7fa07376199a9cd62c8fbc619d0f711204c7a6bcf124e1ef6752f39377b04c09eb63e470e53d08a52aae5a46ee7a35a79 languageName: node linkType: hard @@ -33433,26 +33369,6 @@ __metadata: languageName: node linkType: hard -"mem@npm:^6.0.1": - version: 6.1.1 - resolution: "mem@npm:6.1.1" - dependencies: - map-age-cleaner: ^0.1.3 - mimic-fn: ^3.0.0 - checksum: 59a54b66838f074354fd2ae32cca5064996761ded870e74fa1e098bb3e5d48fc033ebeacf6809d4b2ad3036f7a6fb7538858821bbd4f1cfb7ef8966c0ab9b753 - languageName: node - linkType: hard - -"mem@npm:^8.0.0": - version: 8.1.1 - resolution: "mem@npm:8.1.1" - dependencies: - map-age-cleaner: ^0.1.3 - mimic-fn: ^3.1.0 - checksum: c41bc97f6f82b91899206058989e34bcb1543af40413c2ab59e5a8e97e4f8f2188d62e7bd95b2d575d5b0d823d5034a0f274a0676f6d11a0e0b973898b06c8b1 - languageName: node - linkType: hard - "memfs@npm:^3.1.2, memfs@npm:^3.4.1": version: 3.5.3 resolution: "memfs@npm:3.5.3" @@ -33895,16 +33811,6 @@ __metadata: languageName: node linkType: hard -"micromatch@npm:4.0.5": - version: 4.0.5 - resolution: "micromatch@npm:4.0.5" - dependencies: - braces: ^3.0.2 - picomatch: ^2.3.1 - checksum: 02a17b671c06e8fefeeb6ef996119c1e597c942e632a21ef589154f23898c9c6a9858526246abb14f8bca6e77734aa9dcf65476fca47cedfb80d9577d52843fc - languageName: node - linkType: hard - "micromatch@npm:^4.0.2, micromatch@npm:^4.0.4, micromatch@npm:^4.0.5, micromatch@npm:~4.0.7": version: 4.0.7 resolution: "micromatch@npm:4.0.7" @@ -34002,7 +33908,7 @@ __metadata: languageName: node linkType: hard -"mimic-fn@npm:^3.0.0, mimic-fn@npm:^3.1.0": +"mimic-fn@npm:^3.0.0": version: 3.1.0 resolution: "mimic-fn@npm:3.1.0" checksum: f7b167f9115b8bbdf2c3ee55dce9149d14be9e54b237259c4bc1d8d0512ea60f25a1b323f814eb1fe8f5a541662804bcfcfff3202ca58df143edb986849d58db @@ -34144,7 +34050,7 @@ __metadata: languageName: node linkType: hard -"minimist@npm:1.2.8, minimist@npm:^1.2.0, minimist@npm:^1.2.3, minimist@npm:^1.2.5, minimist@npm:^1.2.6": +"minimist@npm:^1.2.0, minimist@npm:^1.2.3, minimist@npm:^1.2.5, minimist@npm:^1.2.6, minimist@npm:^1.2.8": version: 1.2.8 resolution: "minimist@npm:1.2.8" checksum: 75a6d645fb122dad29c06a7597bddea977258957ed88d7a6df59b5cd3fe4a527e253e9bbf2e783e4b73657f9098b96a5fe96ab8a113655d4109108577ecf85b0 @@ -34500,14 +34406,14 @@ __metadata: linkType: hard "msw@npm:^2.0.0, msw@npm:^2.0.8": - version: 2.2.14 - resolution: "msw@npm:2.2.14" + version: 2.3.1 + resolution: "msw@npm:2.3.1" dependencies: "@bundled-es-modules/cookie": ^2.0.0 "@bundled-es-modules/statuses": ^1.0.1 "@inquirer/confirm": ^3.0.0 "@mswjs/cookies": ^1.1.0 - "@mswjs/interceptors": ^0.26.14 + "@mswjs/interceptors": ^0.29.0 "@open-draft/until": ^2.1.0 "@types/cookie": ^0.6.0 "@types/statuses": ^2.0.4 @@ -34527,7 +34433,7 @@ __metadata: optional: true bin: msw: cli/index.js - checksum: a958b38314f42b733f67ac176e753680f28da862212ab671aa40607b017a577797dcc323e997a3d6c0b2d3f13cc2a3458d4941574e08c916a6b8beeb91d8501a + checksum: bae72567488822889cc5c18318206c847b85d1df4c7bff0eac62e3fa902b95dd2e36710e3679829eaceb9c4f5066f9ed441afd919b304fba111fe2dacf82cefb languageName: node linkType: hard @@ -34586,8 +34492,8 @@ __metadata: linkType: hard "mysql2@npm:^3.0.0": - version: 3.10.0 - resolution: "mysql2@npm:3.10.0" + version: 3.10.1 + resolution: "mysql2@npm:3.10.1" dependencies: denque: ^2.1.0 generate-function: ^2.3.1 @@ -34597,7 +34503,7 @@ __metadata: named-placeholders: ^1.1.3 seq-queue: ^0.0.5 sqlstring: ^2.3.2 - checksum: 4306de21317a05fcd4bbf28679e6b61b5e3421f7b8e2813ce7be8a06a8f7f4e09067bbd77507de465aba59a5742d1c48a3ed1038e96fb76935d24e1648d4b9c3 + checksum: 293e1a76bfdbde146285ee7028336da7693b5dfb507a7c264216fdb3fe2088ba0f5d5a45a0a9e7c4de4f39c3f44edbe890fb05b28299d6c731fc2e4a281836e3 languageName: node linkType: hard @@ -34853,16 +34759,6 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:3.0.0-beta.9": - version: 3.0.0-beta.9 - resolution: "node-fetch@npm:3.0.0-beta.9" - dependencies: - data-uri-to-buffer: ^3.0.1 - fetch-blob: ^2.1.1 - checksum: 586af0910649cb62f1c044ddac41e71c0b0f48133fba406ad5e0fab51baff18f22cd187ea65ef690ceed7386a71910e904348105dc8eae55f907fa94df7e76ca - languageName: node - linkType: hard - "node-fetch@npm:^2.6.0, node-fetch@npm:^2.6.1, node-fetch@npm:^2.6.12, node-fetch@npm:^2.6.7, node-fetch@npm:^2.6.9, node-fetch@npm:^2.7.0": version: 2.7.0 resolution: "node-fetch@npm:2.7.0" @@ -35018,10 +34914,10 @@ __metadata: languageName: node linkType: hard -"node-releases@npm:^2.0.13": - version: 2.0.13 - resolution: "node-releases@npm:2.0.13" - checksum: 17ec8f315dba62710cae71a8dad3cd0288ba943d2ece43504b3b1aa8625bf138637798ab470b1d9035b0545996f63000a8a926e0f6d35d0996424f8b6d36dda3 +"node-releases@npm:^2.0.14": + version: 2.0.14 + resolution: "node-releases@npm:2.0.14" + checksum: 59443a2f77acac854c42d321bf1b43dea0aef55cd544c6a686e9816a697300458d4e82239e2d794ea05f7bbbc8a94500332e2d3ac3f11f52e4b16cbe638b3c41 languageName: node linkType: hard @@ -35149,18 +35045,6 @@ __metadata: languageName: node linkType: hard -"normalize-package-data@npm:^6.0.0": - version: 6.0.0 - resolution: "normalize-package-data@npm:6.0.0" - dependencies: - hosted-git-info: ^7.0.0 - is-core-module: ^2.8.1 - semver: ^7.3.5 - validate-npm-package-license: ^3.0.4 - checksum: 741211a4354ba6d618caffa98f64e0e5ec9e5575bf3aefe47f4b68e662d65f9ba1b6b2d10640c16254763ed0879288155566138b5ffe384172352f6e969c1752 - languageName: node - linkType: hard - "normalize-path@npm:^2.1.1": version: 2.1.1 resolution: "normalize-path@npm:2.1.1" @@ -35231,15 +35115,6 @@ __metadata: languageName: node linkType: hard -"npm-install-checks@npm:^6.0.0": - version: 6.3.0 - resolution: "npm-install-checks@npm:6.3.0" - dependencies: - semver: ^7.1.1 - checksum: 6c20dadb878a0d2f1f777405217b6b63af1299d0b43e556af9363ee6eefaa98a17dfb7b612a473a473e96faf7e789c58b221e0d8ffdc1d34903c4f71618df3b4 - languageName: node - linkType: hard - "npm-normalize-package-bin@npm:^1.0.0, npm-normalize-package-bin@npm:^1.0.1": version: 1.0.1 resolution: "npm-normalize-package-bin@npm:1.0.1" @@ -35254,25 +35129,6 @@ __metadata: languageName: node linkType: hard -"npm-normalize-package-bin@npm:^3.0.0": - version: 3.0.1 - resolution: "npm-normalize-package-bin@npm:3.0.1" - checksum: de416d720ab22137a36292ff8a333af499ea0933ef2320a8c6f56a73b0f0448227fec4db5c890d702e26d21d04f271415eab6580b5546456861cc0c19498a4bf - languageName: node - linkType: hard - -"npm-package-arg@npm:^11.0.0": - version: 11.0.1 - resolution: "npm-package-arg@npm:11.0.1" - dependencies: - hosted-git-info: ^7.0.0 - proc-log: ^3.0.0 - semver: ^7.3.5 - validate-npm-package-name: ^5.0.0 - checksum: 60364504e04e34fc20b47ad192efc9181922bce0cb41fa81871b1b75748d8551725f61b2f9a2e3dffb1782d749a35313f5dc02c18c3987653990d486f223adf2 - languageName: node - linkType: hard - "npm-package-arg@npm:^8.0.1, npm-package-arg@npm:^8.1.2, npm-package-arg@npm:^8.1.5": version: 8.1.5 resolution: "npm-package-arg@npm:8.1.5" @@ -35324,18 +35180,6 @@ __metadata: languageName: node linkType: hard -"npm-pick-manifest@npm:^9.0.0": - version: 9.0.0 - resolution: "npm-pick-manifest@npm:9.0.0" - dependencies: - npm-install-checks: ^6.0.0 - npm-normalize-package-bin: ^3.0.0 - npm-package-arg: ^11.0.0 - semver: ^7.3.5 - checksum: a6f102f9e9e8feea69be3a65e492fef6319084a85fc4e40dc88a277a3aa675089cef13ab0436ed7916e97c7bbba8315633d818eb15402c3abfb0bddc1af08cc7 - languageName: node - linkType: hard - "npm-registry-fetch@npm:^12.0.0, npm-registry-fetch@npm:^12.0.1": version: 12.0.2 resolution: "npm-registry-fetch@npm:12.0.2" @@ -35534,25 +35378,26 @@ __metadata: languageName: node linkType: hard -"object.entries@npm:^1.1.7": - version: 1.1.7 - resolution: "object.entries@npm:1.1.7" +"object.entries@npm:^1.1.7, object.entries@npm:^1.1.8": + version: 1.1.8 + resolution: "object.entries@npm:1.1.8" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - checksum: da287d434e7e32989586cd734382364ba826a2527f2bc82e6acbf9f9bfafa35d51018b66ec02543ffdfa2a5ba4af2b6f1ca6e588c65030cb4fd9c67d6ced594c + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-object-atoms: ^1.0.0 + checksum: 5314877cb637ef3437a30bba61d9bacdb3ce74bf73ac101518be0633c37840c8cc67407edb341f766e8093b3d7516d5c3358f25adfee4a2c697c0ec4c8491907 languageName: node linkType: hard -"object.fromentries@npm:^2.0.7": - version: 2.0.7 - resolution: "object.fromentries@npm:2.0.7" +"object.fromentries@npm:^2.0.7, object.fromentries@npm:^2.0.8": + version: 2.0.8 + resolution: "object.fromentries@npm:2.0.8" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - checksum: 7341ce246e248b39a431b87a9ddd331ff52a454deb79afebc95609f94b1f8238966cf21f52188f2a353f0fdf83294f32f1ebf1f7826aae915ebad21fd0678065 + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + es-object-atoms: ^1.0.0 + checksum: 29b2207a2db2782d7ced83f93b3ff5d425f901945f3665ffda1821e30a7253cd1fd6b891a64279976098137ddfa883d748787a6fea53ecdb51f8df8b8cec0ae1 languageName: node linkType: hard @@ -35568,24 +35413,25 @@ __metadata: languageName: node linkType: hard -"object.hasown@npm:^1.1.3": - version: 1.1.3 - resolution: "object.hasown@npm:1.1.3" +"object.hasown@npm:^1.1.4": + version: 1.1.4 + resolution: "object.hasown@npm:1.1.4" dependencies: - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - checksum: 76bc17356f6124542fb47e5d0e78d531eafa4bba3fc2d6fc4b1a8ce8b6878912366c0d99f37ce5c84ada8fd79df7aa6ea1214fddf721f43e093ad2df51f27da1 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + es-object-atoms: ^1.0.0 + checksum: bc46eb5ca22106fcd07aab1411508c2c68b7565fe8fb272f166fb9bf203972e8b5c86a5a4b2c86204beead0626a7a4119d32cefbaf7c5dd57b400bf9e6363cb6 languageName: node linkType: hard -"object.values@npm:^1.1.6, object.values@npm:^1.1.7": - version: 1.1.7 - resolution: "object.values@npm:1.1.7" +"object.values@npm:^1.1.6, object.values@npm:^1.1.7, object.values@npm:^1.2.0": + version: 1.2.0 + resolution: "object.values@npm:1.2.0" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - checksum: f3e4ae4f21eb1cc7cebb6ce036d4c67b36e1c750428d7b7623c56a0db90edced63d08af8a316d81dfb7c41a3a5fa81b05b7cc9426e98d7da986b1682460f0777 + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-object-atoms: ^1.0.0 + checksum: 51fef456c2a544275cb1766897f34ded968b22adfc13ba13b5e4815fdaf4304a90d42a3aee114b1f1ede048a4890381d47a5594d84296f2767c6a0364b9da8fa languageName: node linkType: hard @@ -35712,16 +35558,6 @@ __metadata: languageName: node linkType: hard -"open@npm:^7.4.2": - version: 7.4.2 - resolution: "open@npm:7.4.2" - dependencies: - is-docker: ^2.0.0 - is-wsl: ^2.1.1 - checksum: 3333900ec0e420d64c23b831bc3467e57031461d843c801f569b2204a1acc3cd7b3ec3c7897afc9dde86491dfa289708eb92bba164093d8bd88fb2c231843c91 - languageName: node - linkType: hard - "open@npm:^8.0.0, open@npm:^8.4.0": version: 8.4.0 resolution: "open@npm:8.4.0" @@ -35734,13 +35570,22 @@ __metadata: linkType: hard "openapi-merge@npm:^1.3.2": - version: 1.3.2 - resolution: "openapi-merge@npm:1.3.2" + version: 1.3.3 + resolution: "openapi-merge@npm:1.3.3" dependencies: atlassian-openapi: ^1.0.8 lodash: ^4.17.15 ts-is-present: ^1.1.1 - checksum: 53284a563270177422db8c7536544913c133dfc5cc7058a1043f3092b5aa997b8224a83c59569d18620f94ccf0a014fcb735e22941a9259b2c60861002f01638 + checksum: d23ed060facb72f52088cf59bf10abbd36e169bf727c634582904ab0cddfa697b2af0d0e720d908154c2966b80344a8d59811827582949e1e9ffd2acdbc70537 + languageName: node + linkType: hard + +"openapi-path-templating@npm:^1.5.1": + version: 1.5.3 + resolution: "openapi-path-templating@npm:1.5.3" + dependencies: + apg-lite: ^1.0.3 + checksum: 064e79f172bc21f4240bc26c2539ffdf9a4f462f58e5014dae30d2ea843e22aa7a22d57de72fe26b8512e0038e9e3bccbd8f5af47cc1a419076dac9dad4ce370 languageName: node linkType: hard @@ -35754,6 +35599,15 @@ __metadata: languageName: node linkType: hard +"openapi-server-url-templating@npm:^1.0.0": + version: 1.0.0 + resolution: "openapi-server-url-templating@npm:1.0.0" + dependencies: + apg-lite: ^1.0.3 + checksum: 97e21c0a9610ebda7098c5c4022b27943382e84dfb6e3f8258cb0b33748f73f90e50424adb2f7ccd115c0bcdd81ffa1146c5ad7f188eb627de69b565abbcf648 + languageName: node + linkType: hard + "openapi-types@npm:^12.0.0, openapi-types@npm:^12.0.2": version: 12.1.3 resolution: "openapi-types@npm:12.1.3" @@ -35978,16 +35832,6 @@ __metadata: languageName: node linkType: hard -"p-memoize@npm:4.0.1": - version: 4.0.1 - resolution: "p-memoize@npm:4.0.1" - dependencies: - mem: ^6.0.1 - mimic-fn: ^3.0.0 - checksum: 322294f7d8c6112cc961cf48f3e08eadc5fa0da7bc457db1a3f6f6c72d9745ae098255584d67a62367707551c514825917c86773e60c27cc341eabc9636d0a0d - languageName: node - linkType: hard - "p-queue@npm:^6.6.2": version: 6.6.2 resolution: "p-queue@npm:6.6.2" @@ -36214,15 +36058,6 @@ __metadata: languageName: node linkType: hard -"parse-npm-tarball-url@npm:^3.0.0": - version: 3.0.0 - resolution: "parse-npm-tarball-url@npm:3.0.0" - dependencies: - semver: ^6.1.0 - checksum: 4a6c1048a86465570fe128d69aa4d5a4a9916cbdf86ac39e43fca3fea16554905cafa4b351bf6274ce131e698412fd89157b372abed29dfd8e6aea9e67b3a717 - languageName: node - linkType: hard - "parse-path@npm:^7.0.0": version: 7.0.0 resolution: "parse-path@npm:7.0.0" @@ -36421,31 +36256,6 @@ __metadata: languageName: node linkType: hard -"patch-package@npm:^8.0.0": - version: 8.0.0 - resolution: "patch-package@npm:8.0.0" - dependencies: - "@yarnpkg/lockfile": ^1.1.0 - chalk: ^4.1.2 - ci-info: ^3.7.0 - cross-spawn: ^7.0.3 - find-yarn-workspace-root: ^2.0.0 - fs-extra: ^9.0.0 - json-stable-stringify: ^1.0.2 - klaw-sync: ^6.0.0 - minimist: ^1.2.6 - open: ^7.4.2 - rimraf: ^2.6.3 - semver: ^7.5.3 - slash: ^2.0.0 - tmp: ^0.0.33 - yaml: ^2.2.2 - bin: - patch-package: index.js - checksum: d23cddc4d1622e2d8c7ca31b145c6eddb24bd271f69905e766de5e1f199f0b9a5479a6a6939ea857288399d4ed249285639d539a2c00fbddb7daa39934b007a2 - languageName: node - linkType: hard - "path-browserify@npm:0.0.1": version: 0.0.1 resolution: "path-browserify@npm:0.0.1" @@ -36533,15 +36343,6 @@ __metadata: languageName: node linkType: hard -"path-temp@npm:^2.1.0": - version: 2.1.0 - resolution: "path-temp@npm:2.1.0" - dependencies: - unique-string: ^2.0.0 - checksum: ad28022a9c807d17d729c3ee265cd51a36f2d0283c9b1daee02dfd84fa2e4944b93e0a8d07bd5c2ed678c3c6c048d011c1817a181f6a3f03cd3a9648faef1b7d - languageName: node - linkType: hard - "path-to-regexp@npm:0.1.7": version: 0.1.7 resolution: "path-to-regexp@npm:0.1.7" @@ -36772,10 +36573,10 @@ __metadata: languageName: node linkType: hard -"picocolors@npm:1.0.0, picocolors@npm:^1.0.0": - version: 1.0.0 - resolution: "picocolors@npm:1.0.0" - checksum: a2e8092dd86c8396bdba9f2b5481032848525b3dc295ce9b57896f931e63fc16f79805144321f72976383fc249584672a75cc18d6777c6b757603f372f745981 +"picocolors@npm:^1.0.0, picocolors@npm:^1.0.1": + version: 1.0.1 + resolution: "picocolors@npm:1.0.1" + checksum: fa68166d1f56009fc02a34cdfd112b0dd3cf1ef57667ac57281f714065558c01828cdf4f18600ad6851cbe0093952ed0660b1e0156bddf2184b6aaf5817553a5 languageName: node linkType: hard @@ -36936,27 +36737,27 @@ __metadata: languageName: node linkType: hard -"playwright-core@npm:1.43.1": - version: 1.43.1 - resolution: "playwright-core@npm:1.43.1" +"playwright-core@npm:1.44.1": + version: 1.44.1 + resolution: "playwright-core@npm:1.44.1" bin: playwright-core: cli.js - checksum: 7c96b3a4a4bce2ee22c3cd680c9b0bb9e4bf07ee4b51d1e9a7f47a6489c7b0b960d4b550e530b8f41d1ffeadd26c7c6bb626ae8689dfd90dce1cb8e35ae78ff7 + checksum: ebc6fa0ff77792fe52648fda06cc4474d4e9746db6dc5750d262b7fe2caf9f9e2327a71f1fb365e862213403a9daf95361c5040a9b0fd462928d7eb4fdc760e1 languageName: node linkType: hard -"playwright@npm:1.43.1": - version: 1.43.1 - resolution: "playwright@npm:1.43.1" +"playwright@npm:1.44.1": + version: 1.44.1 + resolution: "playwright@npm:1.44.1" dependencies: fsevents: 2.3.2 - playwright-core: 1.43.1 + playwright-core: 1.44.1 dependenciesMeta: fsevents: optional: true bin: playwright: cli.js - checksum: de9db021f93018a18275bbb5af09ebf1804aa0534f47578b35b440064abc774509740205802824afc94a99fc84dd55ffe9e215718ad3ecc691b251ab3882b096 + checksum: c2e8ff0a855e4a9e665ae5ffa0ff90423289546157be55e83f78916d17075c5910a7244773739c2a973da884a4ff0b3cf9b6e6b543de112e43b12169a9208e86 languageName: node linkType: hard @@ -37639,7 +37440,7 @@ __metadata: languageName: node linkType: hard -"pretty-ms@npm:9.0.0": +"pretty-ms@npm:^9.0.0": version: 9.0.0 resolution: "pretty-ms@npm:9.0.0" dependencies: @@ -38095,26 +37896,19 @@ __metadata: languageName: node linkType: hard -"ramda-adjunct@npm:^4.0.0, ramda-adjunct@npm:^4.1.1": - version: 4.1.1 - resolution: "ramda-adjunct@npm:4.1.1" +"ramda-adjunct@npm:^5.0.0": + version: 5.0.1 + resolution: "ramda-adjunct@npm:5.0.1" peerDependencies: - ramda: ">= 0.29.0" - checksum: 7cdae1129987afac3d2ab9188b62f949558f86ad14ef76b898bacf065da5542e213e53cb01f064444ad634dfa668148cd3351726017a11dfe141b6b4c3552808 + ramda: ">= 0.30.0" + checksum: 4bad48b60697e14b524934ae43af59a1cddab0f04d8fd1586725a8a90ad5b1f02572681a6870b392835b6523096d9548b0d8ac397f985e12cfff6e295a15ce12 languageName: node linkType: hard -"ramda@npm:@pnpm/ramda@0.28.1": - version: 0.28.1 - resolution: "@pnpm/ramda@npm:0.28.1" - checksum: e45e41ceab4f9a0a08fec9c7809a7b79cf3b3220998588f76567addb7533167b591112e0ea1a34b9d99f97ab7511a5bedb1cbb3d49c424c7dc0cdc060ffc2aae - languageName: node - linkType: hard - -"ramda@npm:~0.29.1": - version: 0.29.1 - resolution: "ramda@npm:0.29.1" - checksum: df7c627597a66d5f317f6ba77ad17d7ba818efc9c2c4a638440bc23f2c651e823970ea05b05a28895738c0e4b738fadbdc17b2c97b3ad922826febc09c859c44 +"ramda@npm:~0.30.0": + version: 0.30.1 + resolution: "ramda@npm:0.30.1" + checksum: ce6f4b6b967a84a4e65c01ab1b1cdd73d46b8efe71aeccf5d1443c56c4e31a0ea82ece7df6510453dd3d83b92cabf8a6b4d50d189a1b35c08a6f44b281bebf79 languageName: node linkType: hard @@ -38439,11 +38233,11 @@ __metadata: linkType: hard "react-hook-form@npm:^7.12.2": - version: 7.51.3 - resolution: "react-hook-form@npm:7.51.3" + version: 7.51.5 + resolution: "react-hook-form@npm:7.51.5" peerDependencies: react: ^16.8.0 || ^17 || ^18 - checksum: 4ac71033b66ae0b7b9d75a1bc2053a6747fb37f68c6895ee85a72cabb890168d82990c8ca7bddd271e80fdbf58f471d14d6a0e0714400d017590d4f56b3d241f + checksum: 6b6a56b6520ddb68d491e2f07791538aa611c13fcd76052a499ba10bdaf7f77f4a5f7191e6ca9d9ab0af739bf07171c6e8d97f6c4da06f576aa74caed71828f1 languageName: node linkType: hard @@ -38601,32 +38395,29 @@ __metadata: languageName: node linkType: hard -"react-redux@npm:^9.1.1": - version: 9.1.1 - resolution: "react-redux@npm:9.1.1" +"react-redux@npm:^9.1.2": + version: 9.1.2 + resolution: "react-redux@npm:9.1.2" dependencies: "@types/use-sync-external-store": ^0.0.3 use-sync-external-store: ^1.0.0 peerDependencies: "@types/react": ^18.2.25 react: ^18.0 - react-native: ">=0.69" redux: ^5.0.0 peerDependenciesMeta: "@types/react": optional: true - react-native: - optional: true redux: optional: true - checksum: 51a61215d7195f381c045dc263b6f5e4e297ec9219c3d34132cae594f4070ac5db9b3762f3b8a73bb8d10bbf251310c364ec61b36829103b1cc7ef9244ee7c8a + checksum: 1ee9cf41f29f68267320b4fc3bcf6a76a3825c82441612582678ddd827a2b60834f687d2a8b755c905885dfce476a1eb41af42b36f4dd71f8ee9991296a1e515 languageName: node linkType: hard -"react-refresh@npm:^0.14.0": - version: 0.14.0 - resolution: "react-refresh@npm:0.14.0" - checksum: dc69fa8c993df512f42dd0f1b604978ae89bd747c0ed5ec595c0cc50d535fb2696619ccd98ae28775cc01d0a7c146a532f0f7fb81dc22e1977c242a4912312f4 +"react-refresh@npm:^0.14.0, react-refresh@npm:^0.14.2": + version: 0.14.2 + resolution: "react-refresh@npm:0.14.2" + checksum: d80db4bd40a36dab79010dc8aa317a5b931f960c0d83c4f3b81f0552cbcf7f29e115b84bb7908ec6a1eb67720fff7023084eff73ece8a7ddc694882478464382 languageName: node linkType: hard @@ -38912,7 +38703,7 @@ __metadata: languageName: node linkType: hard -"react-window@npm:^1.8.6": +"react-window@npm:^1.8.10, react-window@npm:^1.8.6": version: 1.8.10 resolution: "react-window@npm:1.8.10" dependencies: @@ -38962,16 +38753,6 @@ __metadata: languageName: node linkType: hard -"read-package-json-fast@npm:^3.0.0": - version: 3.0.2 - resolution: "read-package-json-fast@npm:3.0.2" - dependencies: - json-parse-even-better-errors: ^3.0.0 - npm-normalize-package-bin: ^3.0.0 - checksum: 8d406869f045f1d76e2a99865a8fd1c1af9c1dc06200b94d2b07eef87ed734b22703a8d72e1cd36ea36cc48e22020bdd187f88243c7dd0563f72114d38c17072 - languageName: node - linkType: hard - "read-pkg-up@npm:^7.0.1": version: 7.0.1 resolution: "read-pkg-up@npm:7.0.1" @@ -39282,7 +39063,7 @@ __metadata: languageName: node linkType: hard -"regexp.prototype.flags@npm:^1.5.0, regexp.prototype.flags@npm:^1.5.2": +"regexp.prototype.flags@npm:^1.5.2": version: 1.5.2 resolution: "regexp.prototype.flags@npm:1.5.2" dependencies: @@ -39405,16 +39186,6 @@ __metadata: languageName: node linkType: hard -"rename-overwrite@npm:^5.0.0": - version: 5.0.0 - resolution: "rename-overwrite@npm:5.0.0" - dependencies: - "@zkochan/rimraf": ^2.1.2 - fs-extra: 10.1.0 - checksum: eaac7b36302b6f184dcff91c625776e3a3b46b234550adcf70434695ef9c7dd28bd9c5b2945c4a7fbcd09649bd31efce26aae39166becdc05ca9213524d2c3b8 - languageName: node - linkType: hard - "renderkid@npm:^3.0.0": version: 3.0.0 resolution: "renderkid@npm:3.0.0" @@ -39580,7 +39351,7 @@ __metadata: languageName: node linkType: hard -"resolve@npm:1.22.8, resolve@npm:^1.1.6, resolve@npm:^1.10.0, resolve@npm:^1.14.2, resolve@npm:^1.17.0, resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.22.1, resolve@npm:^1.22.4, resolve@npm:~1.22.1": +"resolve@npm:^1.1.6, resolve@npm:^1.10.0, resolve@npm:^1.14.2, resolve@npm:^1.17.0, resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.22.1, resolve@npm:^1.22.4, resolve@npm:^1.22.8, resolve@npm:~1.22.1": version: 1.22.8 resolution: "resolve@npm:1.22.8" dependencies: @@ -39616,7 +39387,7 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@1.22.8#~builtin, resolve@patch:resolve@^1.1.6#~builtin, resolve@patch:resolve@^1.10.0#~builtin, resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.17.0#~builtin, resolve@patch:resolve@^1.19.0#~builtin, resolve@patch:resolve@^1.20.0#~builtin, resolve@patch:resolve@^1.22.1#~builtin, resolve@patch:resolve@^1.22.4#~builtin, resolve@patch:resolve@~1.22.1#~builtin": +"resolve@patch:resolve@^1.1.6#~builtin, resolve@patch:resolve@^1.10.0#~builtin, resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.17.0#~builtin, resolve@patch:resolve@^1.19.0#~builtin, resolve@patch:resolve@^1.20.0#~builtin, resolve@patch:resolve@^1.22.1#~builtin, resolve@patch:resolve@^1.22.4#~builtin, resolve@patch:resolve@^1.22.8#~builtin, resolve@patch:resolve@~1.22.1#~builtin": version: 1.22.8 resolution: "resolve@patch:resolve@npm%3A1.22.8#~builtin::version=1.22.8&hash=c3c19d" dependencies: @@ -39769,17 +39540,6 @@ __metadata: languageName: node linkType: hard -"rimraf@npm:^2.6.3": - version: 2.7.1 - resolution: "rimraf@npm:2.7.1" - dependencies: - glob: ^7.1.3 - bin: - rimraf: ./bin.js - checksum: cdc7f6eacb17927f2a075117a823e1c5951792c6498ebcce81ca8203454a811d4cf8900314154d3259bb8f0b42ab17f67396a8694a54cae3283326e57ad250cd - languageName: node - linkType: hard - "rimraf@npm:^3.0.0, rimraf@npm:^3.0.2": version: 3.0.2 resolution: "rimraf@npm:3.0.2" @@ -39838,18 +39598,18 @@ __metadata: linkType: hard "rollup-plugin-dts@npm:^6.1.0": - version: 6.1.0 - resolution: "rollup-plugin-dts@npm:6.1.0" + version: 6.1.1 + resolution: "rollup-plugin-dts@npm:6.1.1" dependencies: - "@babel/code-frame": ^7.22.13 - magic-string: ^0.30.4 + "@babel/code-frame": ^7.24.2 + magic-string: ^0.30.10 peerDependencies: rollup: ^3.29.4 || ^4 typescript: ^4.5 || ^5.0 dependenciesMeta: "@babel/code-frame": optional: true - checksum: a90f8e975e4515734c84fa17e0feaf8fdd9ed9368722c3908687875903a393cba4d07d9934bae9b91a0c1b6c63ac1ef0ccd7363d3e6e4dc10eabca3540be9f11 + checksum: e69da1a286570f5a8d990651a613b2063543a71ad3b3471a97e74ea328125ebee77a74b2c800031f8dcccdc92da0d086f833724d13a2c863a2cbdf7e8fc20329 languageName: node linkType: hard @@ -40033,6 +39793,7 @@ __metadata: "@spotify/eslint-plugin": ^15.0.0 "@spotify/prettier-config": ^15.0.0 "@techdocs/cli": "workspace:*" + "@types/global-agent": ^2.1.3 "@types/node": ^18.17.8 "@types/webpack": ^5.28.0 "@useoptic/optic": ^0.50.10 @@ -40386,7 +40147,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:^6.0.0, semver@npm:^6.1.0, semver@npm:^6.2.0, semver@npm:^6.3.0, semver@npm:^6.3.1": +"semver@npm:^6.0.0, semver@npm:^6.2.0, semver@npm:^6.3.0, semver@npm:^6.3.1": version: 6.3.1 resolution: "semver@npm:6.3.1" bin: @@ -40395,14 +40156,12 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.0.0, 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.4.0, semver@npm:^7.5.2, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0": - version: 7.6.0 - resolution: "semver@npm:7.6.0" - dependencies: - lru-cache: ^6.0.0 +"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.2, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0": + version: 7.6.2 + resolution: "semver@npm:7.6.2" bin: semver: bin/semver.js - checksum: 7427f05b70786c696640edc29fdd4bc33b2acf3bbe1740b955029044f80575fc664e1a512e4113c3af21e767154a94b4aa214bf6cd6e42a1f6dba5914e0b208c + checksum: 40f6a95101e8d854357a644da1b8dd9d93ce786d5c6a77227bc69dbb17bea83d0d1d1d7c4cd5920a6df909f48e8bd8a5909869535007f90278289f2451d0292d languageName: node linkType: hard @@ -40532,14 +40291,15 @@ __metadata: languageName: node linkType: hard -"set-function-name@npm:^2.0.0, set-function-name@npm:^2.0.1": - version: 2.0.1 - resolution: "set-function-name@npm:2.0.1" +"set-function-name@npm:^2.0.1, set-function-name@npm:^2.0.2": + version: 2.0.2 + resolution: "set-function-name@npm:2.0.2" dependencies: - define-data-property: ^1.0.1 + define-data-property: ^1.1.4 + es-errors: ^1.3.0 functions-have-names: ^1.2.3 - has-property-descriptors: ^1.0.0 - checksum: 4975d17d90c40168eee2c7c9c59d023429f0a1690a89d75656306481ece0c3c1fb1ebcc0150ea546d1913e35fbd037bace91372c69e543e51fc5d1f31a9fa126 + has-property-descriptors: ^1.0.2 + checksum: d6229a71527fd0404399fc6227e0ff0652800362510822a291925c9d7b48a1ca1a468b11b281471c34cd5a2da0db4f5d7ff315a61d26655e77f6e971e6d0c80f languageName: node linkType: hard @@ -40800,13 +40560,6 @@ __metadata: languageName: node linkType: hard -"slash@npm:^2.0.0": - version: 2.0.0 - resolution: "slash@npm:2.0.0" - checksum: 512d4350735375bd11647233cb0e2f93beca6f53441015eea241fe784d8068281c3987fbaa93e7ef1c38df68d9c60013045c92837423c69115297d6169aa85e6 - languageName: node - linkType: hard - "slash@npm:^3.0.0": version: 3.0.0 resolution: "slash@npm:3.0.0" @@ -40900,10 +40653,10 @@ __metadata: languageName: node linkType: hard -"smol-toml@npm:1.1.4": - version: 1.1.4 - resolution: "smol-toml@npm:1.1.4" - checksum: 71537b27c18172c819778d54b6328d438af9d16dd63f0722a9df9fd77c7084eb163274224910c89e6dec0369f130ab050bc3cf4bdba34a4dc134b4faa74749de +"smol-toml@npm:^1.1.4": + version: 1.2.1 + resolution: "smol-toml@npm:1.2.1" + checksum: 12040dd8e38b6efb7a1572bfd803c6a7ac89b8d715d0614b024601165059ea3f4653dd5b87b601308dcefd20a26af8445e9be9888b52e0c4f24d1bfc6d2c4e84 languageName: node linkType: hard @@ -41276,7 +41029,7 @@ __metadata: languageName: node linkType: hard -"ssri@npm:10.0.5, ssri@npm:^10.0.0": +"ssri@npm:^10.0.0": version: 10.0.5 resolution: "ssri@npm:10.0.5" dependencies: @@ -41372,13 +41125,6 @@ __metadata: languageName: node linkType: hard -"stampit@npm:^4.3.2": - version: 4.3.2 - resolution: "stampit@npm:4.3.2" - checksum: 731dfe564b98371293bb5e7cb76bb195336dd3589af4e448d1478ac6c99091fd302fd7f41a255daa4b0ec2c1f14ea4f0cc0a2f05cd3d786b29ba531850ad7f62 - languageName: node - linkType: hard - "standard-as-callback@npm:^2.1.0": version: 2.1.0 resolution: "standard-as-callback@npm:2.1.0" @@ -41631,53 +41377,57 @@ __metadata: languageName: node linkType: hard -"string.prototype.matchall@npm:^4.0.10": - version: 4.0.10 - resolution: "string.prototype.matchall@npm:4.0.10" +"string.prototype.matchall@npm:^4.0.11": + version: 4.0.11 + resolution: "string.prototype.matchall@npm:4.0.11" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - get-intrinsic: ^1.2.1 + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + es-errors: ^1.3.0 + es-object-atoms: ^1.0.0 + get-intrinsic: ^1.2.4 + gopd: ^1.0.1 has-symbols: ^1.0.3 - internal-slot: ^1.0.5 - regexp.prototype.flags: ^1.5.0 - set-function-name: ^2.0.0 - side-channel: ^1.0.4 - checksum: 3c78bdeff39360c8e435d7c4c6ea19f454aa7a63eda95fa6fadc3a5b984446a2f9f2c02d5c94171ce22268a573524263fbd0c8edbe3ce2e9890d7cc036cdc3ed + internal-slot: ^1.0.7 + regexp.prototype.flags: ^1.5.2 + set-function-name: ^2.0.2 + side-channel: ^1.0.6 + checksum: 6ac6566ed065c0c8489c91156078ca077db8ff64d683fda97ae652d00c52dfa5f39aaab0a710d8243031a857fd2c7c511e38b45524796764d25472d10d7075ae languageName: node linkType: hard -"string.prototype.trim@npm:^1.2.8": - version: 1.2.8 - resolution: "string.prototype.trim@npm:1.2.8" +"string.prototype.trim@npm:^1.2.9": + version: 1.2.9 + resolution: "string.prototype.trim@npm:1.2.9" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - checksum: 49eb1a862a53aba73c3fb6c2a53f5463173cb1f4512374b623bcd6b43ad49dd559a06fb5789bdec771a40fc4d2a564411c0a75d35fb27e76bbe738c211ecff07 + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.0 + es-object-atoms: ^1.0.0 + checksum: ea2df6ec1e914c9d4e2dc856fa08228e8b1be59b59e50b17578c94a66a176888f417264bb763d4aac638ad3b3dad56e7a03d9317086a178078d131aa293ba193 languageName: node linkType: hard -"string.prototype.trimend@npm:^1.0.7": - version: 1.0.7 - resolution: "string.prototype.trimend@npm:1.0.7" +"string.prototype.trimend@npm:^1.0.8": + version: 1.0.8 + resolution: "string.prototype.trimend@npm:1.0.8" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - checksum: 2375516272fd1ba75992f4c4aa88a7b5f3c7a9ca308d963bcd5645adf689eba6f8a04ebab80c33e30ec0aefc6554181a3a8416015c38da0aa118e60ec896310c + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-object-atoms: ^1.0.0 + checksum: cc3bd2de08d8968a28787deba9a3cb3f17ca5f9f770c91e7e8fa3e7d47f079bad70fadce16f05dda9f261788be2c6e84a942f618c3bed31e42abc5c1084f8dfd languageName: node linkType: hard -"string.prototype.trimstart@npm:^1.0.7": - version: 1.0.7 - resolution: "string.prototype.trimstart@npm:1.0.7" +"string.prototype.trimstart@npm:^1.0.8": + version: 1.0.8 + resolution: "string.prototype.trimstart@npm:1.0.8" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - checksum: 13d0c2cb0d5ff9e926fa0bec559158b062eed2b68cd5be777ffba782c96b2b492944e47057274e064549b94dd27cf81f48b27a31fee8af5b574cff253e7eb613 + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-object-atoms: ^1.0.0 + checksum: df1007a7f580a49d692375d996521dc14fd103acda7f3034b3c558a60b82beeed3a64fa91e494e164581793a8ab0ae2f59578a49896a7af6583c1f20472bce96 languageName: node linkType: hard @@ -42053,46 +41803,47 @@ __metadata: languageName: node linkType: hard -"swagger-client@npm:^3.27.0": - version: 3.27.0 - resolution: "swagger-client@npm:3.27.0" +"swagger-client@npm:^3.28.1": + version: 3.28.2 + resolution: "swagger-client@npm:3.28.2" dependencies: "@babel/runtime-corejs3": ^7.22.15 - "@swagger-api/apidom-core": ">=0.99.1 <1.0.0" - "@swagger-api/apidom-error": ">=0.99.0 <1.0.0" - "@swagger-api/apidom-json-pointer": ">=0.99.1 <1.0.0" - "@swagger-api/apidom-ns-openapi-3-1": ">=0.99.1 <1.0.0" - "@swagger-api/apidom-reference": ">=0.99.1 <1.0.0" + "@swagger-api/apidom-core": ">=1.0.0-alpha.5 <1.0.0-beta.0" + "@swagger-api/apidom-error": ">=1.0.0-alpha.5 <1.0.0-beta.0" + "@swagger-api/apidom-json-pointer": ">=1.0.0-alpha.5 <1.0.0-beta.0" + "@swagger-api/apidom-ns-openapi-3-1": ">=1.0.0-alpha.5 <1.0.0-beta.0" + "@swagger-api/apidom-reference": ">=1.0.0-alpha.5 <1.0.0-beta.0" cookie: ~0.6.0 deepmerge: ~4.3.0 fast-json-patch: ^3.0.0-1 - is-plain-object: ^5.0.0 js-yaml: ^4.1.0 node-abort-controller: ^3.1.1 node-fetch-commonjs: ^3.3.2 + openapi-path-templating: ^1.5.1 + openapi-server-url-templating: ^1.0.0 qs: ^6.10.2 - traverse: ~0.6.6 - checksum: 7279ea2cb96dee71c428f758a7d983ee0a143cbcb1c11432d02327f1e4c65d39ca78f1c39dab7771cda54a4e04c57b33936287f23e663181c5058cbd2aea7477 + ramda-adjunct: ^5.0.0 + traverse: =0.6.8 + checksum: 46b970fce13976c2491d3f1a18cbaee9eedebe89bb6da9c4444a6c60de8f9436f375b4cfbd011093a3070f6719037852e8e4a1d3bf06aeb8b7192b805bfe20bf languageName: node linkType: hard "swagger-ui-react@npm:^5.0.0": - version: 5.17.0 - resolution: "swagger-ui-react@npm:5.17.0" + version: 5.17.14 + resolution: "swagger-ui-react@npm:5.17.14" dependencies: - "@babel/runtime-corejs3": ^7.24.4 - "@braintree/sanitize-url": =7.0.1 + "@babel/runtime-corejs3": ^7.24.5 + "@braintree/sanitize-url": =7.0.2 base64-js: ^1.5.1 classnames: ^2.5.1 css.escape: 1.5.1 deep-extend: 0.6.0 - dompurify: =3.1.0 + dompurify: =3.1.4 ieee754: ^1.2.1 immutable: ^3.x.x js-file-download: ^0.4.12 js-yaml: =4.1.0 lodash: ^4.17.21 - patch-package: ^8.0.0 prop-types: ^15.8.1 randexp: ^0.5.3 randombytes: ^2.1.0 @@ -42101,7 +41852,7 @@ __metadata: react-immutable-proptypes: 2.2.0 react-immutable-pure-component: ^2.2.0 react-inspector: ^6.0.1 - react-redux: ^9.1.1 + react-redux: ^9.1.2 react-syntax-highlighter: ^15.5.0 redux: ^5.0.1 redux-immutable: ^4.0.0 @@ -42109,7 +41860,7 @@ __metadata: reselect: ^5.1.0 serialize-error: ^8.1.0 sha.js: ^2.4.11 - swagger-client: ^3.27.0 + swagger-client: ^3.28.1 url-parse: ^1.5.10 xml: =1.0.1 xml-but-prettier: ^1.0.1 @@ -42117,7 +41868,7 @@ __metadata: peerDependencies: react: ">=16.8.0 <19" react-dom: ">=16.8.0 <19" - checksum: f7c0820b9bd5fe5e1ed2ab6118a56aab31176ce3e6693f489d6915d33c70bfd6b9aa3122cbd371d722a917c1395b863b2f0483515f62e7f5e180fa310eefdca0 + checksum: 1283b23feb91b475ab036f219342374853b6113090c47c49df4576fa9f187a6df05825e7df059d862b8fcf3be51c25691a8da380084f4ca84bc6b5d0ee0ef744 languageName: node linkType: hard @@ -42740,10 +42491,10 @@ __metadata: languageName: node linkType: hard -"traverse@npm:~0.6.6": - version: 0.6.6 - resolution: "traverse@npm:0.6.6" - checksum: e2afa72f11efa9ba31ed763d2d9d2aa244612f22015d16c0ea3ba5f6ca8bf071de87f8108b721885cce06ea4a36ef4605d9228c67e431d9015ea4685cb364420 +"traverse@npm:=0.6.8": + version: 0.6.8 + resolution: "traverse@npm:0.6.8" + checksum: ef22abfc73fe2052403093b6747febbfeb52dcf827db1ca0542a78932c918706b9b12c373ef27e1c3e07e3e92eb1c646b4fe97b936fe775d59cbce7da417e13b languageName: node linkType: hard @@ -42875,7 +42626,7 @@ __metadata: languageName: node linkType: hard -"ts-mixer@npm:^6.0.3": +"ts-mixer@npm:^6.0.3, ts-mixer@npm:^6.0.4": version: 6.0.4 resolution: "ts-mixer@npm:6.0.4" checksum: 36b1af526befd74345e736e9aa16f5c28876ebcea07784da14d929149fd7e6028cfd2fe9304c8efe8cb91b588443a9cc9e991df58e4c6e602326edbaae2af3ab @@ -42956,6 +42707,17 @@ __metadata: languageName: node linkType: hard +"tsconfig-paths@npm:^4.2.0": + version: 4.2.0 + resolution: "tsconfig-paths@npm:4.2.0" + dependencies: + json5: ^2.2.2 + minimist: ^1.2.6 + strip-bom: ^3.0.0 + checksum: 28c5f7bbbcabc9dabd4117e8fdc61483f6872a1c6b02a4b1c4d68c5b79d06896c3cc9547610c4c3ba64658531caa2de13ead1ea1bf321c7b53e969c4752b98c7 + languageName: node + linkType: hard + "tslib@npm:2.6.2, tslib@npm:^2.0.0, tslib@npm:^2.0.1, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.2.0, tslib@npm:^2.3.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:^2.4.1, tslib@npm:^2.4.1 || ^1.9.3, tslib@npm:^2.5.0, tslib@npm:^2.6.0, tslib@npm:^2.6.2": version: 2.6.2 resolution: "tslib@npm:2.6.2" @@ -43199,9 +42961,9 @@ __metadata: languageName: node linkType: hard -"typed-array-length@npm:^1.0.5": - version: 1.0.5 - resolution: "typed-array-length@npm:1.0.5" +"typed-array-length@npm:^1.0.6": + version: 1.0.6 + resolution: "typed-array-length@npm:1.0.6" dependencies: call-bind: ^1.0.7 for-each: ^0.3.3 @@ -43209,7 +42971,7 @@ __metadata: has-proto: ^1.0.3 is-typed-array: ^1.1.13 possible-typed-array-names: ^1.0.0 - checksum: 82f5b666155cff1b345a1f3ab018d3f7667990f525435e4c8448cc094ab0f8ea283bb7cbde4d7bc82ea0b9b1072523bf31e86620d72615951d7fa9ccb4f42dfa + checksum: f0315e5b8f0168c29d390ff410ad13e4d511c78e6006df4a104576844812ee447fcc32daab1f3a76c9ef4f64eff808e134528b5b2439de335586b392e9750e5c languageName: node linkType: hard @@ -43247,12 +43009,12 @@ __metadata: languageName: node linkType: hard -"types-ramda@npm:^0.29.5": - version: 0.29.5 - resolution: "types-ramda@npm:0.29.5" +"types-ramda@npm:^0.30.0": + version: 0.30.0 + resolution: "types-ramda@npm:0.30.0" dependencies: ts-toolbelt: ^9.6.0 - checksum: 0013eec508b74ed98a3de25f9617c2f246ed387dbda084ae37d9f10c5ccac0bb0243a966e861262c918feef8322347616852abf30440a252335e50d9592590e9 + checksum: 595be8f6ad2186b2838ee96bec73b601818382083866456cbabb59e8cec225e807cda9387843cbdc26a80d59040084f56d47edbcd59753f80da576dcc1faa476 languageName: node linkType: hard @@ -43694,17 +43456,17 @@ __metadata: languageName: node linkType: hard -"update-browserslist-db@npm:^1.0.11": - version: 1.0.11 - resolution: "update-browserslist-db@npm:1.0.11" +"update-browserslist-db@npm:^1.0.16": + version: 1.0.16 + resolution: "update-browserslist-db@npm:1.0.16" dependencies: - escalade: ^3.1.1 - picocolors: ^1.0.0 + escalade: ^3.1.2 + picocolors: ^1.0.1 peerDependencies: browserslist: ">= 4.21.0" bin: update-browserslist-db: cli.js - checksum: b98327518f9a345c7cad5437afae4d2ae7d865f9779554baf2a200fdf4bac4969076b679b1115434bd6557376bdd37ca7583d0f9b8f8e302d7d4cc1e91b5f231 + checksum: 51b1f7189c9ea5925c80154b0a6fd3ec36106d07858d8f69826427d8edb4735d1801512c69eade38ba0814d7407d11f400d74440bbf3da0309f3d788017f35b2 languageName: node linkType: hard @@ -44036,7 +43798,7 @@ __metadata: languageName: node linkType: hard -"validate-npm-package-license@npm:^3.0.1, validate-npm-package-license@npm:^3.0.4": +"validate-npm-package-license@npm:^3.0.1": version: 3.0.4 resolution: "validate-npm-package-license@npm:3.0.4" dependencies: @@ -44055,24 +43817,6 @@ __metadata: languageName: node linkType: hard -"validate-npm-package-name@npm:^4.0.0": - version: 4.0.0 - resolution: "validate-npm-package-name@npm:4.0.0" - dependencies: - builtins: ^5.0.0 - checksum: a32fd537bad17fcb59cfd58ae95a414d443866020d448ec3b22e8d40550cb585026582a57efbe1f132b882eea4da8ac38ee35f7be0dd72988a3cb55d305a20c1 - languageName: node - linkType: hard - -"validate-npm-package-name@npm:^5.0.0": - version: 5.0.0 - resolution: "validate-npm-package-name@npm:5.0.0" - dependencies: - builtins: ^5.0.0 - checksum: 5342a994986199b3c28e53a8452a14b2bb5085727691ea7aa0d284a6606b127c371e0925ae99b3f1ef7cc7d2c9de75f52eb61a3d1cc45e39bca1e3a9444cbb4e - languageName: node - linkType: hard - "validate.io-array@npm:^1.0.3": version: 1.0.6 resolution: "validate.io-array@npm:1.0.6" @@ -44161,15 +43905,6 @@ __metadata: languageName: node linkType: hard -"version-selector-type@npm:^3.0.0": - version: 3.0.0 - resolution: "version-selector-type@npm:3.0.0" - dependencies: - semver: ^7.3.2 - checksum: e97968054ad3bd2ff25a1c8e55273d34db5601e573f1ebca144b145d6a984925390358959859e77aca526082a64483e776e3f15178b0d8e2b3f1deb64932a7aa - languageName: node - linkType: hard - "vfile-message@npm:^3.0.0": version: 3.0.2 resolution: "vfile-message@npm:3.0.2" @@ -44241,15 +43976,15 @@ __metadata: languageName: node linkType: hard -"vite-plugin-node-polyfills@npm:^0.21.0": - version: 0.21.0 - resolution: "vite-plugin-node-polyfills@npm:0.21.0" +"vite-plugin-node-polyfills@npm:^0.22.0": + version: 0.22.0 + resolution: "vite-plugin-node-polyfills@npm:0.22.0" dependencies: "@rollup/plugin-inject": ^5.0.5 node-stdlib-browser: ^1.2.0 peerDependencies: vite: ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 - checksum: 923379f0205911d13ffdcdc841a6565a191a6fe199eb7c0d38b6ea1f53bbdf3d42ad12a9ae8d5f49c14e3f4e2cb56fc7ea8c24a51eeedfbe64c6ebbca4a2966a + checksum: c08d3df0d5cc3102280483d3f7b216f92a18e0708fcb9f67f78f01ab865474254756bacee17caa90b3f46afe5834cb9d8de0dd0e58c1bbbdae1b949edc1e6b57 languageName: node linkType: hard @@ -44917,8 +44652,8 @@ __metadata: linkType: hard "ws@npm:*, ws@npm:^8.11.0, ws@npm:^8.12.0, ws@npm:^8.13.0, ws@npm:^8.14.2, ws@npm:^8.16.0, ws@npm:^8.17.0, ws@npm:^8.8.0": - version: 8.17.0 - resolution: "ws@npm:8.17.0" + version: 8.17.1 + resolution: "ws@npm:8.17.1" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ">=5.0.2" @@ -44927,7 +44662,7 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: 147ef9eab0251364e1d2c55338ad0efb15e6913923ccbfdf20f7a8a6cb8f88432bcd7f4d8f66977135bfad35575644f9983201c1a361019594a4e53977bf6d4e + checksum: 442badcce1f1178ec87a0b5372ae2e9771e07c4929a3180321901f226127f252441e8689d765aa5cfba5f50ac60dd830954afc5aeae81609aefa11d3ddf5cecf languageName: node linkType: hard @@ -44947,8 +44682,8 @@ __metadata: linkType: hard "ws@npm:^7, ws@npm:^7.4.6, ws@npm:^7.5.5": - version: 7.5.9 - resolution: "ws@npm:7.5.9" + version: 7.5.10 + resolution: "ws@npm:7.5.10" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ^5.0.2 @@ -44957,7 +44692,7 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: c3c100a181b731f40b7f2fddf004aa023f79d64f489706a28bc23ff88e87f6a64b3c6651fbec3a84a53960b75159574d7a7385709847a62ddb7ad6af76f49138 + checksum: f9bb062abf54cc8f02d94ca86dcd349c3945d63851f5d07a3a61c2fcb755b15a88e943a63cf580cbdb5b74436d67ef6b67f745b8f7c0814e411379138e1863cb languageName: node linkType: hard @@ -45168,11 +44903,11 @@ __metadata: linkType: hard "yaml@npm:^2.0.0, yaml@npm:^2.0.0-10, yaml@npm:^2.1.1, yaml@npm:^2.2.1, yaml@npm:^2.2.2, yaml@npm:^2.3.2, yaml@npm:^2.3.3, yaml@npm:~2.4.2": - version: 2.4.2 - resolution: "yaml@npm:2.4.2" + version: 2.4.5 + resolution: "yaml@npm:2.4.5" bin: yaml: bin.mjs - checksum: 90dda4485de04367251face9abb5c36927c94e44078f4e958e6468a07e74e7e92f89be20fc49860b6268c51ee5a5fc79ef89197d3f874bf24ef8921cc4ba9013 + checksum: f8efd407c07e095f00f3031108c9960b2b12971d10162b1ec19007200f6c987d2e28f73283f4731119aa610f177a3ea03d4a8fcf640600a25de1b74d00c69b3d languageName: node linkType: hard @@ -45446,9 +45181,9 @@ __metadata: linkType: hard "zod@npm:^3.22.4": - version: 3.23.6 - resolution: "zod@npm:3.23.6" - checksum: f534119e2a54e86bf77e5c6ff630ef4ec50b87dd9d9faf66dc7a663a489d37130b716ebd836cdd9d7fc6e124a1accdc0d53f388243a236c10e632dcc945eaa27 + version: 3.23.8 + resolution: "zod@npm:3.23.8" + checksum: 15949ff82118f59c893dacd9d3c766d02b6fa2e71cf474d5aa888570c469dbf5446ac5ad562bb035bf7ac9650da94f290655c194f4a6de3e766f43febd432c5c languageName: node linkType: hard