diff --git a/.changeset/afraid-items-drum.md b/.changeset/afraid-items-drum.md deleted file mode 100644 index 94ddd608cd..0000000000 --- a/.changeset/afraid-items-drum.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli-node': patch ---- - -Updated to use new utilities from `@backstage/cli-common`. diff --git a/.changeset/alert-api-replay.md b/.changeset/alert-api-replay.md deleted file mode 100644 index b41ec091a3..0000000000 --- a/.changeset/alert-api-replay.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-app-api': patch ---- - -Added replay functionality to `AlertApiForwarder` to buffer and replay recent alerts to new subscribers, preventing missed alerts that were posted before subscription. diff --git a/.changeset/all-socks-taste.md b/.changeset/all-socks-taste.md deleted file mode 100644 index 377782c2f9..0000000000 --- a/.changeset/all-socks-taste.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend-module-gitlab': minor ---- - -In the `gitlabRepoPush` action, add 'auto' possibility for `commitAction` input. diff --git a/.changeset/better-ghosts-tell.md b/.changeset/better-ghosts-tell.md new file mode 100644 index 0000000000..af66b4fc6e --- /dev/null +++ b/.changeset/better-ghosts-tell.md @@ -0,0 +1,5 @@ +--- +'@backstage/ui': patch +--- + +Fixes app background color on dark mode. diff --git a/.changeset/bumpy-planets-go.md b/.changeset/bumpy-planets-go.md deleted file mode 100644 index 5477711c1a..0000000000 --- a/.changeset/bumpy-planets-go.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/ui': patch ---- - -Fixed Checkbox indicator showing checkmark color when unchecked. - -Affected components: Checkbox diff --git a/.changeset/chatty-sides-wear.md b/.changeset/chatty-sides-wear.md deleted file mode 100644 index 33937a1286..0000000000 --- a/.changeset/chatty-sides-wear.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-graph': patch ---- - -Fixed zoom out description (replace `&` with &) diff --git a/.changeset/chilly-bikes-rule.md b/.changeset/chilly-bikes-rule.md deleted file mode 100644 index 894999cf56..0000000000 --- a/.changeset/chilly-bikes-rule.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@techdocs/cli': patch ---- - -Updated to use new utilities from `@backstage/cli-common`. diff --git a/.changeset/chilly-hotels-walk.md b/.changeset/chilly-hotels-walk.md deleted file mode 100644 index e9b1ff66ba..0000000000 --- a/.changeset/chilly-hotels-walk.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-search-backend-node': minor ---- - -Improving method that search tokenizer breaks apart entity names diff --git a/.changeset/chilly-waves-relate.md b/.changeset/chilly-waves-relate.md deleted file mode 100644 index 2e78f9245e..0000000000 --- a/.changeset/chilly-waves-relate.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@backstage/cli': minor ---- - -Switched the default module resolution to `bundler` and the `module` setting to `ES2020`. - -You may need to bump some dependencies as part of this change and fix imports in code. The most common source of this is that type checking will now consider the `exports` field in `package.json` when resolving imports. This in turn can break older versions of packages that had incompatible `exports` fields. Generally these issues will have already been fixed in the upstream packages. - -You might be tempted to use `--skipLibCheck` to hide issues due to this change, but it will weaken the type safety of your project. If you run into a large number of issues and want to keep the old behavior, you can reset the `moduleResolution` and `module` settings your own `tsconfig.json` file to `node` and `ESNext` respectively. But keep in mind that the `node` option will be removed in future versions of TypeScript. - -A future version of Backstage will make these new settings mandatory, as we move to rely on the `exports` field for type resolution in packages, rather than the `typesVersions` field. diff --git a/.changeset/clean-toys-reply.md b/.changeset/clean-toys-reply.md deleted file mode 100644 index 66002903ab..0000000000 --- a/.changeset/clean-toys-reply.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-auth-node': patch ---- - -remove leading dot in auth cookie cleanup call diff --git a/.changeset/cold-dogs-study.md b/.changeset/cold-dogs-study.md new file mode 100644 index 0000000000..a27309fc15 --- /dev/null +++ b/.changeset/cold-dogs-study.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs-backend': patch +--- + +Some AWS `publisher` config options such as `region`, `endpoint`, `accountId` are now marked as `@visibility backend` instead of `secret`. diff --git a/.changeset/common-coins-stare.md b/.changeset/common-coins-stare.md deleted file mode 100644 index 0bd0078cf9..0000000000 --- a/.changeset/common-coins-stare.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/ui': patch ---- - -Fixed `ButtonIcon` incorrectly applying `className` to inner elements instead of only the root element. - -Affected components: ButtonIcon diff --git a/.changeset/crazy-hornets-spend.md b/.changeset/crazy-hornets-spend.md deleted file mode 100644 index 4db99675ac..0000000000 --- a/.changeset/crazy-hornets-spend.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@backstage/plugin-catalog-graph': patch -'@backstage/plugin-api-docs': patch -'@backstage/plugin-techdocs': patch -'@backstage/plugin-catalog': patch -'@backstage/plugin-search': patch -'@backstage/plugin-app': patch -'@backstage/plugin-org': patch ---- - -Minor extension type updates after frontend API bump diff --git a/.changeset/create-app-1764689798.md b/.changeset/create-app-1766498726.md similarity index 100% rename from .changeset/create-app-1764689798.md rename to .changeset/create-app-1766498726.md diff --git a/.changeset/dependabot-0d8f6de.md b/.changeset/dependabot-0d8f6de.md deleted file mode 100644 index b0a3955f2d..0000000000 --- a/.changeset/dependabot-0d8f6de.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -'@backstage/backend-defaults': patch -'@backstage/backend-dynamic-feature-service': patch -'@backstage/backend-openapi-utils': patch -'@backstage/backend-test-utils': patch -'@backstage/cli': patch -'@backstage/plugin-app-backend': patch -'@backstage/plugin-app-node': patch -'@backstage/plugin-auth-backend-module-atlassian-provider': patch -'@backstage/plugin-auth-backend-module-auth0-provider': patch -'@backstage/plugin-auth-backend-module-aws-alb-provider': patch -'@backstage/plugin-auth-backend-module-azure-easyauth-provider': patch -'@backstage/plugin-auth-backend-module-bitbucket-provider': patch -'@backstage/plugin-auth-backend-module-cloudflare-access-provider': patch -'@backstage/plugin-auth-backend-module-gcp-iap-provider': patch -'@backstage/plugin-auth-backend-module-gitlab-provider': patch -'@backstage/plugin-auth-backend-module-guest-provider': patch -'@backstage/plugin-auth-backend-module-microsoft-provider': patch -'@backstage/plugin-auth-backend-module-oidc-provider': patch -'@backstage/plugin-auth-backend-module-okta-provider': patch -'@backstage/plugin-auth-backend-module-onelogin-provider': patch -'@backstage/plugin-auth-backend-module-openshift-provider': patch -'@backstage/plugin-auth-backend-module-pinniped-provider': patch -'@backstage/plugin-auth-backend': patch -'@backstage/plugin-auth-node': patch -'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch -'@backstage/plugin-catalog-backend': patch -'@backstage/plugin-devtools-backend': patch -'@backstage/plugin-events-backend': patch -'@backstage/plugin-events-node': patch -'@backstage/plugin-gateway-backend': patch -'@backstage/plugin-kubernetes-backend': patch -'@backstage/plugin-mcp-actions-backend': patch -'@backstage/plugin-notifications-backend': patch -'@backstage/plugin-permission-backend': patch -'@backstage/plugin-permission-node': patch -'@backstage/plugin-proxy-backend': patch -'@backstage/plugin-scaffolder-backend': patch -'@backstage/plugin-search-backend': patch -'@backstage/plugin-signals-backend': patch -'@backstage/plugin-signals-node': patch -'@backstage/plugin-techdocs-backend': patch -'@backstage/plugin-techdocs-node': patch -'@backstage/plugin-user-settings-backend': patch ---- - -chore(deps): bump `express` from 4.21.2 to 4.22.0 diff --git a/.changeset/dependabot-5e654fe.md b/.changeset/dependabot-5e654fe.md deleted file mode 100644 index 93563cffc6..0000000000 --- a/.changeset/dependabot-5e654fe.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-defaults': patch ---- - -build(deps): bump `node-forge` from 1.3.1 to 1.3.2 diff --git a/.changeset/dependabot-aed8e01.md b/.changeset/dependabot-aed8e01.md new file mode 100644 index 0000000000..8606ea8b91 --- /dev/null +++ b/.changeset/dependabot-aed8e01.md @@ -0,0 +1,5 @@ +--- +'@backstage/ui': patch +--- + +build(deps-dev): bump `storybook` from 10.1.9 to 10.1.10 diff --git a/.changeset/early-doors-visit.md b/.changeset/early-doors-visit.md deleted file mode 100644 index 41cd9e92b8..0000000000 --- a/.changeset/early-doors-visit.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-defaults': patch ---- - -Allow configuration of the `referrerPolicy` diff --git a/.changeset/error-boundary-api.md b/.changeset/error-boundary-api.md deleted file mode 100644 index 74803f1dc0..0000000000 --- a/.changeset/error-boundary-api.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/frontend-plugin-api': patch ---- - -Added a new `errorPresentation` prop to `ExtensionBoundary` to control how errors are presented to the user. The default is `'error-display'`, which is the current behavior of showing the error in the `ErrorDisplay` component. The new option is `'error-api'`, posts errors to the `ErrorApi` and does not allow retries. - -The `AppRootElementBlueprint` now wraps its element in an `ErrorBoundary` using the new `'error-api'` presentation mode. diff --git a/.changeset/every-bears-add.md b/.changeset/every-bears-add.md new file mode 100644 index 0000000000..83c6d6b06d --- /dev/null +++ b/.changeset/every-bears-add.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Bump `@swc/core` to support `ES2023` and `ES2024` diff --git a/.changeset/famous-jars-lose.md b/.changeset/famous-jars-lose.md deleted file mode 100644 index 4070701e4e..0000000000 --- a/.changeset/famous-jars-lose.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/ui': patch ---- - -Fixed Table Row component to correctly handle cases where no `href` is provided, preventing unnecessary router provider wrapping and fixing the cursor incorrectly showing as a pointer despite the element not being a link. - -Affected components: Row diff --git a/.changeset/fifty-coats-feel.md b/.changeset/fifty-coats-feel.md deleted file mode 100644 index 0e3425a505..0000000000 --- a/.changeset/fifty-coats-feel.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-kubernetes-react': patch ---- - -Enabled a pod terminal at GKE diff --git a/.changeset/fifty-lights-marry.md b/.changeset/fifty-lights-marry.md deleted file mode 100644 index 423ef89721..0000000000 --- a/.changeset/fifty-lights-marry.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch -'@backstage/plugin-kubernetes-backend': patch -'@backstage/backend-defaults': patch -'@backstage/plugin-scaffolder-react': patch -'@backstage/integration': patch ---- - -Updated luxon types diff --git a/.changeset/fine-eagles-sleep.md b/.changeset/fine-eagles-sleep.md deleted file mode 100644 index 0af6d0dfc0..0000000000 --- a/.changeset/fine-eagles-sleep.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/backend-app-api': minor ---- - -Introduced backend startup result tracking and error handling. The `Backend.start()` method now returns a `BackendStartupResult` with detailed success/failure status and timing information for all plugins and modules. When startup fails, a `BackendStartupError` is thrown that includes the complete startup results, making it easier to diagnose which plugins or modules failed. - -This also improves the default error message when backend startup fails, and of course makes it possible to craft your own custom error reporting based on the startup results. diff --git a/.changeset/flat-pillows-rush.md b/.changeset/flat-pillows-rush.md deleted file mode 100644 index bb64013f62..0000000000 --- a/.changeset/flat-pillows-rush.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/frontend-plugin-api': patch ---- - -Fixed a versioning conflict that could result in a `.withContext` is not a function error. diff --git a/.changeset/floppy-bobcats-serve.md b/.changeset/floppy-bobcats-serve.md deleted file mode 100644 index d698e1482c..0000000000 --- a/.changeset/floppy-bobcats-serve.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -'@backstage/core-components': patch ---- - -Fixed bug in the `LogViewer` component where shift + click always opened a new window instead of just changing the selection. - -In addition, improved the `LogViewer` component by a few usability enhancements: - -- Added support for multiple selections using cmd/ctrl + click -- Improved the generated hash that is added to the URL to also support ranges & multiple selections -- Added an hover effect & info tooltip to the "Copy to clipboard" button to indicate its functionality -- Added some color and a separator to the line numbers to improve readability diff --git a/.changeset/four-peaches-train.md b/.changeset/four-peaches-train.md deleted file mode 100644 index 81b35589c1..0000000000 --- a/.changeset/four-peaches-train.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/backend-defaults': patch -'@backstage/backend-plugin-api': patch ---- - -**BREAKING ALPHA**: The old `instanceMetadataService` has been removed from alpha. Please switch over to using the stable `coreServices.rootInstanceMetadata` and related types instead, available from `@backstage/backend-plugin-api`. diff --git a/.changeset/fruity-rivers-arrive.md b/.changeset/fruity-rivers-arrive.md deleted file mode 100644 index a816946bcc..0000000000 --- a/.changeset/fruity-rivers-arrive.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': minor ---- - -Add `defaultEnvironment` config to scaffolder to enable more flexible and custom templates. Now it's possible enable access to default parameters and secrets in templates, improving security and reducing complexity. diff --git a/.changeset/fruity-words-melt.md b/.changeset/fruity-words-melt.md deleted file mode 100644 index 0f02acee2b..0000000000 --- a/.changeset/fruity-words-melt.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs-module-addons-contrib': patch ---- - -Updated tests to match test-utils change diff --git a/.changeset/full-needles-drive.md b/.changeset/full-needles-drive.md deleted file mode 100644 index d0d7a59551..0000000000 --- a/.changeset/full-needles-drive.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-kubernetes-backend': minor -'@backstage/plugin-kubernetes-node': minor ---- - -Add possibility to extends Kubernetes REST API. Add fetcher to parameters for custom objects provider diff --git a/.changeset/funny-hornets-peel.md b/.changeset/funny-hornets-peel.md deleted file mode 100644 index 2af6702295..0000000000 --- a/.changeset/funny-hornets-peel.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': patch ---- - -Updated `isolated-vm` to `6.0.1` diff --git a/.changeset/funny-papayas-rest.md b/.changeset/funny-papayas-rest.md deleted file mode 100644 index 95f52966ec..0000000000 --- a/.changeset/funny-papayas-rest.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/repo-tools': patch -'@backstage/codemods': patch ---- - -Updated to use new utilities from `@backstage/cli-common`. diff --git a/.changeset/fuzzy-phones-own.md b/.changeset/fuzzy-phones-own.md deleted file mode 100644 index 61725d1f1d..0000000000 --- a/.changeset/fuzzy-phones-own.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-github-org': patch -'@backstage/plugin-catalog-backend-module-github': patch ---- - -Introduce new configuration option to exclude suspended users from GitHub Enterprise instances. - -When it’s set to true, suspended users won’t be returned when querying the organization users for GitHub Enterprise instances. -Note that this option should be used only against GitHub Enterprise instances, the property does not exist in the github.com GraphQL schema, setting it will cause a schema validation error and the syncing of users will fail. diff --git a/.changeset/fuzzy-rivers-travel.md b/.changeset/fuzzy-rivers-travel.md deleted file mode 100644 index fa2c08a671..0000000000 --- a/.changeset/fuzzy-rivers-travel.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/frontend-plugin-api': patch ---- - -Made the return type of `.withOverrides` to be simplified. diff --git a/.changeset/fuzzy-trees-live.md b/.changeset/fuzzy-trees-live.md deleted file mode 100644 index 84cec56fab..0000000000 --- a/.changeset/fuzzy-trees-live.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-components': patch ---- - -long words like urls now breaks to new line on warning panels instead of overflowing the container diff --git a/.changeset/gentle-singers-love.md b/.changeset/gentle-singers-love.md deleted file mode 100644 index ed4372ee06..0000000000 --- a/.changeset/gentle-singers-love.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-app': patch ---- - -Support to set `defaultLanguage` and `availableLanguages` for the app language API in the new frontend system diff --git a/.changeset/gentle-trains-juggle.md b/.changeset/gentle-trains-juggle.md deleted file mode 100644 index e8b1397180..0000000000 --- a/.changeset/gentle-trains-juggle.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-kubernetes-backend': patch ---- - -Replace `@aws-sdk/signature-v4` with `@smithy/signature-v4`, -as stated in the [package documentation](https://www.npmjs.com/package/@aws-sdk/signature-v4?activeTab=readme) diff --git a/.changeset/great-files-shave.md b/.changeset/great-files-shave.md deleted file mode 100644 index 271a8e8955..0000000000 --- a/.changeset/great-files-shave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-react': patch ---- - -Fixed an issue where `EntityOwnerPicker` failed to filter options when the input text contained uppercase characters. diff --git a/.changeset/green-lizards-boil.md b/.changeset/green-lizards-boil.md deleted file mode 100644 index 640699e001..0000000000 --- a/.changeset/green-lizards-boil.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-react': patch ---- - -Use a versioned context for `useEntityList`, to better work with mixed `@backstage/plugin-catalog-react` versions. diff --git a/.changeset/happy-bottles-invite.md b/.changeset/happy-bottles-invite.md deleted file mode 100644 index 07fc222cad..0000000000 --- a/.changeset/happy-bottles-invite.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-defaults': minor ---- - -Move `better-sqlite3` from dependencies to peer dependencies diff --git a/.changeset/happy-streets-dress.md b/.changeset/happy-streets-dress.md deleted file mode 100644 index 46f4d798ed..0000000000 --- a/.changeset/happy-streets-dress.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Updated engines to support Node 22 or 24 diff --git a/.changeset/honest-bears-itch.md b/.changeset/honest-bears-itch.md deleted file mode 100644 index 4c0cd5f47e..0000000000 --- a/.changeset/honest-bears-itch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-test-utils': patch ---- - -Switched `textextensions` dependency for `text-extensions`. diff --git a/.changeset/hot-colts-float.md b/.changeset/hot-colts-float.md new file mode 100644 index 0000000000..093dcfb12a --- /dev/null +++ b/.changeset/hot-colts-float.md @@ -0,0 +1,7 @@ +--- +'@backstage/ui': patch +--- + +Fixed SearchField `startCollapsed` prop not working correctly in Backstage UI. The field now properly starts in a collapsed state, expands when clicked and focused, and collapses back when unfocused with no input. Also fixed CSS logic to work correctly in all layout contexts (flex row, flex column, and regular containers). + +Affected components: SearchField diff --git a/.changeset/kind-hoops-double.md b/.changeset/kind-hoops-double.md deleted file mode 100644 index fd2f9f023f..0000000000 --- a/.changeset/kind-hoops-double.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/integration': patch ---- - -Made the github urls case insensitive. diff --git a/.changeset/large-planes-punch.md b/.changeset/large-planes-punch.md deleted file mode 100644 index 3216653eb9..0000000000 --- a/.changeset/large-planes-punch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-defaults': patch ---- - -Fix for `jose` types diff --git a/.changeset/legal-cloths-spend.md b/.changeset/legal-cloths-spend.md deleted file mode 100644 index 50d965307a..0000000000 --- a/.changeset/legal-cloths-spend.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-mcp-actions-backend': patch ---- - -Clarify error handling in readme and update handleError.ts to include all backstage/errors diff --git a/.changeset/legal-otters-punch.md b/.changeset/legal-otters-punch.md deleted file mode 100644 index 2003492e29..0000000000 --- a/.changeset/legal-otters-punch.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/plugin-kubernetes-backend': patch -'@backstage/plugin-kubernetes-common': patch -'@backstage/plugin-kubernetes-react': patch ---- - -Add Kubernetes Plugin Secrets Accordion with masked secret datas diff --git a/.changeset/lemon-corners-hug.md b/.changeset/lemon-corners-hug.md deleted file mode 100644 index b41c09c928..0000000000 --- a/.changeset/lemon-corners-hug.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs-node': patch ---- - -There was an issue in the uploading of large size files to the AWS S3. We have modified the logic by adding retry along with multipart uploading functionality. diff --git a/.changeset/loose-pets-slide.md b/.changeset/loose-pets-slide.md deleted file mode 100644 index b8ec201f1c..0000000000 --- a/.changeset/loose-pets-slide.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@backstage/repo-tools': patch ---- - -Updates OpenAPI generator templates to preserve original property names (like 'group-name', 'user-id') from OpenAPI specs when propertyNaming=original is specified. Previously, these were always converted to camelCase regardless of the propertyNaming setting. - -- Updates modelGeneric.mustache templates in both client and server generators -- Updates modelTaggedUnion.mustache templates in both client and server generators -- Uses {{baseName}} when available, falls back to {{name}} for backward compatibility -- Maintains backward compatibility - no changes when propertyNaming=original is not used diff --git a/.changeset/loud-yaks-watch.md b/.changeset/loud-yaks-watch.md deleted file mode 100644 index b7ad65b9eb..0000000000 --- a/.changeset/loud-yaks-watch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/repo-tools': patch ---- - -Bump `@microsoft/api-documenter` and `@microsoft/api-extractor` to latest versions. diff --git a/.changeset/lucky-days-hug.md b/.changeset/lucky-days-hug.md deleted file mode 100644 index 4d76caa098..0000000000 --- a/.changeset/lucky-days-hug.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-kubernetes-react': patch -'@backstage/plugin-kubernetes': patch ---- - -add missing i18n support for kubernetes and kubernetes-react diff --git a/.changeset/major-mangos-shine.md b/.changeset/major-mangos-shine.md new file mode 100644 index 0000000000..f42fcf5d0e --- /dev/null +++ b/.changeset/major-mangos-shine.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-openapi-utils': patch +--- + +Internal update to use native feature from our request validation library for handling base path determination. diff --git a/.changeset/many-planes-join.md b/.changeset/many-planes-join.md deleted file mode 100644 index 66107cd370..0000000000 --- a/.changeset/many-planes-join.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/core-app-api': patch -'@backstage/test-utils': patch ---- - -Internal update of translation imports. diff --git a/.changeset/metal-boxes-laugh.md b/.changeset/metal-boxes-laugh.md deleted file mode 100644 index 9a5ab24e0e..0000000000 --- a/.changeset/metal-boxes-laugh.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-plugin-api': patch ---- - -The `useApp` and `useRouteRef` functions are now forwards compatible with the new frontend system. Along with the previous route reference changes this means that there is no longer a need to use `compatWrapper` from `@backstage/core-compat-api` to make code based on `@backstage/core-plugin-api` compatible with `@backstage/frontend-plugin-api` APIs. diff --git a/.changeset/metal-humans-lose.md b/.changeset/metal-humans-lose.md deleted file mode 100644 index f96d33a779..0000000000 --- a/.changeset/metal-humans-lose.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -'@backstage/plugin-catalog-unprocessed-entities': patch -'@backstage/plugin-app-visualizer': patch -'@backstage/plugin-catalog-import': patch -'@backstage/plugin-catalog-graph': patch -'@backstage/plugin-catalog-react': patch -'@backstage/plugin-notifications': patch -'@backstage/plugin-user-settings': patch -'@backstage/plugin-kubernetes': patch -'@backstage/plugin-scaffolder': patch -'@backstage/plugin-api-docs': patch -'@backstage/plugin-devtools': patch -'@backstage/plugin-techdocs': patch -'@backstage/plugin-catalog': patch -'@backstage/plugin-search': patch -'@backstage/plugin-home': patch -'@backstage/plugin-app': patch -'@backstage/plugin-org': patch ---- - -Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. diff --git a/.changeset/modern-taxes-start.md b/.changeset/modern-taxes-start.md deleted file mode 100644 index 9fd7645570..0000000000 --- a/.changeset/modern-taxes-start.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli-common': patch ---- - -Added new `run`, `runOutput`, and `runCheck` utilities to help run child processes in a safe and portable way. diff --git a/.changeset/neat-pens-clean.md b/.changeset/neat-pens-clean.md deleted file mode 100644 index aff67a2a10..0000000000 --- a/.changeset/neat-pens-clean.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/repo-tools': patch ---- - -Properly create workspace in OS temporary directory for `generate-patch` command diff --git a/.changeset/nice-humans-cry.md b/.changeset/nice-humans-cry.md deleted file mode 100644 index c6119702b4..0000000000 --- a/.changeset/nice-humans-cry.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': patch -'@backstage/backend-defaults': patch ---- - -Internal change to support new versions of the `logform` library diff --git a/.changeset/nice-trams-shake.md b/.changeset/nice-trams-shake.md deleted file mode 100644 index b58c03200f..0000000000 --- a/.changeset/nice-trams-shake.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-react': patch ---- - -Fixed bug where custom `review.name` values were incorrectly formatted by `startCase`, preserving them exactly as written. diff --git a/.changeset/old-cats-shake.md b/.changeset/old-cats-shake.md deleted file mode 100644 index 3ca30a0421..0000000000 --- a/.changeset/old-cats-shake.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/backend-defaults': patch -'@backstage/backend-plugin-api': minor ---- - -Adds a new experimental `RootSystemMetadataService` for tracking the collection of Backstage instances that may be deployed at any one time. It currently offers a single API, `getInstalledPlugins` that returns a list of installed plugins based on config you have set up in `discovery.endpoints` as well as the plugins installed on the instance you're calling the API with. It does not handle wildcard values or fallback values. The intention is for this plugin to provide plugin authors with a simple interface to fetch a trustworthy list of all installed plugins. diff --git a/.changeset/old-parks-smell.md b/.changeset/old-parks-smell.md deleted file mode 100644 index f089c7da21..0000000000 --- a/.changeset/old-parks-smell.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -'@backstage/plugin-techdocs-addons-test-utils': major ---- - -**BREAKING**: `TechDocsAddonTester.renderWithEffects()` no longer returns a screen; this means that you can no longer grab assertions such as `getByText` from its return value. - -Newer versions of `@testing-library` recommends using the `screen` export for assertions - and removing this from the addon tester contract allows us to more freely iterate on which underlying version of the testing library is being used. - -One notable effect of this, however, is that the `@testing-library` `screen` does NOT support assertions on the shadow DOM, which techdocs relies on. You will therefore want to add a dependency on [the `shadow-dom-testing-library` package](https://github.com/konnorrogers/shadow-dom-testing-library/) in your tests, and using its `screen` and its dedicated `*Shadow*` methods. As an example, if you keep doing `getByText` you will not get matches inside the shadow DOM - switch to `getByShadowText` instead. - -```ts -import { screen } from 'shadow-dom-testing-library'; - -// ... render the addon ... -await TechDocsAddonTester.buildAddonsInTechDocs([]) - .withDom(TEST_CONTENT) - .renderWithEffects(); - -expect(screen.getByShadowText('TEST_CONTENT')).toBeInTheDocument(); -``` diff --git a/.changeset/open-points-beam.md b/.changeset/open-points-beam.md deleted file mode 100644 index b58bf2b3d5..0000000000 --- a/.changeset/open-points-beam.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -'@backstage/ui': minor ---- - -**Breaking change** The `Cell` component has been refactored to be a generic wrapper component that accepts `children` for custom cell content. The text-specific functionality (previously part of `Cell`) has been moved to a new `CellText` component. - -### Migration Guide - -If you were using `Cell` with text-specific props (`title`, `description`, `leadingIcon`, `href`), you need to update your code to use `CellText` instead: - -**Before:** - -```tsx -} - href="/path" -/> -``` - -**After:** - -```tsx -} - href="/path" -/> -``` - -For custom cell content, use the new generic `Cell` component: - -```tsx -{/* Your custom content */} -``` diff --git a/.changeset/polite-pillows-accept.md b/.changeset/polite-pillows-accept.md new file mode 100644 index 0000000000..ece7c02ee1 --- /dev/null +++ b/.changeset/polite-pillows-accept.md @@ -0,0 +1,5 @@ +--- +'@backstage/integration': patch +--- + +Rollback the lowercase replacing in GitHub integration config diff --git a/.changeset/pre.json b/.changeset/pre.json index f44b869497..9b396bf7a7 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -2,256 +2,221 @@ "mode": "pre", "tag": "next", "initialVersions": { - "example-app": "0.2.115", - "@backstage/app-defaults": "1.7.2", - "example-app-next": "0.0.29", - "app-next-example-plugin": "0.0.29", - "example-backend": "0.0.44", - "@backstage/backend-app-api": "1.3.0", - "@backstage/backend-defaults": "0.13.1", - "@backstage/backend-dev-utils": "0.1.5", - "@backstage/backend-dynamic-feature-service": "0.7.6", - "@backstage/backend-openapi-utils": "0.6.3", - "@backstage/backend-plugin-api": "1.5.0", - "@backstage/backend-test-utils": "1.10.0", + "example-app": "0.2.116", + "@backstage/app-defaults": "1.7.3", + "example-app-next": "0.0.30", + "app-next-example-plugin": "0.0.30", + "example-backend": "0.0.45", + "@backstage/backend-app-api": "1.4.0", + "@backstage/backend-defaults": "0.14.0", + "@backstage/backend-dev-utils": "0.1.6", + "@backstage/backend-dynamic-feature-service": "0.7.7", + "@backstage/backend-openapi-utils": "0.6.4", + "@backstage/backend-plugin-api": "1.6.0", + "@backstage/backend-test-utils": "1.10.2", "@backstage/catalog-client": "1.12.1", "@backstage/catalog-model": "1.7.6", - "@backstage/cli": "0.34.5", - "@backstage/cli-common": "0.1.15", - "@backstage/cli-node": "0.2.15", - "@backstage/codemods": "0.1.52", + "@backstage/cli": "0.35.0", + "@backstage/cli-common": "0.1.16", + "@backstage/cli-node": "0.2.16", + "@backstage/codemods": "0.1.53", "@backstage/config": "1.3.6", - "@backstage/config-loader": "1.10.6", - "@backstage/core-app-api": "1.19.2", - "@backstage/core-compat-api": "0.5.4", - "@backstage/core-components": "0.18.3", - "@backstage/core-plugin-api": "1.12.0", - "@backstage/create-app": "0.7.6", - "@backstage/dev-utils": "1.1.17", - "e2e-test": "0.2.34", + "@backstage/config-loader": "1.10.7", + "@backstage/core-app-api": "1.19.3", + "@backstage/core-compat-api": "0.5.5", + "@backstage/core-components": "0.18.4", + "@backstage/core-plugin-api": "1.12.1", + "@backstage/create-app": "0.7.7", + "@backstage/dev-utils": "1.1.18", + "e2e-test": "0.2.35", "@backstage/e2e-test-utils": "0.1.1", "@backstage/errors": "1.2.7", "@backstage/eslint-plugin": "0.2.0", - "@backstage/frontend-app-api": "0.13.2", - "@backstage/frontend-defaults": "0.3.3", - "@backstage/frontend-dynamic-feature-loader": "0.1.7", - "@internal/frontend": "0.0.15", - "@backstage/frontend-plugin-api": "0.13.0", - "@backstage/frontend-test-utils": "0.4.1", - "@backstage/integration": "1.18.2", + "@backstage/frontend-app-api": "0.13.3", + "@backstage/frontend-defaults": "0.3.4", + "@backstage/frontend-dynamic-feature-loader": "0.1.8", + "@internal/frontend": "0.0.16", + "@backstage/frontend-plugin-api": "0.13.2", + "@backstage/frontend-test-utils": "0.4.2", + "@backstage/integration": "1.19.0", "@backstage/integration-aws-node": "0.1.19", - "@backstage/integration-react": "1.2.12", + "@backstage/integration-react": "1.2.13", "@internal/opaque": "0.0.1", "@backstage/release-manifests": "0.0.13", - "@backstage/repo-tools": "0.16.0", - "@internal/scaffolder": "0.0.15", - "@techdocs/cli": "1.10.2", - "techdocs-cli-embedded-app": "0.2.114", - "@backstage/test-utils": "1.7.13", - "@backstage/theme": "0.7.0", + "@backstage/repo-tools": "0.16.1", + "@internal/scaffolder": "0.0.16", + "@techdocs/cli": "1.10.3", + "techdocs-cli-embedded-app": "0.2.115", + "@backstage/test-utils": "1.7.14", + "@backstage/theme": "0.7.1", "@backstage/types": "1.2.2", - "@backstage/ui": "0.9.0", + "@backstage/ui": "0.10.0", "@backstage/version-bridge": "1.0.11", - "yarn-plugin-backstage": "0.0.7", - "@backstage/plugin-api-docs": "0.13.1", + "yarn-plugin-backstage": "0.0.8", + "@backstage/plugin-api-docs": "0.13.2", "@backstage/plugin-api-docs-module-protoc-gen-doc": "0.1.10", - "@backstage/plugin-app": "0.3.2", - "@backstage/plugin-app-backend": "0.5.8", - "@backstage/plugin-app-node": "0.1.39", - "@backstage/plugin-app-visualizer": "0.1.25", - "@backstage/plugin-auth": "0.1.2", - "@backstage/plugin-auth-backend": "0.25.6", - "@backstage/plugin-auth-backend-module-atlassian-provider": "0.4.9", - "@backstage/plugin-auth-backend-module-auth0-provider": "0.2.9", - "@backstage/plugin-auth-backend-module-aws-alb-provider": "0.4.9", - "@backstage/plugin-auth-backend-module-azure-easyauth-provider": "0.2.14", - "@backstage/plugin-auth-backend-module-bitbucket-provider": "0.3.9", - "@backstage/plugin-auth-backend-module-bitbucket-server-provider": "0.2.9", - "@backstage/plugin-auth-backend-module-cloudflare-access-provider": "0.4.9", - "@backstage/plugin-auth-backend-module-gcp-iap-provider": "0.4.9", - "@backstage/plugin-auth-backend-module-github-provider": "0.3.9", - "@backstage/plugin-auth-backend-module-gitlab-provider": "0.3.9", - "@backstage/plugin-auth-backend-module-google-provider": "0.3.9", - "@backstage/plugin-auth-backend-module-guest-provider": "0.2.14", - "@backstage/plugin-auth-backend-module-microsoft-provider": "0.3.9", - "@backstage/plugin-auth-backend-module-oauth2-provider": "0.4.9", - "@backstage/plugin-auth-backend-module-oauth2-proxy-provider": "0.2.14", - "@backstage/plugin-auth-backend-module-oidc-provider": "0.4.9", - "@backstage/plugin-auth-backend-module-okta-provider": "0.2.9", - "@backstage/plugin-auth-backend-module-onelogin-provider": "0.3.9", - "@backstage/plugin-auth-backend-module-openshift-provider": "0.1.2", - "@backstage/plugin-auth-backend-module-pinniped-provider": "0.3.9", - "@backstage/plugin-auth-backend-module-vmware-cloud-provider": "0.5.9", - "@backstage/plugin-auth-node": "0.6.9", - "@backstage/plugin-auth-react": "0.1.21", - "@backstage/plugin-bitbucket-cloud-common": "0.3.4", - "@backstage/plugin-catalog": "1.32.0", - "@backstage/plugin-catalog-backend": "3.2.0", - "@backstage/plugin-catalog-backend-module-aws": "0.4.17", - "@backstage/plugin-catalog-backend-module-azure": "0.3.11", - "@backstage/plugin-catalog-backend-module-backstage-openapi": "0.5.8", - "@backstage/plugin-catalog-backend-module-bitbucket-cloud": "0.5.5", - "@backstage/plugin-catalog-backend-module-bitbucket-server": "0.5.5", - "@backstage/plugin-catalog-backend-module-gcp": "0.3.14", - "@backstage/plugin-catalog-backend-module-gerrit": "0.3.8", - "@backstage/plugin-catalog-backend-module-gitea": "0.1.6", - "@backstage/plugin-catalog-backend-module-github": "0.11.2", - "@backstage/plugin-catalog-backend-module-github-org": "0.3.16", - "@backstage/plugin-catalog-backend-module-gitlab": "0.7.5", - "@backstage/plugin-catalog-backend-module-gitlab-org": "0.2.15", - "@backstage/plugin-catalog-backend-module-incremental-ingestion": "0.7.6", - "@backstage/plugin-catalog-backend-module-ldap": "0.12.0", - "@backstage/plugin-catalog-backend-module-logs": "0.1.16", - "@backstage/plugin-catalog-backend-module-msgraph": "0.8.2", - "@backstage/plugin-catalog-backend-module-openapi": "0.2.16", - "@backstage/plugin-catalog-backend-module-puppetdb": "0.2.16", - "@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "0.2.14", - "@backstage/plugin-catalog-backend-module-unprocessed": "0.6.6", + "@backstage/plugin-app": "0.3.3", + "@backstage/plugin-app-backend": "0.5.9", + "@backstage/plugin-app-node": "0.1.40", + "@backstage/plugin-app-visualizer": "0.1.26", + "@backstage/plugin-auth": "0.1.3", + "@backstage/plugin-auth-backend": "0.25.7", + "@backstage/plugin-auth-backend-module-atlassian-provider": "0.4.10", + "@backstage/plugin-auth-backend-module-auth0-provider": "0.2.10", + "@backstage/plugin-auth-backend-module-aws-alb-provider": "0.4.10", + "@backstage/plugin-auth-backend-module-azure-easyauth-provider": "0.2.15", + "@backstage/plugin-auth-backend-module-bitbucket-provider": "0.3.10", + "@backstage/plugin-auth-backend-module-bitbucket-server-provider": "0.2.10", + "@backstage/plugin-auth-backend-module-cloudflare-access-provider": "0.4.10", + "@backstage/plugin-auth-backend-module-gcp-iap-provider": "0.4.10", + "@backstage/plugin-auth-backend-module-github-provider": "0.4.0", + "@backstage/plugin-auth-backend-module-gitlab-provider": "0.3.10", + "@backstage/plugin-auth-backend-module-google-provider": "0.3.10", + "@backstage/plugin-auth-backend-module-guest-provider": "0.2.15", + "@backstage/plugin-auth-backend-module-microsoft-provider": "0.3.10", + "@backstage/plugin-auth-backend-module-oauth2-provider": "0.4.10", + "@backstage/plugin-auth-backend-module-oauth2-proxy-provider": "0.2.15", + "@backstage/plugin-auth-backend-module-oidc-provider": "0.4.10", + "@backstage/plugin-auth-backend-module-okta-provider": "0.2.10", + "@backstage/plugin-auth-backend-module-onelogin-provider": "0.3.10", + "@backstage/plugin-auth-backend-module-openshift-provider": "0.1.3", + "@backstage/plugin-auth-backend-module-pinniped-provider": "0.3.10", + "@backstage/plugin-auth-backend-module-vmware-cloud-provider": "0.5.10", + "@backstage/plugin-auth-node": "0.6.10", + "@backstage/plugin-auth-react": "0.1.22", + "@backstage/plugin-bitbucket-cloud-common": "0.3.5", + "@backstage/plugin-catalog": "1.32.1", + "@backstage/plugin-catalog-backend": "3.3.0", + "@backstage/plugin-catalog-backend-module-aws": "0.4.18", + "@backstage/plugin-catalog-backend-module-azure": "0.3.12", + "@backstage/plugin-catalog-backend-module-backstage-openapi": "0.5.9", + "@backstage/plugin-catalog-backend-module-bitbucket-cloud": "0.5.6", + "@backstage/plugin-catalog-backend-module-bitbucket-server": "0.5.6", + "@backstage/plugin-catalog-backend-module-gcp": "0.3.15", + "@backstage/plugin-catalog-backend-module-gerrit": "0.3.9", + "@backstage/plugin-catalog-backend-module-gitea": "0.1.7", + "@backstage/plugin-catalog-backend-module-github": "0.12.0", + "@backstage/plugin-catalog-backend-module-github-org": "0.3.17", + "@backstage/plugin-catalog-backend-module-gitlab": "0.7.6", + "@backstage/plugin-catalog-backend-module-gitlab-org": "0.2.16", + "@backstage/plugin-catalog-backend-module-incremental-ingestion": "0.7.7", + "@backstage/plugin-catalog-backend-module-ldap": "0.12.1", + "@backstage/plugin-catalog-backend-module-logs": "0.1.17", + "@backstage/plugin-catalog-backend-module-msgraph": "0.8.3", + "@backstage/plugin-catalog-backend-module-openapi": "0.2.17", + "@backstage/plugin-catalog-backend-module-puppetdb": "0.2.17", + "@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "0.2.15", + "@backstage/plugin-catalog-backend-module-unprocessed": "0.6.7", "@backstage/plugin-catalog-common": "1.1.7", - "@backstage/plugin-catalog-graph": "0.5.3", - "@backstage/plugin-catalog-import": "0.13.7", - "@backstage/plugin-catalog-node": "1.20.0", - "@backstage/plugin-catalog-react": "1.21.3", - "@backstage/plugin-catalog-unprocessed-entities": "0.2.23", - "@backstage/plugin-catalog-unprocessed-entities-common": "0.0.11", - "@backstage/plugin-config-schema": "0.1.74", - "@backstage/plugin-devtools": "0.1.33", - "@backstage/plugin-devtools-backend": "0.5.11", - "@backstage/plugin-devtools-common": "0.1.19", - "@backstage/plugin-events-backend": "0.5.8", - "@backstage/plugin-events-backend-module-aws-sqs": "0.4.17", - "@backstage/plugin-events-backend-module-azure": "0.2.26", - "@backstage/plugin-events-backend-module-bitbucket-cloud": "0.2.26", - "@backstage/plugin-events-backend-module-bitbucket-server": "0.1.7", - "@backstage/plugin-events-backend-module-gerrit": "0.2.26", - "@backstage/plugin-events-backend-module-github": "0.4.6", - "@backstage/plugin-events-backend-module-gitlab": "0.3.7", - "@backstage/plugin-events-backend-module-google-pubsub": "0.1.6", - "@backstage/plugin-events-backend-module-kafka": "0.1.5", - "@backstage/plugin-events-backend-test-utils": "0.1.50", - "@backstage/plugin-events-node": "0.4.17", - "@internal/plugin-todo-list": "1.0.45", - "@internal/plugin-todo-list-backend": "1.0.45", + "@backstage/plugin-catalog-graph": "0.5.4", + "@backstage/plugin-catalog-import": "0.13.8", + "@backstage/plugin-catalog-node": "1.20.1", + "@backstage/plugin-catalog-react": "1.21.4", + "@backstage/plugin-catalog-unprocessed-entities": "0.2.24", + "@backstage/plugin-catalog-unprocessed-entities-common": "0.0.12", + "@backstage/plugin-config-schema": "0.1.75", + "@backstage/plugin-devtools": "0.1.34", + "@backstage/plugin-devtools-backend": "0.5.12", + "@backstage/plugin-devtools-common": "0.1.20", + "@backstage/plugin-events-backend": "0.5.9", + "@backstage/plugin-events-backend-module-aws-sqs": "0.4.18", + "@backstage/plugin-events-backend-module-azure": "0.2.27", + "@backstage/plugin-events-backend-module-bitbucket-cloud": "0.2.27", + "@backstage/plugin-events-backend-module-bitbucket-server": "0.1.8", + "@backstage/plugin-events-backend-module-gerrit": "0.2.27", + "@backstage/plugin-events-backend-module-github": "0.4.7", + "@backstage/plugin-events-backend-module-gitlab": "0.3.8", + "@backstage/plugin-events-backend-module-google-pubsub": "0.1.7", + "@backstage/plugin-events-backend-module-kafka": "0.2.0", + "@backstage/plugin-events-backend-test-utils": "0.1.51", + "@backstage/plugin-events-node": "0.4.18", + "@internal/plugin-todo-list": "1.0.46", + "@internal/plugin-todo-list-backend": "1.0.46", "@internal/plugin-todo-list-common": "1.0.28", - "@backstage/plugin-gateway-backend": "1.1.0", - "@backstage/plugin-home": "0.8.14", - "@backstage/plugin-home-react": "0.1.32", - "@backstage/plugin-kubernetes": "0.12.13", - "@backstage/plugin-kubernetes-backend": "0.20.4", - "@backstage/plugin-kubernetes-cluster": "0.0.31", - "@backstage/plugin-kubernetes-common": "0.9.8", - "@backstage/plugin-kubernetes-node": "0.3.6", - "@backstage/plugin-kubernetes-react": "0.5.13", - "@backstage/plugin-mcp-actions-backend": "0.1.5", - "@backstage/plugin-mui-to-bui": "0.2.1", - "@backstage/plugin-notifications": "0.5.11", - "@backstage/plugin-notifications-backend": "0.6.0", - "@backstage/plugin-notifications-backend-module-email": "0.3.16", - "@backstage/plugin-notifications-backend-module-slack": "0.2.1", + "@backstage/plugin-gateway-backend": "1.1.1", + "@backstage/plugin-home": "0.8.15", + "@backstage/plugin-home-react": "0.1.33", + "@backstage/plugin-kubernetes": "0.12.14", + "@backstage/plugin-kubernetes-backend": "0.21.0", + "@backstage/plugin-kubernetes-cluster": "0.0.32", + "@backstage/plugin-kubernetes-common": "0.9.9", + "@backstage/plugin-kubernetes-node": "0.4.0", + "@backstage/plugin-kubernetes-react": "0.5.14", + "@backstage/plugin-mcp-actions-backend": "0.1.6", + "@backstage/plugin-mui-to-bui": "0.2.2", + "@backstage/plugin-notifications": "0.5.12", + "@backstage/plugin-notifications-backend": "0.6.1", + "@backstage/plugin-notifications-backend-module-email": "0.3.17", + "@backstage/plugin-notifications-backend-module-slack": "0.3.0", "@backstage/plugin-notifications-common": "0.2.0", - "@backstage/plugin-notifications-node": "0.2.21", - "@backstage/plugin-org": "0.6.46", - "@backstage/plugin-org-react": "0.1.44", - "@backstage/plugin-permission-backend": "0.7.6", - "@backstage/plugin-permission-backend-module-allow-all-policy": "0.2.14", + "@backstage/plugin-notifications-node": "0.2.22", + "@backstage/plugin-org": "0.6.47", + "@backstage/plugin-org-react": "0.1.45", + "@backstage/plugin-permission-backend": "0.7.7", + "@backstage/plugin-permission-backend-module-allow-all-policy": "0.2.15", "@backstage/plugin-permission-common": "0.9.3", - "@backstage/plugin-permission-node": "0.10.6", - "@backstage/plugin-permission-react": "0.4.38", - "@backstage/plugin-proxy-backend": "0.6.8", - "@backstage/plugin-proxy-node": "0.1.10", - "@backstage/plugin-scaffolder": "1.34.3", - "@backstage/plugin-scaffolder-backend": "3.0.1", - "@backstage/plugin-scaffolder-backend-module-azure": "0.2.15", - "@backstage/plugin-scaffolder-backend-module-bitbucket": "0.3.16", - "@backstage/plugin-scaffolder-backend-module-bitbucket-cloud": "0.2.15", - "@backstage/plugin-scaffolder-backend-module-bitbucket-server": "0.2.15", - "@backstage/plugin-scaffolder-backend-module-confluence-to-markdown": "0.3.15", - "@backstage/plugin-scaffolder-backend-module-cookiecutter": "0.3.17", - "@backstage/plugin-scaffolder-backend-module-gcp": "0.2.15", - "@backstage/plugin-scaffolder-backend-module-gerrit": "0.2.15", - "@backstage/plugin-scaffolder-backend-module-gitea": "0.2.15", - "@backstage/plugin-scaffolder-backend-module-github": "0.9.2", - "@backstage/plugin-scaffolder-backend-module-gitlab": "0.10.0", - "@backstage/plugin-scaffolder-backend-module-notifications": "0.1.16", - "@backstage/plugin-scaffolder-backend-module-rails": "0.5.15", - "@backstage/plugin-scaffolder-backend-module-sentry": "0.2.15", - "@backstage/plugin-scaffolder-backend-module-yeoman": "0.4.16", - "@backstage/plugin-scaffolder-common": "1.7.3", - "@backstage/plugin-scaffolder-node": "0.12.1", - "@backstage/plugin-scaffolder-node-test-utils": "0.3.5", - "@backstage/plugin-scaffolder-react": "1.19.3", - "@backstage/plugin-search": "1.5.0", - "@backstage/plugin-search-backend": "2.0.8", - "@backstage/plugin-search-backend-module-catalog": "0.3.10", - "@backstage/plugin-search-backend-module-elasticsearch": "1.7.8", - "@backstage/plugin-search-backend-module-explore": "0.3.9", - "@backstage/plugin-search-backend-module-pg": "0.5.50", - "@backstage/plugin-search-backend-module-stack-overflow-collator": "0.3.15", - "@backstage/plugin-search-backend-module-techdocs": "0.4.8", - "@backstage/plugin-search-backend-node": "1.3.17", + "@backstage/plugin-permission-node": "0.10.7", + "@backstage/plugin-permission-react": "0.4.39", + "@backstage/plugin-proxy-backend": "0.6.9", + "@backstage/plugin-proxy-node": "0.1.11", + "@backstage/plugin-scaffolder": "1.35.0", + "@backstage/plugin-scaffolder-backend": "3.1.0", + "@backstage/plugin-scaffolder-backend-module-azure": "0.2.16", + "@backstage/plugin-scaffolder-backend-module-bitbucket": "0.3.17", + "@backstage/plugin-scaffolder-backend-module-bitbucket-cloud": "0.3.0", + "@backstage/plugin-scaffolder-backend-module-bitbucket-server": "0.2.16", + "@backstage/plugin-scaffolder-backend-module-confluence-to-markdown": "0.3.16", + "@backstage/plugin-scaffolder-backend-module-cookiecutter": "0.3.18", + "@backstage/plugin-scaffolder-backend-module-gcp": "0.2.16", + "@backstage/plugin-scaffolder-backend-module-gerrit": "0.2.16", + "@backstage/plugin-scaffolder-backend-module-gitea": "0.2.16", + "@backstage/plugin-scaffolder-backend-module-github": "0.9.3", + "@backstage/plugin-scaffolder-backend-module-gitlab": "0.11.0", + "@backstage/plugin-scaffolder-backend-module-notifications": "0.1.17", + "@backstage/plugin-scaffolder-backend-module-rails": "0.5.16", + "@backstage/plugin-scaffolder-backend-module-sentry": "0.2.16", + "@backstage/plugin-scaffolder-backend-module-yeoman": "0.4.17", + "@backstage/plugin-scaffolder-common": "1.7.4", + "@backstage/plugin-scaffolder-node": "0.12.2", + "@backstage/plugin-scaffolder-node-test-utils": "0.3.6", + "@backstage/plugin-scaffolder-react": "1.19.4", + "@backstage/plugin-search": "1.5.1", + "@backstage/plugin-search-backend": "2.0.9", + "@backstage/plugin-search-backend-module-catalog": "0.3.11", + "@backstage/plugin-search-backend-module-elasticsearch": "1.7.9", + "@backstage/plugin-search-backend-module-explore": "0.3.10", + "@backstage/plugin-search-backend-module-pg": "0.5.51", + "@backstage/plugin-search-backend-module-stack-overflow-collator": "0.3.16", + "@backstage/plugin-search-backend-module-techdocs": "0.4.9", + "@backstage/plugin-search-backend-node": "1.4.0", "@backstage/plugin-search-common": "1.2.21", - "@backstage/plugin-search-react": "1.10.0", - "@backstage/plugin-signals": "0.0.25", - "@backstage/plugin-signals-backend": "0.3.10", - "@backstage/plugin-signals-node": "0.1.26", - "@backstage/plugin-signals-react": "0.0.17", - "@backstage/plugin-techdocs": "1.16.0", - "@backstage/plugin-techdocs-addons-test-utils": "1.1.2", - "@backstage/plugin-techdocs-backend": "2.1.2", + "@backstage/plugin-search-react": "1.10.1", + "@backstage/plugin-signals": "0.0.26", + "@backstage/plugin-signals-backend": "0.3.11", + "@backstage/plugin-signals-node": "0.1.27", + "@backstage/plugin-signals-react": "0.0.18", + "@backstage/plugin-techdocs": "1.16.1", + "@backstage/plugin-techdocs-addons-test-utils": "2.0.0", + "@backstage/plugin-techdocs-backend": "2.1.3", "@backstage/plugin-techdocs-common": "0.1.1", - "@backstage/plugin-techdocs-module-addons-contrib": "1.1.30", - "@backstage/plugin-techdocs-node": "1.13.9", - "@backstage/plugin-techdocs-react": "1.3.5", - "@backstage/plugin-user-settings": "0.8.29", - "@backstage/plugin-user-settings-backend": "0.3.8", + "@backstage/plugin-techdocs-module-addons-contrib": "1.1.31", + "@backstage/plugin-techdocs-node": "1.13.10", + "@backstage/plugin-techdocs-react": "1.3.6", + "@backstage/plugin-user-settings": "0.8.30", + "@backstage/plugin-user-settings-backend": "0.3.9", "@backstage/plugin-user-settings-common": "0.0.1" }, "changesets": [ - "afraid-items-drum", - "bumpy-planets-go", - "chatty-sides-wear", - "chilly-bikes-rule", - "chilly-hotels-walk", - "clean-toys-reply", - "common-coins-stare", - "create-app-1764689798", - "famous-jars-lose", - "fifty-coats-feel", - "fine-eagles-sleep", - "flat-pillows-rush", - "floppy-bobcats-serve", - "four-peaches-train", - "fruity-rivers-arrive", - "fruity-words-melt", - "funny-papayas-rest", - "fuzzy-phones-own", - "fuzzy-trees-live", - "gentle-trains-juggle", - "great-files-shave", - "happy-bottles-invite", - "kind-hoops-double", - "legal-cloths-spend", - "legal-otters-punch", - "loose-pets-slide", - "lucky-days-hug", - "many-planes-join", - "metal-boxes-laugh", - "metal-humans-lose", - "modern-taxes-start", - "neat-pens-clean", - "nice-trams-shake", - "old-parks-smell", - "open-points-beam", - "quiet-hats-sleep", - "rotten-melons-sleep", - "short-groups-knock", - "slick-books-sleep", - "slick-onions-wash", - "slimy-islands-play", - "spicy-teeth-study", - "stale-eagles-rush", - "tender-dancers-hunt", - "tough-lies-grow", - "twenty-ducks-relate" + "better-ghosts-tell", + "create-app-1766498726", + "dependabot-aed8e01", + "every-bears-add", + "hot-colts-float", + "major-mangos-shine", + "proud-streets-switch", + "shaggy-bats-film", + "thin-teams-roll", + "weak-lemons-create", + "wild-toys-retire" ] } diff --git a/.changeset/proud-streets-switch.md b/.changeset/proud-streets-switch.md new file mode 100644 index 0000000000..188b66f178 --- /dev/null +++ b/.changeset/proud-streets-switch.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend-module-oidc-provider': patch +--- + +Added support for custom start URL search parameters (with the new `startUrlSearchParams` config property) diff --git a/.changeset/quiet-hats-sleep.md b/.changeset/quiet-hats-sleep.md deleted file mode 100644 index 5f75f22f6c..0000000000 --- a/.changeset/quiet-hats-sleep.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': patch ---- - -Fixing OpenAPI definition diff --git a/.changeset/rare-rice-throw.md b/.changeset/rare-rice-throw.md deleted file mode 100644 index 6fa0434f67..0000000000 --- a/.changeset/rare-rice-throw.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-components': patch ---- - -Add `tooltipClasses` prop to `OverflowTooltip` component to allow customisation of the tooltip diff --git a/.changeset/ready-results-march.md b/.changeset/ready-results-march.md deleted file mode 100644 index c28ade8de9..0000000000 --- a/.changeset/ready-results-march.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog': patch ---- - -Fixed `catalogAboutEntityCard` to filter icon links before calling useProps(), preventing side effects from hooks in filtered-out links diff --git a/.changeset/renovate-7b76d6d.md b/.changeset/renovate-7b76d6d.md deleted file mode 100644 index 9ccb2dd94b..0000000000 --- a/.changeset/renovate-7b76d6d.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/cli': patch -'@backstage/plugin-scaffolder-backend': patch ---- - -Updated dependency `esbuild` to `^0.27.0`. diff --git a/.changeset/renovate-959c095.md b/.changeset/renovate-959c095.md deleted file mode 100644 index d2370a1c8b..0000000000 --- a/.changeset/renovate-959c095.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@backstage/plugin-home-react': patch -'@backstage/plugin-home': patch -'@backstage/plugin-scaffolder-react': patch -'@backstage/plugin-scaffolder': patch ---- - -Updated dependency `@rjsf/utils` to `5.24.13`. -Updated dependency `@rjsf/core` to `5.24.13`. -Updated dependency `@rjsf/material-ui` to `5.24.13`. -Updated dependency `@rjsf/validator-ajv8` to `5.24.13`. diff --git a/.changeset/renovate-97eef4b.md b/.changeset/renovate-97eef4b.md deleted file mode 100644 index 9b3692bc1c..0000000000 --- a/.changeset/renovate-97eef4b.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/config-loader': patch ---- - -Updated dependency `typescript-json-schema` to `^0.67.0`. diff --git a/.changeset/renovate-9ec01ff.md b/.changeset/renovate-9ec01ff.md deleted file mode 100644 index 1ab750c0e6..0000000000 --- a/.changeset/renovate-9ec01ff.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-search-backend-module-explore': patch ---- - -Updated dependency `@backstage-community/plugin-explore-common` to `^0.9.0`. diff --git a/.changeset/renovate-a3c2cbd.md b/.changeset/renovate-a3c2cbd.md deleted file mode 100644 index 2fde85d39e..0000000000 --- a/.changeset/renovate-a3c2cbd.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-react': patch ---- - -Updated dependency `use-immer` to `^0.11.0`. diff --git a/.changeset/renovate-aa0bb93.md b/.changeset/renovate-aa0bb93.md deleted file mode 100644 index 5f40a61fab..0000000000 --- a/.changeset/renovate-aa0bb93.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-notifications-backend-module-email': patch ---- - -Updated dependency `@types/nodemailer` to `^7.0.0`. diff --git a/.changeset/renovate-ad7bf17.md b/.changeset/renovate-ad7bf17.md deleted file mode 100644 index a0f90ff97d..0000000000 --- a/.changeset/renovate-ad7bf17.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-defaults': patch ---- - -Updated dependency `@types/archiver` to `^7.0.0`. diff --git a/.changeset/renovate-d7ceb06.md b/.changeset/renovate-d7ceb06.md deleted file mode 100644 index d22f266301..0000000000 --- a/.changeset/renovate-d7ceb06.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Updated dependency `@pmmmwh/react-refresh-webpack-plugin` to `^0.6.0`. diff --git a/.changeset/renovate-ea25c93.md b/.changeset/renovate-ea25c93.md deleted file mode 100644 index 958e032b64..0000000000 --- a/.changeset/renovate-ea25c93.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Updated dependency `webpack` to `~5.103.0`. diff --git a/.changeset/rotten-melons-sleep.md b/.changeset/rotten-melons-sleep.md deleted file mode 100644 index c12e0a9669..0000000000 --- a/.changeset/rotten-melons-sleep.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -'@backstage/plugin-catalog-unprocessed-entities-common': patch -'@backstage/plugin-catalog-unprocessed-entities': patch ---- - -Moved types, API and client to the common package, allowing both frontend and -backend plugins to use the `CatalogUnprocessedEntitiesClient`. - -The following types, clients and interfaces have been deprecated and should be -imported from the `@backstage/plugin-catalog-unprocessed-entities-common` instead: -`CatalogUnprocessedEntitiesApi`, `CatalogUnprocessedEntitiesApiResponse`, `UnprocessedEntity`, -`UnprocessedEntityCache`, `UnprocessedEntityError`, `CatalogUnprocessedEntitiesClient`. - -All those types, clients and interfaces are re-exported temporarily in the -`@backstage/plugin-catalog-unprocessed-entities` package until cleaned up. diff --git a/.changeset/salty-camels-wash.md b/.changeset/salty-camels-wash.md deleted file mode 100644 index 56600db540..0000000000 --- a/.changeset/salty-camels-wash.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Fixed internal usage of `yargs`. diff --git a/.changeset/seven-games-rest.md b/.changeset/seven-games-rest.md deleted file mode 100644 index b498c3b138..0000000000 --- a/.changeset/seven-games-rest.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs-backend': patch ---- - -Corrected `ErrorCallback` type to work with Node 22 types diff --git a/.changeset/shaggy-bats-film.md b/.changeset/shaggy-bats-film.md new file mode 100644 index 0000000000..3e5be9648b --- /dev/null +++ b/.changeset/shaggy-bats-film.md @@ -0,0 +1,5 @@ +--- +'@backstage/ui': minor +--- + +**BREAKING**: Renamed CSS variable `--bui-bg` to `--bui-bg-surface-0` for consistency. diff --git a/.changeset/short-groups-knock.md b/.changeset/short-groups-knock.md deleted file mode 100644 index 0b622a71ed..0000000000 --- a/.changeset/short-groups-knock.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/cli-common': patch -'@backstage/create-app': patch -'@backstage/cli': patch ---- - -Add proxy configuration from env-vars to create-app tasks diff --git a/.changeset/slick-books-sleep.md b/.changeset/slick-books-sleep.md deleted file mode 100644 index 7aa3be5b03..0000000000 --- a/.changeset/slick-books-sleep.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/theme': patch ---- - -Added a `themeName` prop to `UnifiedThemeProvider`, enabling Backstage UI `data-theme-name` CSS attribute to be set based on active theme. diff --git a/.changeset/slick-onions-wash.md b/.changeset/slick-onions-wash.md deleted file mode 100644 index 4627d02e81..0000000000 --- a/.changeset/slick-onions-wash.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-components': patch ---- - -Add i18n support for LogViewer search control diff --git a/.changeset/slimy-islands-play.md b/.changeset/slimy-islands-play.md deleted file mode 100644 index 497d86761b..0000000000 --- a/.changeset/slimy-islands-play.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/ui': patch ---- - -Added row selection support with visual state styling for hover, selected, and pressed states. Fixed checkbox rendering to only show for multi-select toggle mode. - -Affected components: Table, TableHeader, Row, Column diff --git a/.changeset/slimy-mugs-taste.md b/.changeset/slimy-mugs-taste.md deleted file mode 100644 index 5773db6853..0000000000 --- a/.changeset/slimy-mugs-taste.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-test-utils': patch ---- - -Fix PostgreSQL 18 `TestDatabases` by pinning the data directory diff --git a/.changeset/sour-bats-press.md b/.changeset/sour-bats-press.md deleted file mode 100644 index bfcf3985e6..0000000000 --- a/.changeset/sour-bats-press.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-auth-node': patch ---- - -fix flawed cookie removal logic with chunked tokens diff --git a/.changeset/spicy-teeth-study.md b/.changeset/spicy-teeth-study.md deleted file mode 100644 index 03cc8a5440..0000000000 --- a/.changeset/spicy-teeth-study.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/ui': patch ---- - -Fixed `useTable` hook to prioritize `providedRowCount` over data length for accurate row count in server-side pagination scenarios. diff --git a/.changeset/stale-eagles-rush.md b/.changeset/stale-eagles-rush.md deleted file mode 100644 index fe640ccd44..0000000000 --- a/.changeset/stale-eagles-rush.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/frontend-plugin-api': patch -'@backstage/core-plugin-api': patch ---- - -Reversed the relationship between the old `@backstage/core-plugin-api` and the new `@backstage/frontend-plugin-api`. Previously, the a lot of API definitions and utilities where defined in the old and re-exported from the old, but this change flips that around so that they now reside in the new package and are re-exported from the old. The external API of both packages remain the same, but this is a step towards being able to add further compatibility with the new frontend system built into the old. diff --git a/.changeset/stupid-cases-fold.md b/.changeset/stupid-cases-fold.md deleted file mode 100644 index 5cf0f0f72a..0000000000 --- a/.changeset/stupid-cases-fold.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Switched ECMAScript version to ES2023. diff --git a/.changeset/tall-ideas-lead.md b/.changeset/tall-ideas-lead.md deleted file mode 100644 index 60bef903d8..0000000000 --- a/.changeset/tall-ideas-lead.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend-module-bitbucket-server': patch ---- - -Improve error message when provided target branch is missing diff --git a/.changeset/tame-mirrors-sit.md b/.changeset/tame-mirrors-sit.md deleted file mode 100644 index f317185ea2..0000000000 --- a/.changeset/tame-mirrors-sit.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-dev-utils': patch ---- - -Internal update for Node.js v24 support. diff --git a/.changeset/tender-dancers-hunt.md b/.changeset/tender-dancers-hunt.md deleted file mode 100644 index e20ec43ae0..0000000000 --- a/.changeset/tender-dancers-hunt.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Updated to use new utilities from `@backstage/cli-common`. diff --git a/.changeset/thin-teams-roll.md b/.changeset/thin-teams-roll.md new file mode 100644 index 0000000000..f0c395410a --- /dev/null +++ b/.changeset/thin-teams-roll.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-defaults': patch +--- + +Fixed a spelling mistake in root health service shutdown response. diff --git a/.changeset/tired-dogs-remain.md b/.changeset/tired-dogs-remain.md deleted file mode 100644 index 06c193068b..0000000000 --- a/.changeset/tired-dogs-remain.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend-module-rails': patch -'@backstage/plugin-kubernetes-cluster': patch -'@techdocs/cli': patch -'@backstage/cli-common': patch -'@backstage/create-app': patch -'@backstage/repo-tools': patch -'@backstage/codemods': patch -'@backstage/cli': patch ---- - -Bumped dev dependencies `@types/node` diff --git a/.changeset/tough-lies-grow.md b/.changeset/tough-lies-grow.md deleted file mode 100644 index dab952df65..0000000000 --- a/.changeset/tough-lies-grow.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-techdocs-backend': patch -'@backstage/plugin-techdocs': patch ---- - -The `techdocs` config is now marked as optional. diff --git a/.changeset/twenty-ducks-relate.md b/.changeset/twenty-ducks-relate.md deleted file mode 100644 index 359eda66f3..0000000000 --- a/.changeset/twenty-ducks-relate.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/ui': patch ---- - -Fixed Table column sorting indicator to show up arrow when no sort is active, correctly indicating that clicking will sort ascending. - -Affected components: Column diff --git a/.changeset/weak-lemons-create.md b/.changeset/weak-lemons-create.md new file mode 100644 index 0000000000..344a6660ce --- /dev/null +++ b/.changeset/weak-lemons-create.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Bump minimum required `@swc/core` to avoid transpilation bug diff --git a/.changeset/wild-toys-retire.md b/.changeset/wild-toys-retire.md new file mode 100644 index 0000000000..f7179e2527 --- /dev/null +++ b/.changeset/wild-toys-retire.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-mui-to-bui': patch +--- + +Updated tokens from `--bui-bg` to `--bui-bg-surface-0` diff --git a/.github/vale/config/vocabularies/Backstage/accept.txt b/.github/vale/config/vocabularies/Backstage/accept.txt index 6697fad858..44ee42a25a 100644 --- a/.github/vale/config/vocabularies/Backstage/accept.txt +++ b/.github/vale/config/vocabularies/Backstage/accept.txt @@ -268,6 +268,7 @@ maintainer's maintainership makefile Matomo +matchers md memcache memoization diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7552898bd0..36b4114efe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -203,7 +203,7 @@ jobs: env: CI: true - NODE_OPTIONS: --max-old-space-size=8192 --no-node-snapshot --experimental-vm-modules + NODE_OPTIONS: --max-old-space-size=8192 --experimental-vm-modules INTEGRATION_TEST_GITHUB_TOKEN: ${{ secrets.INTEGRATION_TEST_GITHUB_TOKEN }} INTEGRATION_TEST_GITLAB_TOKEN: ${{ secrets.INTEGRATION_TEST_GITLAB_TOKEN }} INTEGRATION_TEST_BITBUCKET_TOKEN: ${{ secrets.INTEGRATION_TEST_BITBUCKET_TOKEN }} diff --git a/.github/workflows/deploy_microsite.yml b/.github/workflows/deploy_microsite.yml index e799bcae00..08f349c7ec 100644 --- a/.github/workflows/deploy_microsite.yml +++ b/.github/workflows/deploy_microsite.yml @@ -329,7 +329,7 @@ jobs: run: ls microsite/build && ls microsite/build/storybook && ls microsite/build/api/stable && ls microsite/build/api/next - name: Deploy both microsite and storybook to gh-pages - uses: JamesIves/github-pages-deploy-action@4a3abc783e1a24aeb44c16e869ad83caf6b4cc23 # v4.7.4 + uses: JamesIves/github-pages-deploy-action@9d877eea73427180ae43cf98e8914934fe157a1a # v4.7.6 with: branch: gh-pages folder: microsite/build diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 96cb3368be..077eb2d856 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -67,6 +67,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: 'Upload to code-scanning' - uses: github/codeql-action/upload-sarif@497990dfed22177a82ba1bbab381bc8f6d27058f # v3.31.6 + uses: github/codeql-action/upload-sarif@f47c8e6a9bd05ef3ee422fc8d8663be7fe4bdc61 # v3.31.8 with: sarif_file: results.sarif diff --git a/.github/workflows/sync_patch-release.yml b/.github/workflows/sync_patch-release.yml index e17a229256..bdf93aa8a0 100644 --- a/.github/workflows/sync_patch-release.yml +++ b/.github/workflows/sync_patch-release.yml @@ -36,6 +36,12 @@ jobs: fetch-tags: true token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} + - name: Use Node.js 22.x + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version: 22.x + registry-url: https://registry.npmjs.org/ # Needed for auth + - name: Configure Git run: | git config --global user.email noreply@backstage.io diff --git a/.github/workflows/sync_snyk-monitor.yml b/.github/workflows/sync_snyk-monitor.yml index 8b76338645..632d03c35d 100644 --- a/.github/workflows/sync_snyk-monitor.yml +++ b/.github/workflows/sync_snyk-monitor.yml @@ -58,6 +58,6 @@ jobs: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} NODE_OPTIONS: --max-old-space-size=7168 - name: Upload Snyk report - uses: github/codeql-action/upload-sarif@497990dfed22177a82ba1bbab381bc8f6d27058f # v3.31.6 + uses: github/codeql-action/upload-sarif@f47c8e6a9bd05ef3ee422fc8d8663be7fe4bdc61 # v3.31.8 with: sarif_file: snyk.sarif diff --git a/.github/workflows/verify_codeql.yml b/.github/workflows/verify_codeql.yml index d06c8ea270..5d976f8583 100644 --- a/.github/workflows/verify_codeql.yml +++ b/.github/workflows/verify_codeql.yml @@ -55,7 +55,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@497990dfed22177a82ba1bbab381bc8f6d27058f # v3.31.6 + uses: github/codeql-action/init@f47c8e6a9bd05ef3ee422fc8d8663be7fe4bdc61 # v3.31.8 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -66,7 +66,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@497990dfed22177a82ba1bbab381bc8f6d27058f # v3.31.6 + uses: github/codeql-action/autobuild@f47c8e6a9bd05ef3ee422fc8d8663be7fe4bdc61 # v3.31.8 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -80,4 +80,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@497990dfed22177a82ba1bbab381bc8f6d27058f # v3.31.6 + uses: github/codeql-action/analyze@f47c8e6a9bd05ef3ee422fc8d8663be7fe4bdc61 # v3.31.8 diff --git a/.github/workflows/verify_e2e-windows.yml b/.github/workflows/verify_e2e-windows.yml index 933bbb0840..f63eb5d61b 100644 --- a/.github/workflows/verify_e2e-windows.yml +++ b/.github/workflows/verify_e2e-windows.yml @@ -28,7 +28,7 @@ jobs: env: CI: true - NODE_OPTIONS: --max-old-space-size=8192 --no-node-snapshot --experimental-vm-modules + NODE_OPTIONS: --max-old-space-size=8192 --experimental-vm-modules name: E2E Windows ${{ matrix.node-version }} steps: diff --git a/.github/workflows/verify_windows.yml b/.github/workflows/verify_windows.yml index ae2ec477d3..f7de04772d 100644 --- a/.github/workflows/verify_windows.yml +++ b/.github/workflows/verify_windows.yml @@ -21,7 +21,7 @@ jobs: env: CI: true - NODE_OPTIONS: --max-old-space-size=8192 --no-node-snapshot --experimental-vm-modules + NODE_OPTIONS: --max-old-space-size=8192 --experimental-vm-modules INTEGRATION_TEST_GITHUB_TOKEN: ${{ secrets.INTEGRATION_TEST_GITHUB_TOKEN }} INTEGRATION_TEST_GITLAB_TOKEN: ${{ secrets.INTEGRATION_TEST_GITLAB_TOKEN }} INTEGRATION_TEST_BITBUCKET_TOKEN: ${{ secrets.INTEGRATION_TEST_BITBUCKET_TOKEN }} diff --git a/.storybook/main.ts b/.storybook/main.ts index 788df83ba9..5453627f34 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -1,7 +1,13 @@ -import type { StorybookConfig } from '@storybook/react-vite'; +import { defineMain } from '@storybook/react-vite/node'; +import { fileURLToPath } from 'node:url'; +import { createRequire } from 'node:module'; import { join, dirname, posix } from 'path'; +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +const require = createRequire(import.meta.url); + const isChromatic = process.env.STORYBOOK_STORY_SET === 'chromatic'; // All stories for full development @@ -35,13 +41,14 @@ function getAbsolutePath(value: string): any { return dirname(require.resolve(join(value, 'package.json'))); } -const config: StorybookConfig = { +export default defineMain({ stories, addons: [ getAbsolutePath('@storybook/addon-links'), getAbsolutePath('@storybook/addon-themes'), getAbsolutePath('@storybook/addon-docs'), getAbsolutePath('@storybook/addon-a11y'), + getAbsolutePath('@storybook/addon-vitest'), ], framework: { name: getAbsolutePath('@storybook/react-vite'), @@ -122,6 +129,4 @@ const config: StorybookConfig = { return config; }, -}; - -export default config; +}); diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index 8f987ebab1..4e15677aed 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -1,8 +1,12 @@ -import React, { useEffect } from 'react'; +import addonA11y from '@storybook/addon-a11y'; +import addonDocs from '@storybook/addon-docs'; +import addonThemes from '@storybook/addon-themes'; +import addonLinks from '@storybook/addon-links'; +import { definePreview } from '@storybook/react-vite'; +import { useEffect } from 'react'; import { TestApiProvider } from '@backstage/test-utils'; import { Content, AlertDisplay } from '@backstage/core-components'; import { apis } from './support/apis'; -import type { Decorator, Preview } from '@storybook/react-vite'; import { useGlobals } from 'storybook/preview-api'; import { UnifiedThemeProvider, themes } from '@backstage/theme'; import { allModes } from './modes'; @@ -16,7 +20,7 @@ import './storybook.css'; // Custom themes import './themes/spotify.css'; -const preview: Preview = { +export default definePreview({ globalTypes: { themeMode: { name: 'Theme Mode', @@ -47,10 +51,12 @@ const preview: Preview = { }, }, }, + initialGlobals: { themeMode: 'light', themeName: 'backstage', }, + parameters: { layout: 'fullscreen', @@ -72,7 +78,7 @@ const preview: Preview = { }, viewport: { - viewports: { + options: { initial: { name: 'Initial', styles: { width: '320px', height: '100%' }, @@ -102,6 +108,7 @@ const preview: Preview = { }, }, }, + decorators: [ Story => { const [globals] = useGlobals(); @@ -121,10 +128,11 @@ const preview: Preview = { }; }, [selectedTheme, selectedThemeName]); - document.body.style.backgroundColor = 'var(--bui-bg)'; + document.body.style.backgroundColor = 'var(--bui-bg-surface-0)'; const docsStoryElements = document.getElementsByClassName('docs-story'); Array.from(docsStoryElements).forEach(element => { - (element as HTMLElement).style.backgroundColor = 'var(--bui-bg)'; + (element as HTMLElement).style.backgroundColor = + 'var(--bui-bg-surface-0)'; }); return ( @@ -140,6 +148,6 @@ const preview: Preview = { ); }, ], -}; -export default preview; + addons: [addonLinks(), addonThemes(), addonDocs(), addonA11y()], +}); diff --git a/.storybook/themes/spotify.css b/.storybook/themes/spotify.css index bcb1ded9ff..db3a0ca16c 100644 --- a/.storybook/themes/spotify.css +++ b/.storybook/themes/spotify.css @@ -216,9 +216,6 @@ } [data-theme-mode='light'][data-theme-name='spotify'] { - --bui-bg: var(--bui-gray-1); - --bui-bg-surface-1: var(--bui-white); - --bui-bg-surface-2: var(--bui-gray-2); --bui-bg-solid: #1ed760; --bui-bg-solid-hover: #3be477; --bui-bg-solid-pressed: #1abc54; @@ -248,9 +245,7 @@ } [data-theme-mode='dark'][data-theme-name='spotify'] { - --bui-bg: var(--bui-black); - --bui-bg-surface-1: var(--bui-gray-1); - --bui-bg-surface-2: var(--bui-gray-2); + --bui-bg-surface-0: var(--bui-black); --bui-bg-solid: #1ed760; --bui-bg-solid-hover: #3be477; --bui-bg-solid-pressed: #1abc54; diff --git a/OWNERS.md b/OWNERS.md index 44b4ebca15..764237d9c1 100644 --- a/OWNERS.md +++ b/OWNERS.md @@ -5,11 +5,13 @@ Team: @backstage/maintainers -| Maintainer | Organization | GitHub | Discord | -| --------------- | ------------ | ----------------------------------------------- | ------------- | -| Patrik Oldsberg | Spotify | [Rugvip](https://github.com/Rugvip) | `Rugvip#0019` | -| Fredrik Adelöw | Spotify | [freben](https://github.com/freben) | `freben#3926` | -| Ben Lambert | Spotify | [benjdlambert](https://github.com/benjdlambert) | `blam#2159` | +| Maintainer | Organization | GitHub | Discord | +| --------------- | ------------ | ----------------------------------------------------- | ------------- | +| André Wanlin | Spotify | [awanlin](https://github.com/awanlin) | `ahhhndre` | +| Aramis Sennyey | DoorDash | [aramissennyeydd](https://github.com/aramissennyeydd) | `Aramis#7984` | +| Ben Lambert | Spotify | [benjdlambert](https://github.com/benjdlambert) | `blam#2159` | +| Fredrik Adelöw | Spotify | [freben](https://github.com/freben) | `freben#3926` | +| Patrik Oldsberg | Spotify | [Rugvip](https://github.com/Rugvip) | `Rugvip#0019` | ## Project Areas @@ -78,7 +80,7 @@ Scope: The Backstage Documentation and Microsite, excluding the plugins listing | Name | Organization | GitHub | Discord | | --------------- | ------------- | ----------------------------------------------------- | ------------- | -| Andre Wanlin | Spotify | [awanlin](https://github.com/awanlin) | `ahhhndre` | +| André Wanlin | Spotify | [awanlin](https://github.com/awanlin) | `ahhhndre` | | Aramis Sennyey | DoorDash | [aramissennyeydd](https://github.com/aramissennyeydd) | `Aramis#7984` | | Peter Macdonald | VodafoneZiggo | [Parsifal-M](https://github.com/Parsifal-M) | `parsifal` | @@ -267,6 +269,7 @@ Scope: The Scaffolder frontend and backend plugins, and related tooling. | Niklas Gustavsson | Spotify | [protocol7](https://github.com/protocol7) | | | Dave Zolotusky | Spotify | [dzolotusky](https://github.com/dzolotusky) | | | Pia Nilsson | Spotify | [pianilsson](https://github.com/pianilsson) | | +| Stefan Särne | Spotify | [ssarne](https://github.com/ssarne) | | ## Organization Members @@ -274,9 +277,7 @@ Scope: The Scaffolder frontend and backend plugins, and related tooling. | ------------------------------ | ------------------------- | ----------------------------------------------------- | ------------------------------ | | Adam Harvey | Okta | [adamdmharvey](https://github.com/adamdmharvey) | `adamharvey_` | | Alex Crome | | [afscrome](https://github.com/afscrome) | `afscrome` | -| Andre Wanlin | Spotify | [awanlin](https://github.com/awanlin) | `ahhhndre` | | Andrew Thauer | Wealthsimple | [andrewthauer](https://github.com/andrewthauer) | `andrewthauer#3060` | -| Aramis Sennyey | DoorDash | [aramissennyeydd](https://github.com/aramissennyeydd) | `Aramis#7984` | | Brian Fletcher | Roadie.io | [punkle](https://github.com/punkle) | `Brian Fletcher#7051` | | Carlos Esteban Lopez Jaramillo | VMWare | [luchillo17](https://github.com/luchillo17) | `luchillo17#8777` | | David Tuite | Roadie.io | [dtuite](https://github.com/dtuite) | `David Tuite (roadie.io)#1010` | diff --git a/app-config.yaml b/app-config.yaml index c1a894dcc7..54ece44da3 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -109,8 +109,12 @@ integrations: token: ${GITLAB_TOKEN} ### Example for how to add a bitbucket cloud integration # bitbucketCloud: + # # Using API token # - username: ${BITBUCKET_USERNAME} # token: ${BITBUCKET_API_TOKEN} + # # Using OAuth + # - clientId: ${BITBUCKET_CLIENT_ID} + # clientSecret: ${BITBUCKET_CLIENT_SECRET} ### Example for how to add your bitbucket server instance using the API: # - host: server.bitbucket.com # apiBaseUrl: server.bitbucket.com @@ -311,3 +315,8 @@ auth: permission: enabled: true + +devTools: + scheduledTasks: + plugins: + - catalog diff --git a/docs-ui/package.json b/docs-ui/package.json index ff5d59e7f0..2f17987107 100644 --- a/docs-ui/package.json +++ b/docs-ui/package.json @@ -32,13 +32,13 @@ "clsx": "^2.1.1", "html-react-parser": "^5.2.5", "motion": "^12.4.1", - "next": "15.5.7", + "next": "15.5.9", "next-mdx-remote-client": "^2.1.2", "prop-types": "^15.8.1", "react": "19.1.1", "react-dom": "19.1.1", "shiki": "^3.13.0", - "storybook": "^8.6.12" + "storybook": "^8.6.15" }, "devDependencies": { "@octokit/rest": "^22.0.1", diff --git a/docs-ui/public/theme-backstage.css b/docs-ui/public/theme-backstage.css index 59a5b986be..9b59448c11 100644 --- a/docs-ui/public/theme-backstage.css +++ b/docs-ui/public/theme-backstage.css @@ -1 +1 @@ -@layer tokens{:root{--bui-font-regular:system-ui;--bui-font-monospace:ui-monospace,"Menlo","Monaco","Consolas","Liberation Mono","Courier New",monospace;--bui-font-weight-regular:400;--bui-font-weight-bold:600;--bui-font-size-1:.625rem;--bui-font-size-2:.75rem;--bui-font-size-3:.875rem;--bui-font-size-4:1rem;--bui-font-size-5:1.25rem;--bui-font-size-6:1.5rem;--bui-font-size-7:2rem;--bui-font-size-8:3rem;--bui-font-size-9:4rem;--bui-font-size-10:5.75rem;--bui-space:.25rem;--bui-space-0_5:calc(var(--bui-space)*.5);--bui-space-1:var(--bui-space);--bui-space-1_5:calc(var(--bui-space)*1.5);--bui-space-2:calc(var(--bui-space)*2);--bui-space-3:calc(var(--bui-space)*3);--bui-space-4:calc(var(--bui-space)*4);--bui-space-5:calc(var(--bui-space)*5);--bui-space-6:calc(var(--bui-space)*6);--bui-space-7:calc(var(--bui-space)*7);--bui-space-8:calc(var(--bui-space)*8);--bui-space-9:calc(var(--bui-space)*9);--bui-space-10:calc(var(--bui-space)*10);--bui-space-11:calc(var(--bui-space)*11);--bui-space-12:calc(var(--bui-space)*12);--bui-space-13:calc(var(--bui-space)*13);--bui-space-14:calc(var(--bui-space)*14);--bui-radius-1:calc(.125rem);--bui-radius-2:calc(.25rem);--bui-radius-3:calc(.5rem);--bui-radius-4:calc(.75rem);--bui-radius-5:calc(1rem);--bui-radius-6:calc(1.25rem);--bui-radius-full:9999px;--bui-black:#000;--bui-white:#fff;--bui-gray-1:#f8f8f8;--bui-gray-2:#ececec;--bui-gray-3:#d9d9d9;--bui-gray-4:#c1c1c1;--bui-gray-5:#9e9e9e;--bui-gray-6:#8c8c8c;--bui-gray-7:#757575;--bui-gray-8:#595959;--bui-bg:var(--bui-gray-1);--bui-bg-surface-1:var(--bui-white);--bui-bg-surface-2:var(--bui-gray-2);--bui-bg-solid:#1f5493;--bui-bg-solid-hover:#163a66;--bui-bg-solid-pressed:#0f2b4e;--bui-bg-solid-disabled:#ebebeb;--bui-bg-tint:transparent;--bui-bg-tint-hover:#1f549366;--bui-bg-tint-pressed:#1f549399;--bui-bg-tint-disabled:#ebebeb;--bui-bg-danger:#feebe7;--bui-bg-warning:#fff2b2;--bui-bg-success:#e6f6eb;--bui-fg-primary:var(--bui-black);--bui-fg-secondary:var(--bui-gray-7);--bui-fg-link:#1f5493;--bui-fg-link-hover:#1f2d5c;--bui-fg-disabled:#9e9e9e;--bui-fg-solid:var(--bui-white);--bui-fg-solid-disabled:#9c9c9c;--bui-fg-tint:#1f5493;--bui-fg-tint-disabled:var(--bui-gray-5);--bui-fg-danger:#e22b2b;--bui-fg-warning:#e36d05;--bui-fg-success:#1db954;--bui-border:#0000001a;--bui-border-hover:#0003;--bui-border-pressed:#0006;--bui-border-disabled:#0000001a;--bui-border-danger:#f87a7a;--bui-border-warning:#e36d05;--bui-border-success:#53db83;--bui-ring:#1f5493;--bui-scrollbar:#a0a0a03b;--bui-scrollbar-thumb:#a0a0a0;--bui-animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite}[data-theme-mode=dark]{--bui-gray-1:#191919;--bui-gray-2:#242424;--bui-gray-3:#373737;--bui-gray-4:#464646;--bui-gray-5:#575757;--bui-gray-6:#7b7b7b;--bui-gray-7:#9e9e9e;--bui-gray-8:#b4b4b4;--bui-bg:#333;--bui-bg-surface-1:#424242;--bui-bg-surface-2:var(--bui-gray-2);--bui-bg-solid:#9cc9ff;--bui-bg-solid-hover:#83b9fd;--bui-bg-solid-pressed:#83b9fd;--bui-bg-solid-disabled:#222;--bui-bg-tint:transparent;--bui-bg-tint-hover:#9cc9ff1f;--bui-bg-tint-pressed:#9cc9ff29;--bui-bg-tint-disabled:transparent;--bui-bg-danger:#3b1219;--bui-bg-warning:#302008;--bui-bg-success:#132d21;--bui-fg-primary:var(--bui-white);--bui-fg-secondary:var(--bui-gray-7);--bui-fg-link:#9cc9ff;--bui-fg-link-hover:#7eb5f7;--bui-fg-disabled:var(--bui-gray-7);--bui-fg-solid:#101821;--bui-fg-solid-disabled:var(--bui-gray-5);--bui-fg-tint:#9cc9ff;--bui-fg-tint-disabled:var(--bui-gray-5);--bui-fg-danger:#e22b2b;--bui-fg-warning:#e36d05;--bui-fg-success:#1db954;--bui-border:#ffffff1f;--bui-border-hover:#fff6;--bui-border-pressed:#ffffff80;--bui-border-disabled:#fff3;--bui-border-danger:#f87a7a;--bui-border-warning:#e36d05;--bui-border-success:#53db83;--bui-ring:#1f5493;--bui-scrollbar:#3636363a;--bui-scrollbar-thumb:#575757}}@layer base{*,:before,:after{box-sizing:border-box}html{-webkit-text-size-adjust:100%;tab-size:4;font-family:system-ui,Segoe UI,Roboto,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji;line-height:1.15}body{margin:0}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{border-color:currentColor}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:100%;line-height:1.15}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}legend{padding:0}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}:where(a){color:inherit;text-decoration:none}@keyframes pulse{50%{opacity:.5}}body{background-color:var(--bui-bg);color:var(--bui-fg-primary);font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);font-size:var(--bui-font-size-3);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}}@layer components;@layer utilities{.bui-p{padding:var(--p)}.bui-p-0\.5{padding:var(--bui-space-0_5)}.bui-p-1{padding:var(--bui-space-1)}.bui-p-1\.5{padding:var(--bui-space-1_5)}.bui-p-2{padding:var(--bui-space-2)}.bui-p-3{padding:var(--bui-space-3)}.bui-p-4{padding:var(--bui-space-4)}.bui-p-5{padding:var(--bui-space-5)}.bui-p-6{padding:var(--bui-space-6)}.bui-p-7{padding:var(--bui-space-7)}.bui-p-8{padding:var(--bui-space-8)}.bui-p-9{padding:var(--bui-space-9)}.bui-p-10{padding:var(--bui-space-10)}.bui-p-11{padding:var(--bui-space-11)}.bui-p-12{padding:var(--bui-space-12)}.bui-p-13{padding:var(--bui-space-13)}.bui-p-14{padding:var(--bui-space-14)}@media (width>=640px){.xs\:bui-p{padding:var(--p-xs)}.xs\:bui-p-0\.5{padding:var(--bui-space-0_5)}.xs\:bui-p-1{padding:var(--bui-space-1)}.xs\:bui-p-1\.5{padding:var(--bui-space-1_5)}.xs\:bui-p-2{padding:var(--bui-space-2)}.xs\:bui-p-3{padding:var(--bui-space-3)}.xs\:bui-p-4{padding:var(--bui-space-4)}.xs\:bui-p-5{padding:var(--bui-space-5)}.xs\:bui-p-6{padding:var(--bui-space-6)}.xs\:bui-p-7{padding:var(--bui-space-7)}.xs\:bui-p-8{padding:var(--bui-space-8)}.xs\:bui-p-9{padding:var(--bui-space-9)}.xs\:bui-p-10{padding:var(--bui-space-10)}.xs\:bui-p-11{padding:var(--bui-space-11)}.xs\:bui-p-12{padding:var(--bui-space-12)}.xs\:bui-p-13{padding:var(--bui-space-13)}.xs\:bui-p-14{padding:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-p{padding:var(--p-sm)}.sm\:bui-p-0\.5{padding:var(--bui-space-0_5)}.sm\:bui-p-1{padding:var(--bui-space-1)}.sm\:bui-p-1\.5{padding:var(--bui-space-1_5)}.sm\:bui-p-2{padding:var(--bui-space-2)}.sm\:bui-p-3{padding:var(--bui-space-3)}.sm\:bui-p-4{padding:var(--bui-space-4)}.sm\:bui-p-5{padding:var(--bui-space-5)}.sm\:bui-p-6{padding:var(--bui-space-6)}.sm\:bui-p-7{padding:var(--bui-space-7)}.sm\:bui-p-8{padding:var(--bui-space-8)}.sm\:bui-p-9{padding:var(--bui-space-9)}.sm\:bui-p-10{padding:var(--bui-space-10)}.sm\:bui-p-11{padding:var(--bui-space-11)}.sm\:bui-p-12{padding:var(--bui-space-12)}.sm\:bui-p-13{padding:var(--bui-space-13)}.sm\:bui-p-14{padding:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-p{padding:var(--p-md)}.md\:bui-p-0\.5{padding:var(--bui-space-0_5)}.md\:bui-p-1{padding:var(--bui-space-1)}.md\:bui-p-1\.5{padding:var(--bui-space-1_5)}.md\:bui-p-2{padding:var(--bui-space-2)}.md\:bui-p-3{padding:var(--bui-space-3)}.md\:bui-p-4{padding:var(--bui-space-4)}.md\:bui-p-5{padding:var(--bui-space-5)}.md\:bui-p-6{padding:var(--bui-space-6)}.md\:bui-p-7{padding:var(--bui-space-7)}.md\:bui-p-8{padding:var(--bui-space-8)}.md\:bui-p-9{padding:var(--bui-space-9)}.md\:bui-p-10{padding:var(--bui-space-10)}.md\:bui-p-11{padding:var(--bui-space-11)}.md\:bui-p-12{padding:var(--bui-space-12)}.md\:bui-p-13{padding:var(--bui-space-13)}.md\:bui-p-14{padding:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-p{padding:var(--p-lg)}.lg\:bui-p-0\.5{padding:var(--bui-space-0_5)}.lg\:bui-p-1{padding:var(--bui-space-1)}.lg\:bui-p-1\.5{padding:var(--bui-space-1_5)}.lg\:bui-p-2{padding:var(--bui-space-2)}.lg\:bui-p-3{padding:var(--bui-space-3)}.lg\:bui-p-4{padding:var(--bui-space-4)}.lg\:bui-p-5{padding:var(--bui-space-5)}.lg\:bui-p-6{padding:var(--bui-space-6)}.lg\:bui-p-7{padding:var(--bui-space-7)}.lg\:bui-p-8{padding:var(--bui-space-8)}.lg\:bui-p-9{padding:var(--bui-space-9)}.lg\:bui-p-10{padding:var(--bui-space-10)}.lg\:bui-p-11{padding:var(--bui-space-11)}.lg\:bui-p-12{padding:var(--bui-space-12)}.lg\:bui-p-13{padding:var(--bui-space-13)}.lg\:bui-p-14{padding:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-p{padding:var(--p-xl)}.xl\:bui-p-0\.5{padding:var(--bui-space-0_5)}.xl\:bui-p-1{padding:var(--bui-space-1)}.xl\:bui-p-1\.5{padding:var(--bui-space-1_5)}.xl\:bui-p-2{padding:var(--bui-space-2)}.xl\:bui-p-3{padding:var(--bui-space-3)}.xl\:bui-p-4{padding:var(--bui-space-4)}.xl\:bui-p-5{padding:var(--bui-space-5)}.xl\:bui-p-6{padding:var(--bui-space-6)}.xl\:bui-p-7{padding:var(--bui-space-7)}.xl\:bui-p-8{padding:var(--bui-space-8)}.xl\:bui-p-9{padding:var(--bui-space-9)}.xl\:bui-p-10{padding:var(--bui-space-10)}.xl\:bui-p-11{padding:var(--bui-space-11)}.xl\:bui-p-12{padding:var(--bui-space-12)}.xl\:bui-p-13{padding:var(--bui-space-13)}.xl\:bui-p-14{padding:var(--bui-space-14)}}.bui-pl{padding-left:var(--pl)}.bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.bui-pl-1{padding-left:var(--bui-space-1)}.bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.bui-pl-2{padding-left:var(--bui-space-2)}.bui-pl-3{padding-left:var(--bui-space-3)}.bui-pl-4{padding-left:var(--bui-space-4)}.bui-pl-5{padding-left:var(--bui-space-5)}.bui-pl-6{padding-left:var(--bui-space-6)}.bui-pl-7{padding-left:var(--bui-space-7)}.bui-pl-8{padding-left:var(--bui-space-8)}.bui-pl-9{padding-left:var(--bui-space-9)}.bui-pl-10{padding-left:var(--bui-space-10)}.bui-pl-11{padding-left:var(--bui-space-11)}.bui-pl-12{padding-left:var(--bui-space-12)}.bui-pl-13{padding-left:var(--bui-space-13)}.bui-pl-14{padding-left:var(--bui-space-14)}@media (width>=640px){.xs\:bui-pl{padding-left:var(--pl-xs)}.xs\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.xs\:bui-pl-1{padding-left:var(--bui-space-1)}.xs\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.xs\:bui-pl-2{padding-left:var(--bui-space-2)}.xs\:bui-pl-3{padding-left:var(--bui-space-3)}.xs\:bui-pl-4{padding-left:var(--bui-space-4)}.xs\:bui-pl-5{padding-left:var(--bui-space-5)}.xs\:bui-pl-6{padding-left:var(--bui-space-6)}.xs\:bui-pl-7{padding-left:var(--bui-space-7)}.xs\:bui-pl-8{padding-left:var(--bui-space-8)}.xs\:bui-pl-9{padding-left:var(--bui-space-9)}.xs\:bui-pl-10{padding-left:var(--bui-space-10)}.xs\:bui-pl-11{padding-left:var(--bui-space-11)}.xs\:bui-pl-12{padding-left:var(--bui-space-12)}.xs\:bui-pl-13{padding-left:var(--bui-space-13)}.xs\:bui-pl-14{padding-left:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-pl{padding-left:var(--pl-sm)}.sm\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.sm\:bui-pl-1{padding-left:var(--bui-space-1)}.sm\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.sm\:bui-pl-2{padding-left:var(--bui-space-2)}.sm\:bui-pl-3{padding-left:var(--bui-space-3)}.sm\:bui-pl-4{padding-left:var(--bui-space-4)}.sm\:bui-pl-5{padding-left:var(--bui-space-5)}.sm\:bui-pl-6{padding-left:var(--bui-space-6)}.sm\:bui-pl-7{padding-left:var(--bui-space-7)}.sm\:bui-pl-8{padding-left:var(--bui-space-8)}.sm\:bui-pl-9{padding-left:var(--bui-space-9)}.sm\:bui-pl-10{padding-left:var(--bui-space-10)}.sm\:bui-pl-11{padding-left:var(--bui-space-11)}.sm\:bui-pl-12{padding-left:var(--bui-space-12)}.sm\:bui-pl-13{padding-left:var(--bui-space-13)}.sm\:bui-pl-14{padding-left:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-pl{padding-left:var(--pl-md)}.md\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.md\:bui-pl-1{padding-left:var(--bui-space-1)}.md\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.md\:bui-pl-2{padding-left:var(--bui-space-2)}.md\:bui-pl-3{padding-left:var(--bui-space-3)}.md\:bui-pl-4{padding-left:var(--bui-space-4)}.md\:bui-pl-5{padding-left:var(--bui-space-5)}.md\:bui-pl-6{padding-left:var(--bui-space-6)}.md\:bui-pl-7{padding-left:var(--bui-space-7)}.md\:bui-pl-8{padding-left:var(--bui-space-8)}.md\:bui-pl-9{padding-left:var(--bui-space-9)}.md\:bui-pl-10{padding-left:var(--bui-space-10)}.md\:bui-pl-11{padding-left:var(--bui-space-11)}.md\:bui-pl-12{padding-left:var(--bui-space-12)}.md\:bui-pl-13{padding-left:var(--bui-space-13)}.md\:bui-pl-14{padding-left:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-pl{padding-left:var(--pl-lg)}.lg\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.lg\:bui-pl-1{padding-left:var(--bui-space-1)}.lg\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.lg\:bui-pl-2{padding-left:var(--bui-space-2)}.lg\:bui-pl-3{padding-left:var(--bui-space-3)}.lg\:bui-pl-4{padding-left:var(--bui-space-4)}.lg\:bui-pl-5{padding-left:var(--bui-space-5)}.lg\:bui-pl-6{padding-left:var(--bui-space-6)}.lg\:bui-pl-7{padding-left:var(--bui-space-7)}.lg\:bui-pl-8{padding-left:var(--bui-space-8)}.lg\:bui-pl-9{padding-left:var(--bui-space-9)}.lg\:bui-pl-10{padding-left:var(--bui-space-10)}.lg\:bui-pl-11{padding-left:var(--bui-space-11)}.lg\:bui-pl-12{padding-left:var(--bui-space-12)}.lg\:bui-pl-13{padding-left:var(--bui-space-13)}.lg\:bui-pl-14{padding-left:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-pl{padding-left:var(--pl-xl)}.xl\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.xl\:bui-pl-1{padding-left:var(--bui-space-1)}.xl\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.xl\:bui-pl-2{padding-left:var(--bui-space-2)}.xl\:bui-pl-3{padding-left:var(--bui-space-3)}.xl\:bui-pl-4{padding-left:var(--bui-space-4)}.xl\:bui-pl-5{padding-left:var(--bui-space-5)}.xl\:bui-pl-6{padding-left:var(--bui-space-6)}.xl\:bui-pl-7{padding-left:var(--bui-space-7)}.xl\:bui-pl-8{padding-left:var(--bui-space-8)}.xl\:bui-pl-9{padding-left:var(--bui-space-9)}.xl\:bui-pl-10{padding-left:var(--bui-space-10)}.xl\:bui-pl-11{padding-left:var(--bui-space-11)}.xl\:bui-pl-12{padding-left:var(--bui-space-12)}.xl\:bui-pl-13{padding-left:var(--bui-space-13)}.xl\:bui-pl-14{padding-left:var(--bui-space-14)}}.bui-pr{padding-right:var(--pr)}.bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.bui-pr-1{padding-right:var(--bui-space-1)}.bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.bui-pr-2{padding-right:var(--bui-space-2)}.bui-pr-3{padding-right:var(--bui-space-3)}.bui-pr-4{padding-right:var(--bui-space-4)}.bui-pr-5{padding-right:var(--bui-space-5)}.bui-pr-6{padding-right:var(--bui-space-6)}.bui-pr-7{padding-right:var(--bui-space-7)}.bui-pr-8{padding-right:var(--bui-space-8)}.bui-pr-9{padding-right:var(--bui-space-9)}.bui-pr-10{padding-right:var(--bui-space-10)}.bui-pr-11{padding-right:var(--bui-space-11)}.bui-pr-12{padding-right:var(--bui-space-12)}.bui-pr-13{padding-right:var(--bui-space-13)}.bui-pr-14{padding-right:var(--bui-space-14)}@media (width>=640px){.xs\:bui-pr{padding-right:var(--pr-xs)}.xs\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.xs\:bui-pr-1{padding-right:var(--bui-space-1)}.xs\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.xs\:bui-pr-2{padding-right:var(--bui-space-2)}.xs\:bui-pr-3{padding-right:var(--bui-space-3)}.xs\:bui-pr-4{padding-right:var(--bui-space-4)}.xs\:bui-pr-5{padding-right:var(--bui-space-5)}.xs\:bui-pr-6{padding-right:var(--bui-space-6)}.xs\:bui-pr-7{padding-right:var(--bui-space-7)}.xs\:bui-pr-8{padding-right:var(--bui-space-8)}.xs\:bui-pr-9{padding-right:var(--bui-space-9)}.xs\:bui-pr-10{padding-right:var(--bui-space-10)}.xs\:bui-pr-11{padding-right:var(--bui-space-11)}.xs\:bui-pr-12{padding-right:var(--bui-space-12)}.xs\:bui-pr-13{padding-right:var(--bui-space-13)}.xs\:bui-pr-14{padding-right:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-pr{padding-right:var(--pr-sm)}.sm\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.sm\:bui-pr-1{padding-right:var(--bui-space-1)}.sm\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.sm\:bui-pr-2{padding-right:var(--bui-space-2)}.sm\:bui-pr-3{padding-right:var(--bui-space-3)}.sm\:bui-pr-4{padding-right:var(--bui-space-4)}.sm\:bui-pr-5{padding-right:var(--bui-space-5)}.sm\:bui-pr-6{padding-right:var(--bui-space-6)}.sm\:bui-pr-7{padding-right:var(--bui-space-7)}.sm\:bui-pr-8{padding-right:var(--bui-space-8)}.sm\:bui-pr-9{padding-right:var(--bui-space-9)}.sm\:bui-pr-10{padding-right:var(--bui-space-10)}.sm\:bui-pr-11{padding-right:var(--bui-space-11)}.sm\:bui-pr-12{padding-right:var(--bui-space-12)}.sm\:bui-pr-13{padding-right:var(--bui-space-13)}.sm\:bui-pr-14{padding-right:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-pr{padding-right:var(--pr-md)}.md\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.md\:bui-pr-1{padding-right:var(--bui-space-1)}.md\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.md\:bui-pr-2{padding-right:var(--bui-space-2)}.md\:bui-pr-3{padding-right:var(--bui-space-3)}.md\:bui-pr-4{padding-right:var(--bui-space-4)}.md\:bui-pr-5{padding-right:var(--bui-space-5)}.md\:bui-pr-6{padding-right:var(--bui-space-6)}.md\:bui-pr-7{padding-right:var(--bui-space-7)}.md\:bui-pr-8{padding-right:var(--bui-space-8)}.md\:bui-pr-9{padding-right:var(--bui-space-9)}.md\:bui-pr-10{padding-right:var(--bui-space-10)}.md\:bui-pr-11{padding-right:var(--bui-space-11)}.md\:bui-pr-12{padding-right:var(--bui-space-12)}.md\:bui-pr-13{padding-right:var(--bui-space-13)}.md\:bui-pr-14{padding-right:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-pr{padding-right:var(--pr-lg)}.lg\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.lg\:bui-pr-1{padding-right:var(--bui-space-1)}.lg\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.lg\:bui-pr-2{padding-right:var(--bui-space-2)}.lg\:bui-pr-3{padding-right:var(--bui-space-3)}.lg\:bui-pr-4{padding-right:var(--bui-space-4)}.lg\:bui-pr-5{padding-right:var(--bui-space-5)}.lg\:bui-pr-6{padding-right:var(--bui-space-6)}.lg\:bui-pr-7{padding-right:var(--bui-space-7)}.lg\:bui-pr-8{padding-right:var(--bui-space-8)}.lg\:bui-pr-9{padding-right:var(--bui-space-9)}.lg\:bui-pr-10{padding-right:var(--bui-space-10)}.lg\:bui-pr-11{padding-right:var(--bui-space-11)}.lg\:bui-pr-12{padding-right:var(--bui-space-12)}.lg\:bui-pr-13{padding-right:var(--bui-space-13)}.lg\:bui-pr-14{padding-right:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-pr{padding-right:var(--pr-xl)}.xl\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.xl\:bui-pr-1{padding-right:var(--bui-space-1)}.xl\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.xl\:bui-pr-2{padding-right:var(--bui-space-2)}.xl\:bui-pr-3{padding-right:var(--bui-space-3)}.xl\:bui-pr-4{padding-right:var(--bui-space-4)}.xl\:bui-pr-5{padding-right:var(--bui-space-5)}.xl\:bui-pr-6{padding-right:var(--bui-space-6)}.xl\:bui-pr-7{padding-right:var(--bui-space-7)}.xl\:bui-pr-8{padding-right:var(--bui-space-8)}.xl\:bui-pr-9{padding-right:var(--bui-space-9)}.xl\:bui-pr-10{padding-right:var(--bui-space-10)}.xl\:bui-pr-11{padding-right:var(--bui-space-11)}.xl\:bui-pr-12{padding-right:var(--bui-space-12)}.xl\:bui-pr-13{padding-right:var(--bui-space-13)}.xl\:bui-pr-14{padding-right:var(--bui-space-14)}}.bui-pt{padding-top:var(--pt)}.bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.bui-pt-1{padding-top:var(--bui-space-1)}.bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.bui-pt-2{padding-top:var(--bui-space-2)}.bui-pt-3{padding-top:var(--bui-space-3)}.bui-pt-4{padding-top:var(--bui-space-4)}.bui-pt-5{padding-top:var(--bui-space-5)}.bui-pt-6{padding-top:var(--bui-space-6)}.bui-pt-7{padding-top:var(--bui-space-7)}.bui-pt-8{padding-top:var(--bui-space-8)}.bui-pt-9{padding-top:var(--bui-space-9)}.bui-pt-10{padding-top:var(--bui-space-10)}.bui-pt-11{padding-top:var(--bui-space-11)}.bui-pt-12{padding-top:var(--bui-space-12)}.bui-pt-13{padding-top:var(--bui-space-13)}.bui-pt-14{padding-top:var(--bui-space-14)}@media (width>=640px){.xs\:bui-pt{padding-top:var(--pt-xs)}.xs\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.xs\:bui-pt-1{padding-top:var(--bui-space-1)}.xs\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.xs\:bui-pt-2{padding-top:var(--bui-space-2)}.xs\:bui-pt-3{padding-top:var(--bui-space-3)}.xs\:bui-pt-4{padding-top:var(--bui-space-4)}.xs\:bui-pt-5{padding-top:var(--bui-space-5)}.xs\:bui-pt-6{padding-top:var(--bui-space-6)}.xs\:bui-pt-7{padding-top:var(--bui-space-7)}.xs\:bui-pt-8{padding-top:var(--bui-space-8)}.xs\:bui-pt-9{padding-top:var(--bui-space-9)}.xs\:bui-pt-10{padding-top:var(--bui-space-10)}.xs\:bui-pt-11{padding-top:var(--bui-space-11)}.xs\:bui-pt-12{padding-top:var(--bui-space-12)}.xs\:bui-pt-13{padding-top:var(--bui-space-13)}.xs\:bui-pt-14{padding-top:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-pt{padding-top:var(--pt-sm)}.sm\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.sm\:bui-pt-1{padding-top:var(--bui-space-1)}.sm\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.sm\:bui-pt-2{padding-top:var(--bui-space-2)}.sm\:bui-pt-3{padding-top:var(--bui-space-3)}.sm\:bui-pt-4{padding-top:var(--bui-space-4)}.sm\:bui-pt-5{padding-top:var(--bui-space-5)}.sm\:bui-pt-6{padding-top:var(--bui-space-6)}.sm\:bui-pt-7{padding-top:var(--bui-space-7)}.sm\:bui-pt-8{padding-top:var(--bui-space-8)}.sm\:bui-pt-9{padding-top:var(--bui-space-9)}.sm\:bui-pt-10{padding-top:var(--bui-space-10)}.sm\:bui-pt-11{padding-top:var(--bui-space-11)}.sm\:bui-pt-12{padding-top:var(--bui-space-12)}.sm\:bui-pt-13{padding-top:var(--bui-space-13)}.sm\:bui-pt-14{padding-top:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-pt{padding-top:var(--pt-md)}.md\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.md\:bui-pt-1{padding-top:var(--bui-space-1)}.md\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.md\:bui-pt-2{padding-top:var(--bui-space-2)}.md\:bui-pt-3{padding-top:var(--bui-space-3)}.md\:bui-pt-4{padding-top:var(--bui-space-4)}.md\:bui-pt-5{padding-top:var(--bui-space-5)}.md\:bui-pt-6{padding-top:var(--bui-space-6)}.md\:bui-pt-7{padding-top:var(--bui-space-7)}.md\:bui-pt-8{padding-top:var(--bui-space-8)}.md\:bui-pt-9{padding-top:var(--bui-space-9)}.md\:bui-pt-10{padding-top:var(--bui-space-10)}.md\:bui-pt-11{padding-top:var(--bui-space-11)}.md\:bui-pt-12{padding-top:var(--bui-space-12)}.md\:bui-pt-13{padding-top:var(--bui-space-13)}.md\:bui-pt-14{padding-top:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-pt{padding-top:var(--pt-lg)}.lg\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.lg\:bui-pt-1{padding-top:var(--bui-space-1)}.lg\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.lg\:bui-pt-2{padding-top:var(--bui-space-2)}.lg\:bui-pt-3{padding-top:var(--bui-space-3)}.lg\:bui-pt-4{padding-top:var(--bui-space-4)}.lg\:bui-pt-5{padding-top:var(--bui-space-5)}.lg\:bui-pt-6{padding-top:var(--bui-space-6)}.lg\:bui-pt-7{padding-top:var(--bui-space-7)}.lg\:bui-pt-8{padding-top:var(--bui-space-8)}.lg\:bui-pt-9{padding-top:var(--bui-space-9)}.lg\:bui-pt-10{padding-top:var(--bui-space-10)}.lg\:bui-pt-11{padding-top:var(--bui-space-11)}.lg\:bui-pt-12{padding-top:var(--bui-space-12)}.lg\:bui-pt-13{padding-top:var(--bui-space-13)}.lg\:bui-pt-14{padding-top:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-pt{padding-top:var(--pt-xl)}.xl\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.xl\:bui-pt-1{padding-top:var(--bui-space-1)}.xl\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.xl\:bui-pt-2{padding-top:var(--bui-space-2)}.xl\:bui-pt-3{padding-top:var(--bui-space-3)}.xl\:bui-pt-4{padding-top:var(--bui-space-4)}.xl\:bui-pt-5{padding-top:var(--bui-space-5)}.xl\:bui-pt-6{padding-top:var(--bui-space-6)}.xl\:bui-pt-7{padding-top:var(--bui-space-7)}.xl\:bui-pt-8{padding-top:var(--bui-space-8)}.xl\:bui-pt-9{padding-top:var(--bui-space-9)}.xl\:bui-pt-10{padding-top:var(--bui-space-10)}.xl\:bui-pt-11{padding-top:var(--bui-space-11)}.xl\:bui-pt-12{padding-top:var(--bui-space-12)}.xl\:bui-pt-13{padding-top:var(--bui-space-13)}.xl\:bui-pt-14{padding-top:var(--bui-space-14)}}.bui-pb{padding-bottom:var(--pb)}.bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.bui-pb-1{padding-bottom:var(--bui-space-1)}.bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.bui-pb-2{padding-bottom:var(--bui-space-2)}.bui-pb-3{padding-bottom:var(--bui-space-3)}.bui-pb-4{padding-bottom:var(--bui-space-4)}.bui-pb-5{padding-bottom:var(--bui-space-5)}.bui-pb-6{padding-bottom:var(--bui-space-6)}.bui-pb-7{padding-bottom:var(--bui-space-7)}.bui-pb-8{padding-bottom:var(--bui-space-8)}.bui-pb-9{padding-bottom:var(--bui-space-9)}.bui-pb-10{padding-bottom:var(--bui-space-10)}.bui-pb-11{padding-bottom:var(--bui-space-11)}.bui-pb-12{padding-bottom:var(--bui-space-12)}.bui-pb-13{padding-bottom:var(--bui-space-13)}.bui-pb-14{padding-bottom:var(--bui-space-14)}@media (width>=640px){.xs\:bui-pb{padding-bottom:var(--pb-xs)}.xs\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.xs\:bui-pb-1{padding-bottom:var(--bui-space-1)}.xs\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.xs\:bui-pb-2{padding-bottom:var(--bui-space-2)}.xs\:bui-pb-3{padding-bottom:var(--bui-space-3)}.xs\:bui-pb-4{padding-bottom:var(--bui-space-4)}.xs\:bui-pb-5{padding-bottom:var(--bui-space-5)}.xs\:bui-pb-6{padding-bottom:var(--bui-space-6)}.xs\:bui-pb-7{padding-bottom:var(--bui-space-7)}.xs\:bui-pb-8{padding-bottom:var(--bui-space-8)}.xs\:bui-pb-9{padding-bottom:var(--bui-space-9)}.xs\:bui-pb-10{padding-bottom:var(--bui-space-10)}.xs\:bui-pb-11{padding-bottom:var(--bui-space-11)}.xs\:bui-pb-12{padding-bottom:var(--bui-space-12)}.xs\:bui-pb-13{padding-bottom:var(--bui-space-13)}.xs\:bui-pb-14{padding-bottom:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-pb{padding-bottom:var(--pb-sm)}.sm\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.sm\:bui-pb-1{padding-bottom:var(--bui-space-1)}.sm\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.sm\:bui-pb-2{padding-bottom:var(--bui-space-2)}.sm\:bui-pb-3{padding-bottom:var(--bui-space-3)}.sm\:bui-pb-4{padding-bottom:var(--bui-space-4)}.sm\:bui-pb-5{padding-bottom:var(--bui-space-5)}.sm\:bui-pb-6{padding-bottom:var(--bui-space-6)}.sm\:bui-pb-7{padding-bottom:var(--bui-space-7)}.sm\:bui-pb-8{padding-bottom:var(--bui-space-8)}.sm\:bui-pb-9{padding-bottom:var(--bui-space-9)}.sm\:bui-pb-10{padding-bottom:var(--bui-space-10)}.sm\:bui-pb-11{padding-bottom:var(--bui-space-11)}.sm\:bui-pb-12{padding-bottom:var(--bui-space-12)}.sm\:bui-pb-13{padding-bottom:var(--bui-space-13)}.sm\:bui-pb-14{padding-bottom:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-pb{padding-bottom:var(--pb-md)}.md\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.md\:bui-pb-1{padding-bottom:var(--bui-space-1)}.md\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.md\:bui-pb-2{padding-bottom:var(--bui-space-2)}.md\:bui-pb-3{padding-bottom:var(--bui-space-3)}.md\:bui-pb-4{padding-bottom:var(--bui-space-4)}.md\:bui-pb-5{padding-bottom:var(--bui-space-5)}.md\:bui-pb-6{padding-bottom:var(--bui-space-6)}.md\:bui-pb-7{padding-bottom:var(--bui-space-7)}.md\:bui-pb-8{padding-bottom:var(--bui-space-8)}.md\:bui-pb-9{padding-bottom:var(--bui-space-9)}.md\:bui-pb-10{padding-bottom:var(--bui-space-10)}.md\:bui-pb-11{padding-bottom:var(--bui-space-11)}.md\:bui-pb-12{padding-bottom:var(--bui-space-12)}.md\:bui-pb-13{padding-bottom:var(--bui-space-13)}.md\:bui-pb-14{padding-bottom:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-pb{padding-bottom:var(--pb-lg)}.lg\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.lg\:bui-pb-1{padding-bottom:var(--bui-space-1)}.lg\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.lg\:bui-pb-2{padding-bottom:var(--bui-space-2)}.lg\:bui-pb-3{padding-bottom:var(--bui-space-3)}.lg\:bui-pb-4{padding-bottom:var(--bui-space-4)}.lg\:bui-pb-5{padding-bottom:var(--bui-space-5)}.lg\:bui-pb-6{padding-bottom:var(--bui-space-6)}.lg\:bui-pb-7{padding-bottom:var(--bui-space-7)}.lg\:bui-pb-8{padding-bottom:var(--bui-space-8)}.lg\:bui-pb-9{padding-bottom:var(--bui-space-9)}.lg\:bui-pb-10{padding-bottom:var(--bui-space-10)}.lg\:bui-pb-11{padding-bottom:var(--bui-space-11)}.lg\:bui-pb-12{padding-bottom:var(--bui-space-12)}.lg\:bui-pb-13{padding-bottom:var(--bui-space-13)}.lg\:bui-pb-14{padding-bottom:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-pb{padding-bottom:var(--pb-xl)}.xl\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.xl\:bui-pb-1{padding-bottom:var(--bui-space-1)}.xl\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.xl\:bui-pb-2{padding-bottom:var(--bui-space-2)}.xl\:bui-pb-3{padding-bottom:var(--bui-space-3)}.xl\:bui-pb-4{padding-bottom:var(--bui-space-4)}.xl\:bui-pb-5{padding-bottom:var(--bui-space-5)}.xl\:bui-pb-6{padding-bottom:var(--bui-space-6)}.xl\:bui-pb-7{padding-bottom:var(--bui-space-7)}.xl\:bui-pb-8{padding-bottom:var(--bui-space-8)}.xl\:bui-pb-9{padding-bottom:var(--bui-space-9)}.xl\:bui-pb-10{padding-bottom:var(--bui-space-10)}.xl\:bui-pb-11{padding-bottom:var(--bui-space-11)}.xl\:bui-pb-12{padding-bottom:var(--bui-space-12)}.xl\:bui-pb-13{padding-bottom:var(--bui-space-13)}.xl\:bui-pb-14{padding-bottom:var(--bui-space-14)}}.bui-py{padding-top:var(--py);padding-bottom:var(--py)}.bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}@media (width>=640px){.xs\:bui-py{padding-top:var(--py-xs);padding-bottom:var(--py-xs)}.xs\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.xs\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.xs\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.xs\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.xs\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.xs\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.xs\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.xs\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.xs\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.xs\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.xs\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.xs\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.xs\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.xs\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.xs\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.xs\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-py{padding-top:var(--py-sm);padding-bottom:var(--py-sm)}.sm\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.sm\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.sm\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.sm\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.sm\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.sm\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.sm\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.sm\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.sm\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.sm\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.sm\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.sm\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.sm\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.sm\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.sm\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.sm\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-py{padding-top:var(--py-md);padding-bottom:var(--py-md)}.md\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.md\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.md\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.md\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.md\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.md\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.md\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.md\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.md\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.md\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.md\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.md\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.md\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.md\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.md\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.md\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-py{padding-top:var(--py-lg);padding-bottom:var(--py-lg)}.lg\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.lg\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.lg\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.lg\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.lg\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.lg\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.lg\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.lg\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.lg\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.lg\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.lg\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.lg\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.lg\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.lg\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.lg\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.lg\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-py{padding-top:var(--py-xl);padding-bottom:var(--py-xl)}.xl\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.xl\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.xl\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.xl\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.xl\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.xl\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.xl\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.xl\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.xl\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.xl\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.xl\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.xl\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.xl\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.xl\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.xl\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.xl\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}.bui-px{padding-left:var(--px);padding-right:var(--px)}.bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}@media (width>=640px){.xs\:bui-px{padding-left:var(--px-xs);padding-right:var(--px-xs)}.xs\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.xs\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.xs\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.xs\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.xs\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.xs\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.xs\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.xs\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.xs\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.xs\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.xs\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.xs\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.xs\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.xs\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.xs\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.xs\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-px{padding-left:var(--px-sm);padding-right:var(--px-sm)}.sm\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.sm\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.sm\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.sm\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.sm\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.sm\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.sm\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.sm\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.sm\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.sm\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.sm\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.sm\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.sm\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.sm\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.sm\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.sm\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-px{padding-left:var(--px-md);padding-right:var(--px-md)}.md\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.md\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.md\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.md\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.md\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.md\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.md\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.md\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.md\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.md\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.md\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.md\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.md\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.md\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.md\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.md\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-px{padding-left:var(--px-lg);padding-right:var(--px-lg)}.lg\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.lg\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.lg\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.lg\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.lg\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.lg\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.lg\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.lg\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.lg\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.lg\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.lg\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.lg\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.lg\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.lg\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.lg\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.lg\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-px{padding-left:var(--px-xl);padding-right:var(--px-xl)}.xl\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.xl\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.xl\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.xl\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.xl\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.xl\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.xl\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.xl\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.xl\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.xl\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.xl\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.xl\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.xl\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.xl\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.xl\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.xl\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}.bui-m{margin:var(--m)}.bui-m-0\.5{margin:var(--bui-space-0_5)}.bui-m-1{margin:var(--bui-space-1)}.bui-m-1\.5{margin:var(--bui-space-1_5)}.bui-m-2{margin:var(--bui-space-2)}.bui-m-3{margin:var(--bui-space-3)}.bui-m-4{margin:var(--bui-space-4)}.bui-m-5{margin:var(--bui-space-5)}.bui-m-6{margin:var(--bui-space-6)}.bui-m-7{margin:var(--bui-space-7)}.bui-m-8{margin:var(--bui-space-8)}.bui-m-9{margin:var(--bui-space-9)}.bui-m-10{margin:var(--bui-space-10)}.bui-m-11{margin:var(--bui-space-11)}.bui-m-12{margin:var(--bui-space-12)}.bui-m-13{margin:var(--bui-space-13)}.bui-m-14{margin:var(--bui-space-14)}@media (width>=640px){.xs\:bui-m{margin:var(--p-xs)}.xs\:bui-m-0\.5{margin:var(--bui-space-0_5)}.xs\:bui-m-1{margin:var(--bui-space-1)}.xs\:bui-m-1\.5{margin:var(--bui-space-1_5)}.xs\:bui-m-2{margin:var(--bui-space-2)}.xs\:bui-m-3{margin:var(--bui-space-3)}.xs\:bui-m-4{margin:var(--bui-space-4)}.xs\:bui-m-5{margin:var(--bui-space-5)}.xs\:bui-m-6{margin:var(--bui-space-6)}.xs\:bui-m-7{margin:var(--bui-space-7)}.xs\:bui-m-8{margin:var(--bui-space-8)}.xs\:bui-m-9{margin:var(--bui-space-9)}.xs\:bui-m-10{margin:var(--bui-space-10)}.xs\:bui-m-11{margin:var(--bui-space-11)}.xs\:bui-m-12{margin:var(--bui-space-12)}.xs\:bui-m-13{margin:var(--bui-space-13)}.xs\:bui-m-14{margin:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-m{margin:var(--p-sm)}.sm\:bui-m-0\.5{margin:var(--bui-space-0_5)}.sm\:bui-m-1{margin:var(--bui-space-1)}.sm\:bui-m-1\.5{margin:var(--bui-space-1_5)}.sm\:bui-m-2{margin:var(--bui-space-2)}.sm\:bui-m-3{margin:var(--bui-space-3)}.sm\:bui-m-4{margin:var(--bui-space-4)}.sm\:bui-m-5{margin:var(--bui-space-5)}.sm\:bui-m-6{margin:var(--bui-space-6)}.sm\:bui-m-7{margin:var(--bui-space-7)}.sm\:bui-m-8{margin:var(--bui-space-8)}.sm\:bui-m-9{margin:var(--bui-space-9)}.sm\:bui-m-10{margin:var(--bui-space-10)}.sm\:bui-m-11{margin:var(--bui-space-11)}.sm\:bui-m-12{margin:var(--bui-space-12)}.sm\:bui-m-13{margin:var(--bui-space-13)}.sm\:bui-m-14{margin:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-m{margin:var(--p-md)}.md\:bui-m-0\.5{margin:var(--bui-space-0_5)}.md\:bui-m-1{margin:var(--bui-space-1)}.md\:bui-m-1\.5{margin:var(--bui-space-1_5)}.md\:bui-m-2{margin:var(--bui-space-2)}.md\:bui-m-3{margin:var(--bui-space-3)}.md\:bui-m-4{margin:var(--bui-space-4)}.md\:bui-m-5{margin:var(--bui-space-5)}.md\:bui-m-6{margin:var(--bui-space-6)}.md\:bui-m-7{margin:var(--bui-space-7)}.md\:bui-m-8{margin:var(--bui-space-8)}.md\:bui-m-9{margin:var(--bui-space-9)}.md\:bui-m-10{margin:var(--bui-space-10)}.md\:bui-m-11{margin:var(--bui-space-11)}.md\:bui-m-12{margin:var(--bui-space-12)}.md\:bui-m-13{margin:var(--bui-space-13)}.md\:bui-m-14{margin:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-m{margin:var(--p-lg)}.lg\:bui-m-0\.5{margin:var(--bui-space-0_5)}.lg\:bui-m-1{margin:var(--bui-space-1)}.lg\:bui-m-1\.5{margin:var(--bui-space-1_5)}.lg\:bui-m-2{margin:var(--bui-space-2)}.lg\:bui-m-3{margin:var(--bui-space-3)}.lg\:bui-m-4{margin:var(--bui-space-4)}.lg\:bui-m-5{margin:var(--bui-space-5)}.lg\:bui-m-6{margin:var(--bui-space-6)}.lg\:bui-m-7{margin:var(--bui-space-7)}.lg\:bui-m-8{margin:var(--bui-space-8)}.lg\:bui-m-9{margin:var(--bui-space-9)}.lg\:bui-m-10{margin:var(--bui-space-10)}.lg\:bui-m-11{margin:var(--bui-space-11)}.lg\:bui-m-12{margin:var(--bui-space-12)}.lg\:bui-m-13{margin:var(--bui-space-13)}.lg\:bui-m-14{margin:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-m{margin:var(--p-xl)}.xl\:bui-m-0\.5{margin:var(--bui-space-0_5)}.xl\:bui-m-1{margin:var(--bui-space-1)}.xl\:bui-m-1\.5{margin:var(--bui-space-1_5)}.xl\:bui-m-2{margin:var(--bui-space-2)}.xl\:bui-m-3{margin:var(--bui-space-3)}.xl\:bui-m-4{margin:var(--bui-space-4)}.xl\:bui-m-5{margin:var(--bui-space-5)}.xl\:bui-m-6{margin:var(--bui-space-6)}.xl\:bui-m-7{margin:var(--bui-space-7)}.xl\:bui-m-8{margin:var(--bui-space-8)}.xl\:bui-m-9{margin:var(--bui-space-9)}.xl\:bui-m-10{margin:var(--bui-space-10)}.xl\:bui-m-11{margin:var(--bui-space-11)}.xl\:bui-m-12{margin:var(--bui-space-12)}.xl\:bui-m-13{margin:var(--bui-space-13)}.xl\:bui-m-14{margin:var(--bui-space-14)}}.bui-ml{margin-left:var(--ml)}.bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.bui-ml-1{margin-left:var(--bui-space-1)}.bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.bui-ml-2{margin-left:var(--bui-space-2)}.bui-ml-3{margin-left:var(--bui-space-3)}.bui-ml-4{margin-left:var(--bui-space-4)}.bui-ml-5{margin-left:var(--bui-space-5)}.bui-ml-6{margin-left:var(--bui-space-6)}.bui-ml-7{margin-left:var(--bui-space-7)}.bui-ml-8{margin-left:var(--bui-space-8)}.bui-ml-9{margin-left:var(--bui-space-9)}.bui-ml-10{margin-left:var(--bui-space-10)}.bui-ml-11{margin-left:var(--bui-space-11)}.bui-ml-12{margin-left:var(--bui-space-12)}.bui-ml-13{margin-left:var(--bui-space-13)}.bui-ml-14{margin-left:var(--bui-space-14)}@media (width>=640px){.xs\:bui-ml{margin-left:var(--ml-xs)}.xs\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.xs\:bui-ml-1{margin-left:var(--bui-space-1)}.xs\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.xs\:bui-ml-2{margin-left:var(--bui-space-2)}.xs\:bui-ml-3{margin-left:var(--bui-space-3)}.xs\:bui-ml-4{margin-left:var(--bui-space-4)}.xs\:bui-ml-5{margin-left:var(--bui-space-5)}.xs\:bui-ml-6{margin-left:var(--bui-space-6)}.xs\:bui-ml-7{margin-left:var(--bui-space-7)}.xs\:bui-ml-8{margin-left:var(--bui-space-8)}.xs\:bui-ml-9{margin-left:var(--bui-space-9)}.xs\:bui-ml-10{margin-left:var(--bui-space-10)}.xs\:bui-ml-11{margin-left:var(--bui-space-11)}.xs\:bui-ml-12{margin-left:var(--bui-space-12)}.xs\:bui-ml-13{margin-left:var(--bui-space-13)}.xs\:bui-ml-14{margin-left:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-ml{margin-left:var(--ml-sm)}.sm\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.sm\:bui-ml-1{margin-left:var(--bui-space-1)}.sm\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.sm\:bui-ml-2{margin-left:var(--bui-space-2)}.sm\:bui-ml-3{margin-left:var(--bui-space-3)}.sm\:bui-ml-4{margin-left:var(--bui-space-4)}.sm\:bui-ml-5{margin-left:var(--bui-space-5)}.sm\:bui-ml-6{margin-left:var(--bui-space-6)}.sm\:bui-ml-7{margin-left:var(--bui-space-7)}.sm\:bui-ml-8{margin-left:var(--bui-space-8)}.sm\:bui-ml-9{margin-left:var(--bui-space-9)}.sm\:bui-ml-10{margin-left:var(--bui-space-10)}.sm\:bui-ml-11{margin-left:var(--bui-space-11)}.sm\:bui-ml-12{margin-left:var(--bui-space-12)}.sm\:bui-ml-13{margin-left:var(--bui-space-13)}.sm\:bui-ml-14{margin-left:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-ml{margin-left:var(--ml-md)}.md\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.md\:bui-ml-1{margin-left:var(--bui-space-1)}.md\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.md\:bui-ml-2{margin-left:var(--bui-space-2)}.md\:bui-ml-3{margin-left:var(--bui-space-3)}.md\:bui-ml-4{margin-left:var(--bui-space-4)}.md\:bui-ml-5{margin-left:var(--bui-space-5)}.md\:bui-ml-6{margin-left:var(--bui-space-6)}.md\:bui-ml-7{margin-left:var(--bui-space-7)}.md\:bui-ml-8{margin-left:var(--bui-space-8)}.md\:bui-ml-9{margin-left:var(--bui-space-9)}.md\:bui-ml-10{margin-left:var(--bui-space-10)}.md\:bui-ml-11{margin-left:var(--bui-space-11)}.md\:bui-ml-12{margin-left:var(--bui-space-12)}.md\:bui-ml-13{margin-left:var(--bui-space-13)}.md\:bui-ml-14{margin-left:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-ml{margin-left:var(--ml-lg)}.lg\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.lg\:bui-ml-1{margin-left:var(--bui-space-1)}.lg\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.lg\:bui-ml-2{margin-left:var(--bui-space-2)}.lg\:bui-ml-3{margin-left:var(--bui-space-3)}.lg\:bui-ml-4{margin-left:var(--bui-space-4)}.lg\:bui-ml-5{margin-left:var(--bui-space-5)}.lg\:bui-ml-6{margin-left:var(--bui-space-6)}.lg\:bui-ml-7{margin-left:var(--bui-space-7)}.lg\:bui-ml-8{margin-left:var(--bui-space-8)}.lg\:bui-ml-9{margin-left:var(--bui-space-9)}.lg\:bui-ml-10{margin-left:var(--bui-space-10)}.lg\:bui-ml-11{margin-left:var(--bui-space-11)}.lg\:bui-ml-12{margin-left:var(--bui-space-12)}.lg\:bui-ml-13{margin-left:var(--bui-space-13)}.lg\:bui-ml-14{margin-left:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-ml{margin-left:var(--ml-xl)}.xl\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.xl\:bui-ml-1{margin-left:var(--bui-space-1)}.xl\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.xl\:bui-ml-2{margin-left:var(--bui-space-2)}.xl\:bui-ml-3{margin-left:var(--bui-space-3)}.xl\:bui-ml-4{margin-left:var(--bui-space-4)}.xl\:bui-ml-5{margin-left:var(--bui-space-5)}.xl\:bui-ml-6{margin-left:var(--bui-space-6)}.xl\:bui-ml-7{margin-left:var(--bui-space-7)}.xl\:bui-ml-8{margin-left:var(--bui-space-8)}.xl\:bui-ml-9{margin-left:var(--bui-space-9)}.xl\:bui-ml-10{margin-left:var(--bui-space-10)}.xl\:bui-ml-11{margin-left:var(--bui-space-11)}.xl\:bui-ml-12{margin-left:var(--bui-space-12)}.xl\:bui-ml-13{margin-left:var(--bui-space-13)}.xl\:bui-ml-14{margin-left:var(--bui-space-14)}}.bui-mr{margin-right:var(--mr)}.bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.bui-mr-1{margin-right:var(--bui-space-1)}.bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.bui-mr-2{margin-right:var(--bui-space-2)}.bui-mr-3{margin-right:var(--bui-space-3)}.bui-mr-4{margin-right:var(--bui-space-4)}.bui-mr-5{margin-right:var(--bui-space-5)}.bui-mr-6{margin-right:var(--bui-space-6)}.bui-mr-7{margin-right:var(--bui-space-7)}.bui-mr-8{margin-right:var(--bui-space-8)}.bui-mr-9{margin-right:var(--bui-space-9)}.bui-mr-10{margin-right:var(--bui-space-10)}.bui-mr-11{margin-right:var(--bui-space-11)}.bui-mr-12{margin-right:var(--bui-space-12)}.bui-mr-13{margin-right:var(--bui-space-13)}.bui-mr-14{margin-right:var(--bui-space-14)}@media (width>=640px){.xs\:bui-mr{margin-right:var(--mr-xs)}.xs\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.xs\:bui-mr-1{margin-right:var(--bui-space-1)}.xs\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.xs\:bui-mr-2{margin-right:var(--bui-space-2)}.xs\:bui-mr-3{margin-right:var(--bui-space-3)}.xs\:bui-mr-4{margin-right:var(--bui-space-4)}.xs\:bui-mr-5{margin-right:var(--bui-space-5)}.xs\:bui-mr-6{margin-right:var(--bui-space-6)}.xs\:bui-mr-7{margin-right:var(--bui-space-7)}.xs\:bui-mr-8{margin-right:var(--bui-space-8)}.xs\:bui-mr-9{margin-right:var(--bui-space-9)}.xs\:bui-mr-10{margin-right:var(--bui-space-10)}.xs\:bui-mr-11{margin-right:var(--bui-space-11)}.xs\:bui-mr-12{margin-right:var(--bui-space-12)}.xs\:bui-mr-13{margin-right:var(--bui-space-13)}.xs\:bui-mr-14{margin-right:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-mr{margin-right:var(--mr-sm)}.sm\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.sm\:bui-mr-1{margin-right:var(--bui-space-1)}.sm\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.sm\:bui-mr-2{margin-right:var(--bui-space-2)}.sm\:bui-mr-3{margin-right:var(--bui-space-3)}.sm\:bui-mr-4{margin-right:var(--bui-space-4)}.sm\:bui-mr-5{margin-right:var(--bui-space-5)}.sm\:bui-mr-6{margin-right:var(--bui-space-6)}.sm\:bui-mr-7{margin-right:var(--bui-space-7)}.sm\:bui-mr-8{margin-right:var(--bui-space-8)}.sm\:bui-mr-9{margin-right:var(--bui-space-9)}.sm\:bui-mr-10{margin-right:var(--bui-space-10)}.sm\:bui-mr-11{margin-right:var(--bui-space-11)}.sm\:bui-mr-12{margin-right:var(--bui-space-12)}.sm\:bui-mr-13{margin-right:var(--bui-space-13)}.sm\:bui-mr-14{margin-right:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-mr{margin-right:var(--mr-md)}.md\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.md\:bui-mr-1{margin-right:var(--bui-space-1)}.md\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.md\:bui-mr-2{margin-right:var(--bui-space-2)}.md\:bui-mr-3{margin-right:var(--bui-space-3)}.md\:bui-mr-4{margin-right:var(--bui-space-4)}.md\:bui-mr-5{margin-right:var(--bui-space-5)}.md\:bui-mr-6{margin-right:var(--bui-space-6)}.md\:bui-mr-7{margin-right:var(--bui-space-7)}.md\:bui-mr-8{margin-right:var(--bui-space-8)}.md\:bui-mr-9{margin-right:var(--bui-space-9)}.md\:bui-mr-10{margin-right:var(--bui-space-10)}.md\:bui-mr-11{margin-right:var(--bui-space-11)}.md\:bui-mr-12{margin-right:var(--bui-space-12)}.md\:bui-mr-13{margin-right:var(--bui-space-13)}.md\:bui-mr-14{margin-right:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-mr{margin-right:var(--mr-lg)}.lg\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.lg\:bui-mr-1{margin-right:var(--bui-space-1)}.lg\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.lg\:bui-mr-2{margin-right:var(--bui-space-2)}.lg\:bui-mr-3{margin-right:var(--bui-space-3)}.lg\:bui-mr-4{margin-right:var(--bui-space-4)}.lg\:bui-mr-5{margin-right:var(--bui-space-5)}.lg\:bui-mr-6{margin-right:var(--bui-space-6)}.lg\:bui-mr-7{margin-right:var(--bui-space-7)}.lg\:bui-mr-8{margin-right:var(--bui-space-8)}.lg\:bui-mr-9{margin-right:var(--bui-space-9)}.lg\:bui-mr-10{margin-right:var(--bui-space-10)}.lg\:bui-mr-11{margin-right:var(--bui-space-11)}.lg\:bui-mr-12{margin-right:var(--bui-space-12)}.lg\:bui-mr-13{margin-right:var(--bui-space-13)}.lg\:bui-mr-14{margin-right:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-mr{margin-right:var(--mr-xl)}.xl\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.xl\:bui-mr-1{margin-right:var(--bui-space-1)}.xl\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.xl\:bui-mr-2{margin-right:var(--bui-space-2)}.xl\:bui-mr-3{margin-right:var(--bui-space-3)}.xl\:bui-mr-4{margin-right:var(--bui-space-4)}.xl\:bui-mr-5{margin-right:var(--bui-space-5)}.xl\:bui-mr-6{margin-right:var(--bui-space-6)}.xl\:bui-mr-7{margin-right:var(--bui-space-7)}.xl\:bui-mr-8{margin-right:var(--bui-space-8)}.xl\:bui-mr-9{margin-right:var(--bui-space-9)}.xl\:bui-mr-10{margin-right:var(--bui-space-10)}.xl\:bui-mr-11{margin-right:var(--bui-space-11)}.xl\:bui-mr-12{margin-right:var(--bui-space-12)}.xl\:bui-mr-13{margin-right:var(--bui-space-13)}.xl\:bui-mr-14{margin-right:var(--bui-space-14)}}.bui-mt{margin-top:var(--mt)}.bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.bui-mt-1{margin-top:var(--bui-space-1)}.bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.bui-mt-2{margin-top:var(--bui-space-2)}.bui-mt-3{margin-top:var(--bui-space-3)}.bui-mt-4{margin-top:var(--bui-space-4)}.bui-mt-5{margin-top:var(--bui-space-5)}.bui-mt-6{margin-top:var(--bui-space-6)}.bui-mt-7{margin-top:var(--bui-space-7)}.bui-mt-8{margin-top:var(--bui-space-8)}.bui-mt-9{margin-top:var(--bui-space-9)}.bui-mt-10{margin-top:var(--bui-space-10)}.bui-mt-11{margin-top:var(--bui-space-11)}.bui-mt-12{margin-top:var(--bui-space-12)}.bui-mt-13{margin-top:var(--bui-space-13)}.bui-mt-14{margin-top:var(--bui-space-14)}@media (width>=640px){.xs\:bui-mt{margin-top:var(--mt-xs)}.xs\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.xs\:bui-mt-1{margin-top:var(--bui-space-1)}.xs\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.xs\:bui-mt-2{margin-top:var(--bui-space-2)}.xs\:bui-mt-3{margin-top:var(--bui-space-3)}.xs\:bui-mt-4{margin-top:var(--bui-space-4)}.xs\:bui-mt-5{margin-top:var(--bui-space-5)}.xs\:bui-mt-6{margin-top:var(--bui-space-6)}.xs\:bui-mt-7{margin-top:var(--bui-space-7)}.xs\:bui-mt-8{margin-top:var(--bui-space-8)}.xs\:bui-mt-9{margin-top:var(--bui-space-9)}.xs\:bui-mt-10{margin-top:var(--bui-space-10)}.xs\:bui-mt-11{margin-top:var(--bui-space-11)}.xs\:bui-mt-12{margin-top:var(--bui-space-12)}.xs\:bui-mt-13{margin-top:var(--bui-space-13)}.xs\:bui-mt-14{margin-top:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-mt{margin-top:var(--mt-sm)}.sm\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.sm\:bui-mt-1{margin-top:var(--bui-space-1)}.sm\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.sm\:bui-mt-2{margin-top:var(--bui-space-2)}.sm\:bui-mt-3{margin-top:var(--bui-space-3)}.sm\:bui-mt-4{margin-top:var(--bui-space-4)}.sm\:bui-mt-5{margin-top:var(--bui-space-5)}.sm\:bui-mt-6{margin-top:var(--bui-space-6)}.sm\:bui-mt-7{margin-top:var(--bui-space-7)}.sm\:bui-mt-8{margin-top:var(--bui-space-8)}.sm\:bui-mt-9{margin-top:var(--bui-space-9)}.sm\:bui-mt-10{margin-top:var(--bui-space-10)}.sm\:bui-mt-11{margin-top:var(--bui-space-11)}.sm\:bui-mt-12{margin-top:var(--bui-space-12)}.sm\:bui-mt-13{margin-top:var(--bui-space-13)}.sm\:bui-mt-14{margin-top:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-mt{margin-top:var(--mt-md)}.md\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.md\:bui-mt-1{margin-top:var(--bui-space-1)}.md\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.md\:bui-mt-2{margin-top:var(--bui-space-2)}.md\:bui-mt-3{margin-top:var(--bui-space-3)}.md\:bui-mt-4{margin-top:var(--bui-space-4)}.md\:bui-mt-5{margin-top:var(--bui-space-5)}.md\:bui-mt-6{margin-top:var(--bui-space-6)}.md\:bui-mt-7{margin-top:var(--bui-space-7)}.md\:bui-mt-8{margin-top:var(--bui-space-8)}.md\:bui-mt-9{margin-top:var(--bui-space-9)}.md\:bui-mt-10{margin-top:var(--bui-space-10)}.md\:bui-mt-11{margin-top:var(--bui-space-11)}.md\:bui-mt-12{margin-top:var(--bui-space-12)}.md\:bui-mt-13{margin-top:var(--bui-space-13)}.md\:bui-mt-14{margin-top:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-mt{margin-top:var(--mt-lg)}.lg\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.lg\:bui-mt-1{margin-top:var(--bui-space-1)}.lg\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.lg\:bui-mt-2{margin-top:var(--bui-space-2)}.lg\:bui-mt-3{margin-top:var(--bui-space-3)}.lg\:bui-mt-4{margin-top:var(--bui-space-4)}.lg\:bui-mt-5{margin-top:var(--bui-space-5)}.lg\:bui-mt-6{margin-top:var(--bui-space-6)}.lg\:bui-mt-7{margin-top:var(--bui-space-7)}.lg\:bui-mt-8{margin-top:var(--bui-space-8)}.lg\:bui-mt-9{margin-top:var(--bui-space-9)}.lg\:bui-mt-10{margin-top:var(--bui-space-10)}.lg\:bui-mt-11{margin-top:var(--bui-space-11)}.lg\:bui-mt-12{margin-top:var(--bui-space-12)}.lg\:bui-mt-13{margin-top:var(--bui-space-13)}.lg\:bui-mt-14{margin-top:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-mt{margin-top:var(--mt-xl)}.xl\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.xl\:bui-mt-1{margin-top:var(--bui-space-1)}.xl\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.xl\:bui-mt-2{margin-top:var(--bui-space-2)}.xl\:bui-mt-3{margin-top:var(--bui-space-3)}.xl\:bui-mt-4{margin-top:var(--bui-space-4)}.xl\:bui-mt-5{margin-top:var(--bui-space-5)}.xl\:bui-mt-6{margin-top:var(--bui-space-6)}.xl\:bui-mt-7{margin-top:var(--bui-space-7)}.xl\:bui-mt-8{margin-top:var(--bui-space-8)}.xl\:bui-mt-9{margin-top:var(--bui-space-9)}.xl\:bui-mt-10{margin-top:var(--bui-space-10)}.xl\:bui-mt-11{margin-top:var(--bui-space-11)}.xl\:bui-mt-12{margin-top:var(--bui-space-12)}.xl\:bui-mt-13{margin-top:var(--bui-space-13)}.xl\:bui-mt-14{margin-top:var(--bui-space-14)}}.bui-mb{margin-bottom:var(--mb)}.bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.bui-mb-1{margin-bottom:var(--bui-space-1)}.bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.bui-mb-2{margin-bottom:var(--bui-space-2)}.bui-mb-3{margin-bottom:var(--bui-space-3)}.bui-mb-4{margin-bottom:var(--bui-space-4)}.bui-mb-5{margin-bottom:var(--bui-space-5)}.bui-mb-6{margin-bottom:var(--bui-space-6)}.bui-mb-7{margin-bottom:var(--bui-space-7)}.bui-mb-8{margin-bottom:var(--bui-space-8)}.bui-mb-9{margin-bottom:var(--bui-space-9)}.bui-mb-10{margin-bottom:var(--bui-space-10)}.bui-mb-11{margin-bottom:var(--bui-space-11)}.bui-mb-12{margin-bottom:var(--bui-space-12)}.bui-mb-13{margin-bottom:var(--bui-space-13)}.bui-mb-14{margin-bottom:var(--bui-space-14)}@media (width>=640px){.xs\:bui-mb{margin-bottom:var(--mb-xs)}.xs\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.xs\:bui-mb-1{margin-bottom:var(--bui-space-1)}.xs\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.xs\:bui-mb-2{margin-bottom:var(--bui-space-2)}.xs\:bui-mb-3{margin-bottom:var(--bui-space-3)}.xs\:bui-mb-4{margin-bottom:var(--bui-space-4)}.xs\:bui-mb-5{margin-bottom:var(--bui-space-5)}.xs\:bui-mb-6{margin-bottom:var(--bui-space-6)}.xs\:bui-mb-7{margin-bottom:var(--bui-space-7)}.xs\:bui-mb-8{margin-bottom:var(--bui-space-8)}.xs\:bui-mb-9{margin-bottom:var(--bui-space-9)}.xs\:bui-mb-10{margin-bottom:var(--bui-space-10)}.xs\:bui-mb-11{margin-bottom:var(--bui-space-11)}.xs\:bui-mb-12{margin-bottom:var(--bui-space-12)}.xs\:bui-mb-13{margin-bottom:var(--bui-space-13)}.xs\:bui-mb-14{margin-bottom:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-mb{margin-bottom:var(--mb-sm)}.sm\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.sm\:bui-mb-1{margin-bottom:var(--bui-space-1)}.sm\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.sm\:bui-mb-2{margin-bottom:var(--bui-space-2)}.sm\:bui-mb-3{margin-bottom:var(--bui-space-3)}.sm\:bui-mb-4{margin-bottom:var(--bui-space-4)}.sm\:bui-mb-5{margin-bottom:var(--bui-space-5)}.sm\:bui-mb-6{margin-bottom:var(--bui-space-6)}.sm\:bui-mb-7{margin-bottom:var(--bui-space-7)}.sm\:bui-mb-8{margin-bottom:var(--bui-space-8)}.sm\:bui-mb-9{margin-bottom:var(--bui-space-9)}.sm\:bui-mb-10{margin-bottom:var(--bui-space-10)}.sm\:bui-mb-11{margin-bottom:var(--bui-space-11)}.sm\:bui-mb-12{margin-bottom:var(--bui-space-12)}.sm\:bui-mb-13{margin-bottom:var(--bui-space-13)}.sm\:bui-mb-14{margin-bottom:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-mb{margin-bottom:var(--mb-md)}.md\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.md\:bui-mb-1{margin-bottom:var(--bui-space-1)}.md\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.md\:bui-mb-2{margin-bottom:var(--bui-space-2)}.md\:bui-mb-3{margin-bottom:var(--bui-space-3)}.md\:bui-mb-4{margin-bottom:var(--bui-space-4)}.md\:bui-mb-5{margin-bottom:var(--bui-space-5)}.md\:bui-mb-6{margin-bottom:var(--bui-space-6)}.md\:bui-mb-7{margin-bottom:var(--bui-space-7)}.md\:bui-mb-8{margin-bottom:var(--bui-space-8)}.md\:bui-mb-9{margin-bottom:var(--bui-space-9)}.md\:bui-mb-10{margin-bottom:var(--bui-space-10)}.md\:bui-mb-11{margin-bottom:var(--bui-space-11)}.md\:bui-mb-12{margin-bottom:var(--bui-space-12)}.md\:bui-mb-13{margin-bottom:var(--bui-space-13)}.md\:bui-mb-14{margin-bottom:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-mb{margin-bottom:var(--mb-lg)}.lg\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.lg\:bui-mb-1{margin-bottom:var(--bui-space-1)}.lg\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.lg\:bui-mb-2{margin-bottom:var(--bui-space-2)}.lg\:bui-mb-3{margin-bottom:var(--bui-space-3)}.lg\:bui-mb-4{margin-bottom:var(--bui-space-4)}.lg\:bui-mb-5{margin-bottom:var(--bui-space-5)}.lg\:bui-mb-6{margin-bottom:var(--bui-space-6)}.lg\:bui-mb-7{margin-bottom:var(--bui-space-7)}.lg\:bui-mb-8{margin-bottom:var(--bui-space-8)}.lg\:bui-mb-9{margin-bottom:var(--bui-space-9)}.lg\:bui-mb-10{margin-bottom:var(--bui-space-10)}.lg\:bui-mb-11{margin-bottom:var(--bui-space-11)}.lg\:bui-mb-12{margin-bottom:var(--bui-space-12)}.lg\:bui-mb-13{margin-bottom:var(--bui-space-13)}.lg\:bui-mb-14{margin-bottom:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-mb{margin-bottom:var(--mb-xl)}.xl\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.xl\:bui-mb-1{margin-bottom:var(--bui-space-1)}.xl\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.xl\:bui-mb-2{margin-bottom:var(--bui-space-2)}.xl\:bui-mb-3{margin-bottom:var(--bui-space-3)}.xl\:bui-mb-4{margin-bottom:var(--bui-space-4)}.xl\:bui-mb-5{margin-bottom:var(--bui-space-5)}.xl\:bui-mb-6{margin-bottom:var(--bui-space-6)}.xl\:bui-mb-7{margin-bottom:var(--bui-space-7)}.xl\:bui-mb-8{margin-bottom:var(--bui-space-8)}.xl\:bui-mb-9{margin-bottom:var(--bui-space-9)}.xl\:bui-mb-10{margin-bottom:var(--bui-space-10)}.xl\:bui-mb-11{margin-bottom:var(--bui-space-11)}.xl\:bui-mb-12{margin-bottom:var(--bui-space-12)}.xl\:bui-mb-13{margin-bottom:var(--bui-space-13)}.xl\:bui-mb-14{margin-bottom:var(--bui-space-14)}}.bui-my{margin-top:var(--my);margin-bottom:var(--my)}.bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}@media (width>=640px){.xs\:bui-my{margin-top:var(--my-xs);margin-bottom:var(--my-xs)}.xs\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.xs\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.xs\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.xs\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.xs\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.xs\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.xs\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.xs\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.xs\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.xs\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.xs\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.xs\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.xs\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.xs\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.xs\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.xs\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-my{margin-top:var(--my-sm);margin-bottom:var(--my-sm)}.sm\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.sm\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.sm\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.sm\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.sm\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.sm\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.sm\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.sm\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.sm\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.sm\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.sm\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.sm\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.sm\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.sm\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.sm\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.sm\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-my{margin-top:var(--my-md);margin-bottom:var(--my-md)}.md\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.md\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.md\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.md\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.md\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.md\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.md\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.md\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.md\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.md\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.md\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.md\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.md\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.md\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.md\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.md\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-my{margin-top:var(--my-lg);margin-bottom:var(--my-lg)}.lg\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.lg\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.lg\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.lg\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.lg\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.lg\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.lg\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.lg\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.lg\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.lg\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.lg\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.lg\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.lg\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.lg\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.lg\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.lg\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-my{margin-top:var(--my-xl);margin-bottom:var(--my-xl)}.xl\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.xl\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.xl\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.xl\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.xl\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.xl\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.xl\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.xl\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.xl\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.xl\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.xl\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.xl\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.xl\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.xl\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.xl\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.xl\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}.bui-mx{margin-left:var(--mx);margin-right:var(--mx)}.bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}@media (width>=640px){.xs\:bui-mx{margin-left:var(--mx-xs);margin-right:var(--mx-xs)}.xs\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.xs\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.xs\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.xs\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.xs\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.xs\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.xs\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.xs\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.xs\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.xs\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.xs\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.xs\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.xs\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.xs\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.xs\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.xs\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-mx{margin-left:var(--mx-sm);margin-right:var(--mx-sm)}.sm\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.sm\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.sm\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.sm\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.sm\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.sm\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.sm\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.sm\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.sm\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.sm\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.sm\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.sm\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.sm\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.sm\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.sm\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.sm\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-mx{margin-left:var(--mx-md);margin-right:var(--mx-md)}.md\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.md\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.md\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.md\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.md\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.md\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.md\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.md\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.md\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.md\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.md\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.md\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.md\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.md\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.md\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.md\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-mx{margin-left:var(--mx-lg);margin-right:var(--mx-lg)}.lg\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.lg\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.lg\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.lg\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.lg\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.lg\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.lg\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.lg\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.lg\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.lg\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.lg\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.lg\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.lg\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.lg\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.lg\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.lg\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-mx{margin-left:var(--mx-xl);margin-right:var(--mx-xl)}.xl\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.xl\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.xl\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.xl\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.xl\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.xl\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.xl\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.xl\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.xl\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.xl\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.xl\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.xl\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.xl\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.xl\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.xl\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.xl\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}.bui-display-none{display:none}.bui-display-inline{display:inline}.bui-display-inline-block{display:inline-block}.bui-display-block{display:block}@media (width>=640px){.xs\:bui-display-none{display:none}.xs\:bui-display-inline{display:inline}.xs\:bui-display-inline-block{display:inline-block}.xs\:bui-display-block{display:block}}@media (width>=768px){.sm\:bui-display-none{display:none}.sm\:bui-display-inline{display:inline}.sm\:bui-display-inline-block{display:inline-block}.sm\:bui-display-block{display:block}}@media (width>=1024px){.md\:bui-display-none{display:none}.md\:bui-display-inline{display:inline}.md\:bui-display-inline-block{display:inline-block}.md\:bui-display-block{display:block}}@media (width>=1280px){.lg\:bui-display-none{display:none}.lg\:bui-display-inline{display:inline}.lg\:bui-display-inline-block{display:inline-block}.lg\:bui-display-block{display:block}}@media (width>=1536px){.xl\:bui-display-none{display:none}.xl\:bui-display-inline{display:inline}.xl\:bui-display-inline-block{display:inline-block}.xl\:bui-display-block{display:block}}.bui-w{width:var(--width)}.bui-min-w{min-width:var(--min-width)}.bui-max-w{max-width:var(--max-width)}@media (width>=640px){.xs\:bui-w{width:var(--width)}.xs\:bui-min-w{min-width:var(--min-width)}.xs\:bui-max-w{max-width:var(--max-width)}}@media (width>=768px){.sm\:bui-w{width:var(--width)}.sm\:bui-min-w{min-width:var(--min-width)}.sm\:bui-max-w{max-width:var(--max-width)}}@media (width>=1024px){.md\:bui-w{width:var(--width)}.md\:bui-min-w{min-width:var(--min-width)}.md\:bui-max-w{max-width:var(--max-width)}}@media (width>=1280px){.lg\:bui-w{width:var(--width)}.lg\:bui-min-w{min-width:var(--min-width)}.lg\:bui-max-w{max-width:var(--max-width)}}@media (width>=1536px){.xl\:bui-w{width:var(--width)}.xl\:bui-min-w{min-width:var(--min-width)}.xl\:bui-max-w{max-width:var(--max-width)}}.bui-h{height:var(--height)}.bui-min-h{min-height:var(--min-height)}.bui-max-h{max-height:var(--max-height)}@media (width>=640px){.xs\:bui-h{height:var(--height)}.xs\:bui-min-h{min-height:var(--min-height)}.xs\:bui-max-h{max-height:var(--max-height)}}@media (width>=768px){.sm\:bui-h{height:var(--height)}.sm\:bui-min-h{min-height:var(--min-height)}.sm\:bui-max-h{max-height:var(--max-height)}}@media (width>=1024px){.md\:bui-h{height:var(--height)}.md\:bui-min-h{min-height:var(--min-height)}.md\:bui-max-h{max-height:var(--max-height)}}@media (width>=1280px){.lg\:bui-h{height:var(--height)}.lg\:bui-min-h{min-height:var(--min-height)}.lg\:bui-max-h{max-height:var(--max-height)}}@media (width>=1536px){.xl\:bui-h{height:var(--height)}.xl\:bui-min-h{min-height:var(--min-height)}.xl\:bui-max-h{max-height:var(--max-height)}}.bui-position-absolute{position:absolute}.bui-position-fixed{position:fixed}.bui-position-sticky{position:sticky}.bui-position-relative{position:relative}.bui-position-static{position:static}@media (width>=640px){.xs\:bui-position-absolute{position:absolute}.xs\:bui-position-fixed{position:fixed}.xs\:bui-position-sticky{position:sticky}.xs\:bui-position-relative{position:relative}.xs\:bui-position-static{position:static}}@media (width>=768px){.sm\:bui-position-absolute{position:absolute}.sm\:bui-position-fixed{position:fixed}.sm\:bui-position-sticky{position:sticky}.sm\:bui-position-relative{position:relative}.sm\:bui-position-static{position:static}}@media (width>=1024px){.md\:bui-position-absolute{position:absolute}.md\:bui-position-fixed{position:fixed}.md\:bui-position-sticky{position:sticky}.md\:bui-position-relative{position:relative}.md\:bui-position-static{position:static}}@media (width>=1280px){.lg\:bui-position-absolute{position:absolute}.lg\:bui-position-fixed{position:fixed}.lg\:bui-position-sticky{position:sticky}.lg\:bui-position-relative{position:relative}.lg\:bui-position-static{position:static}}@media (width>=1536px){.xl\:bui-position-absolute{position:absolute}.xl\:bui-position-fixed{position:fixed}.xl\:bui-position-sticky{position:sticky}.xl\:bui-position-relative{position:relative}.xl\:bui-position-static{position:static}}.bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.bui-col-span-1{grid-column:span 1/span 1}.bui-col-span-2{grid-column:span 2/span 2}.bui-col-span-3{grid-column:span 3/span 3}.bui-col-span-4{grid-column:span 4/span 4}.bui-col-span-5{grid-column:span 5/span 5}.bui-col-span-6{grid-column:span 6/span 6}.bui-col-span-7{grid-column:span 7/span 7}.bui-col-span-8{grid-column:span 8/span 8}.bui-col-span-9{grid-column:span 9/span 9}.bui-col-span-10{grid-column:span 10/span 10}.bui-col-span-11{grid-column:span 11/span 11}.bui-col-span-12{grid-column:span 12/span 12}.bui-col-span-auto{grid-column:span auto/span auto}.bui-col-start-1{grid-column-start:1}.bui-col-start-2{grid-column-start:2}.bui-col-start-3{grid-column-start:3}.bui-col-start-4{grid-column-start:4}.bui-col-start-5{grid-column-start:5}.bui-col-start-6{grid-column-start:6}.bui-col-start-7{grid-column-start:7}.bui-col-start-8{grid-column-start:8}.bui-col-start-9{grid-column-start:9}.bui-col-start-10{grid-column-start:10}.bui-col-start-11{grid-column-start:11}.bui-col-start-12{grid-column-start:12}.bui-col-start-13{grid-column-start:13}.bui-col-start-auto{grid-column-start:auto}.bui-col-end-1{grid-column-end:1}.bui-col-end-2{grid-column-end:2}.bui-col-end-3{grid-column-end:3}.bui-col-end-4{grid-column-end:4}.bui-col-end-5{grid-column-end:5}.bui-col-end-6{grid-column-end:6}.bui-col-end-7{grid-column-end:7}.bui-col-end-8{grid-column-end:8}.bui-col-end-9{grid-column-end:9}.bui-col-end-10{grid-column-end:10}.bui-col-end-11{grid-column-end:11}.bui-col-end-12{grid-column-end:12}.bui-col-end-13{grid-column-end:13}.bui-col-end-auto{grid-column-end:auto}.bui-row-span-1{grid-row:span 1/span 1}.bui-row-span-2{grid-row:span 2/span 2}.bui-row-span-3{grid-row:span 3/span 3}.bui-row-span-4{grid-row:span 4/span 4}.bui-row-span-5{grid-row:span 5/span 5}.bui-row-span-6{grid-row:span 6/span 6}.bui-row-span-7{grid-row:span 7/span 7}.bui-row-span-8{grid-row:span 8/span 8}.bui-row-span-9{grid-row:span 9/span 9}.bui-row-span-10{grid-row:span 10/span 10}.bui-row-span-11{grid-row:span 11/span 11}.bui-row-span-12{grid-row:span 12/span 12}.bui-row-span-auto{grid-row:span auto/span auto}@media (width>=640px){.xs\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.xs\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.xs\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.xs\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.xs\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.xs\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.xs\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.xs\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.xs\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.xs\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.xs\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.xs\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.xs\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.xs\:bui-col-span-1{grid-column:span 1/span 1}.xs\:bui-col-span-2{grid-column:span 2/span 2}.xs\:bui-col-span-3{grid-column:span 3/span 3}.xs\:bui-col-span-4{grid-column:span 4/span 4}.xs\:bui-col-span-5{grid-column:span 5/span 5}.xs\:bui-col-span-6{grid-column:span 6/span 6}.xs\:bui-col-span-7{grid-column:span 7/span 7}.xs\:bui-col-span-8{grid-column:span 8/span 8}.xs\:bui-col-span-9{grid-column:span 9/span 9}.xs\:bui-col-span-10{grid-column:span 10/span 10}.xs\:bui-col-span-11{grid-column:span 11/span 11}.xs\:bui-col-span-12{grid-column:span 12/span 12}.xs\:bui-col-span-auto{grid-column:span auto/span auto}.xs\:bui-col-start-1{grid-column-start:1}.xs\:bui-col-start-2{grid-column-start:2}.xs\:bui-col-start-3{grid-column-start:3}.xs\:bui-col-start-4{grid-column-start:4}.xs\:bui-col-start-5{grid-column-start:5}.xs\:bui-col-start-6{grid-column-start:6}.xs\:bui-col-start-7{grid-column-start:7}.xs\:bui-col-start-8{grid-column-start:8}.xs\:bui-col-start-9{grid-column-start:9}.xs\:bui-col-start-10{grid-column-start:10}.xs\:bui-col-start-11{grid-column-start:11}.xs\:bui-col-start-12{grid-column-start:12}.xs\:bui-col-start-13{grid-column-start:13}.xs\:bui-col-start-auto{grid-column-start:auto}.xs\:bui-col-end-1{grid-column-end:1}.xs\:bui-col-end-2{grid-column-end:2}.xs\:bui-col-end-3{grid-column-end:3}.xs\:bui-col-end-4{grid-column-end:4}.xs\:bui-col-end-5{grid-column-end:5}.xs\:bui-col-end-6{grid-column-end:6}.xs\:bui-col-end-7{grid-column-end:7}.xs\:bui-col-end-8{grid-column-end:8}.xs\:bui-col-end-9{grid-column-end:9}.xs\:bui-col-end-10{grid-column-end:10}.xs\:bui-col-end-11{grid-column-end:11}.xs\:bui-col-end-12{grid-column-end:12}.xs\:bui-col-end-13{grid-column-end:13}.xs\:bui-col-end-auto{grid-column-end:auto}.xs\:bui-row-span-1{grid-row:span 1/span 1}.xs\:bui-row-span-2{grid-row:span 2/span 2}.xs\:bui-row-span-3{grid-row:span 3/span 3}.xs\:bui-row-span-4{grid-row:span 4/span 4}.xs\:bui-row-span-5{grid-row:span 5/span 5}.xs\:bui-row-span-6{grid-row:span 6/span 6}.xs\:bui-row-span-7{grid-row:span 7/span 7}.xs\:bui-row-span-8{grid-row:span 8/span 8}.xs\:bui-row-span-9{grid-row:span 9/span 9}.xs\:bui-row-span-10{grid-row:span 10/span 10}.xs\:bui-row-span-11{grid-row:span 11/span 11}.xs\:bui-row-span-12{grid-row:span 12/span 12}.xs\:bui-row-span-auto{grid-row:span auto/span auto}}@media (width>=768px){.sm\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.sm\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.sm\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.sm\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.sm\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.sm\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.sm\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.sm\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.sm\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.sm\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.sm\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.sm\:bui-col-span-1{grid-column:span 1/span 1}.sm\:bui-col-span-2{grid-column:span 2/span 2}.sm\:bui-col-span-3{grid-column:span 3/span 3}.sm\:bui-col-span-4{grid-column:span 4/span 4}.sm\:bui-col-span-5{grid-column:span 5/span 5}.sm\:bui-col-span-6{grid-column:span 6/span 6}.sm\:bui-col-span-7{grid-column:span 7/span 7}.sm\:bui-col-span-8{grid-column:span 8/span 8}.sm\:bui-col-span-9{grid-column:span 9/span 9}.sm\:bui-col-span-10{grid-column:span 10/span 10}.sm\:bui-col-span-11{grid-column:span 11/span 11}.sm\:bui-col-span-12{grid-column:span 12/span 12}.sm\:bui-col-span-auto{grid-column:span auto/span auto}.sm\:bui-col-start-1{grid-column-start:1}.sm\:bui-col-start-2{grid-column-start:2}.sm\:bui-col-start-3{grid-column-start:3}.sm\:bui-col-start-4{grid-column-start:4}.sm\:bui-col-start-5{grid-column-start:5}.sm\:bui-col-start-6{grid-column-start:6}.sm\:bui-col-start-7{grid-column-start:7}.sm\:bui-col-start-8{grid-column-start:8}.sm\:bui-col-start-9{grid-column-start:9}.sm\:bui-col-start-10{grid-column-start:10}.sm\:bui-col-start-11{grid-column-start:11}.sm\:bui-col-start-12{grid-column-start:12}.sm\:bui-col-start-13{grid-column-start:13}.sm\:bui-col-start-auto{grid-column-start:auto}.sm\:bui-col-end-1{grid-column-end:1}.sm\:bui-col-end-2{grid-column-end:2}.sm\:bui-col-end-3{grid-column-end:3}.sm\:bui-col-end-4{grid-column-end:4}.sm\:bui-col-end-5{grid-column-end:5}.sm\:bui-col-end-6{grid-column-end:6}.sm\:bui-col-end-7{grid-column-end:7}.sm\:bui-col-end-8{grid-column-end:8}.sm\:bui-col-end-9{grid-column-end:9}.sm\:bui-col-end-10{grid-column-end:10}.sm\:bui-col-end-11{grid-column-end:11}.sm\:bui-col-end-12{grid-column-end:12}.sm\:bui-col-end-13{grid-column-end:13}.sm\:bui-col-end-auto{grid-column-end:auto}.sm\:bui-row-span-1{grid-row:span 1/span 1}.sm\:bui-row-span-2{grid-row:span 2/span 2}.sm\:bui-row-span-3{grid-row:span 3/span 3}.sm\:bui-row-span-4{grid-row:span 4/span 4}.sm\:bui-row-span-5{grid-row:span 5/span 5}.sm\:bui-row-span-6{grid-row:span 6/span 6}.sm\:bui-row-span-7{grid-row:span 7/span 7}.sm\:bui-row-span-8{grid-row:span 8/span 8}.sm\:bui-row-span-9{grid-row:span 9/span 9}.sm\:bui-row-span-10{grid-row:span 10/span 10}.sm\:bui-row-span-11{grid-row:span 11/span 11}.sm\:bui-row-span-12{grid-row:span 12/span 12}.sm\:bui-row-span-auto{grid-row:span auto/span auto}}@media (width>=1024px){.md\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.md\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.md\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.md\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.md\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.md\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.md\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.md\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.md\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.md\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.md\:bui-col-span-1{grid-column:span 1/span 1}.md\:bui-col-span-2{grid-column:span 2/span 2}.md\:bui-col-span-3{grid-column:span 3/span 3}.md\:bui-col-span-4{grid-column:span 4/span 4}.md\:bui-col-span-5{grid-column:span 5/span 5}.md\:bui-col-span-6{grid-column:span 6/span 6}.md\:bui-col-span-7{grid-column:span 7/span 7}.md\:bui-col-span-8{grid-column:span 8/span 8}.md\:bui-col-span-9{grid-column:span 9/span 9}.md\:bui-col-span-10{grid-column:span 10/span 10}.md\:bui-col-span-11{grid-column:span 11/span 11}.md\:bui-col-span-12{grid-column:span 12/span 12}.md\:bui-col-span-auto{grid-column:span auto/span auto}.md\:bui-col-start-1{grid-column-start:1}.md\:bui-col-start-2{grid-column-start:2}.md\:bui-col-start-3{grid-column-start:3}.md\:bui-col-start-4{grid-column-start:4}.md\:bui-col-start-5{grid-column-start:5}.md\:bui-col-start-6{grid-column-start:6}.md\:bui-col-start-7{grid-column-start:7}.md\:bui-col-start-8{grid-column-start:8}.md\:bui-col-start-9{grid-column-start:9}.md\:bui-col-start-10{grid-column-start:10}.md\:bui-col-start-11{grid-column-start:11}.md\:bui-col-start-12{grid-column-start:12}.md\:bui-col-start-13{grid-column-start:13}.md\:bui-col-start-auto{grid-column-start:auto}.md\:bui-col-end-1{grid-column-end:1}.md\:bui-col-end-2{grid-column-end:2}.md\:bui-col-end-3{grid-column-end:3}.md\:bui-col-end-4{grid-column-end:4}.md\:bui-col-end-5{grid-column-end:5}.md\:bui-col-end-6{grid-column-end:6}.md\:bui-col-end-7{grid-column-end:7}.md\:bui-col-end-8{grid-column-end:8}.md\:bui-col-end-9{grid-column-end:9}.md\:bui-col-end-10{grid-column-end:10}.md\:bui-col-end-11{grid-column-end:11}.md\:bui-col-end-12{grid-column-end:12}.md\:bui-col-end-13{grid-column-end:13}.md\:bui-col-end-auto{grid-column-end:auto}.md\:bui-row-span-1{grid-row:span 1/span 1}.md\:bui-row-span-2{grid-row:span 2/span 2}.md\:bui-row-span-3{grid-row:span 3/span 3}.md\:bui-row-span-4{grid-row:span 4/span 4}.md\:bui-row-span-5{grid-row:span 5/span 5}.md\:bui-row-span-6{grid-row:span 6/span 6}.md\:bui-row-span-7{grid-row:span 7/span 7}.md\:bui-row-span-8{grid-row:span 8/span 8}.md\:bui-row-span-9{grid-row:span 9/span 9}.md\:bui-row-span-10{grid-row:span 10/span 10}.md\:bui-row-span-11{grid-row:span 11/span 11}.md\:bui-row-span-12{grid-row:span 12/span 12}.md\:bui-row-span-auto{grid-row:span auto/span auto}}@media (width>=1280px){.lg\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.lg\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.lg\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.lg\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.lg\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.lg\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.lg\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.lg\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.lg\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.lg\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.lg\:bui-col-span-1{grid-column:span 1/span 1}.lg\:bui-col-span-2{grid-column:span 2/span 2}.lg\:bui-col-span-3{grid-column:span 3/span 3}.lg\:bui-col-span-4{grid-column:span 4/span 4}.lg\:bui-col-span-5{grid-column:span 5/span 5}.lg\:bui-col-span-6{grid-column:span 6/span 6}.lg\:bui-col-span-7{grid-column:span 7/span 7}.lg\:bui-col-span-8{grid-column:span 8/span 8}.lg\:bui-col-span-9{grid-column:span 9/span 9}.lg\:bui-col-span-10{grid-column:span 10/span 10}.lg\:bui-col-span-11{grid-column:span 11/span 11}.lg\:bui-col-span-12{grid-column:span 12/span 12}.lg\:bui-col-span-auto{grid-column:span auto/span auto}.lg\:bui-col-start-1{grid-column-start:1}.lg\:bui-col-start-2{grid-column-start:2}.lg\:bui-col-start-3{grid-column-start:3}.lg\:bui-col-start-4{grid-column-start:4}.lg\:bui-col-start-5{grid-column-start:5}.lg\:bui-col-start-6{grid-column-start:6}.lg\:bui-col-start-7{grid-column-start:7}.lg\:bui-col-start-8{grid-column-start:8}.lg\:bui-col-start-9{grid-column-start:9}.lg\:bui-col-start-10{grid-column-start:10}.lg\:bui-col-start-11{grid-column-start:11}.lg\:bui-col-start-12{grid-column-start:12}.lg\:bui-col-start-13{grid-column-start:13}.lg\:bui-col-start-auto{grid-column-start:auto}.lg\:bui-col-end-1{grid-column-end:1}.lg\:bui-col-end-2{grid-column-end:2}.lg\:bui-col-end-3{grid-column-end:3}.lg\:bui-col-end-4{grid-column-end:4}.lg\:bui-col-end-5{grid-column-end:5}.lg\:bui-col-end-6{grid-column-end:6}.lg\:bui-col-end-7{grid-column-end:7}.lg\:bui-col-end-8{grid-column-end:8}.lg\:bui-col-end-9{grid-column-end:9}.lg\:bui-col-end-10{grid-column-end:10}.lg\:bui-col-end-11{grid-column-end:11}.lg\:bui-col-end-12{grid-column-end:12}.lg\:bui-col-end-13{grid-column-end:13}.lg\:bui-col-end-auto{grid-column-end:auto}.lg\:bui-row-span-1{grid-row:span 1/span 1}.lg\:bui-row-span-2{grid-row:span 2/span 2}.lg\:bui-row-span-3{grid-row:span 3/span 3}.lg\:bui-row-span-4{grid-row:span 4/span 4}.lg\:bui-row-span-5{grid-row:span 5/span 5}.lg\:bui-row-span-6{grid-row:span 6/span 6}.lg\:bui-row-span-7{grid-row:span 7/span 7}.lg\:bui-row-span-8{grid-row:span 8/span 8}.lg\:bui-row-span-9{grid-row:span 9/span 9}.lg\:bui-row-span-10{grid-row:span 10/span 10}.lg\:bui-row-span-11{grid-row:span 11/span 11}.lg\:bui-row-span-12{grid-row:span 12/span 12}.lg\:bui-row-span-auto{grid-row:span auto/span auto}}@media (width>=1536px){.xl\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.xl\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.xl\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.xl\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.xl\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.xl\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.xl\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.xl\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.xl\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.xl\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.xl\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.xl\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.xl\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.xl\:bui-col-span-1{grid-column:span 1/span 1}.xl\:bui-col-span-2{grid-column:span 2/span 2}.xl\:bui-col-span-3{grid-column:span 3/span 3}.xl\:bui-col-span-4{grid-column:span 4/span 4}.xl\:bui-col-span-5{grid-column:span 5/span 5}.xl\:bui-col-span-6{grid-column:span 6/span 6}.xl\:bui-col-span-7{grid-column:span 7/span 7}.xl\:bui-col-span-8{grid-column:span 8/span 8}.xl\:bui-col-span-9{grid-column:span 9/span 9}.xl\:bui-col-span-10{grid-column:span 10/span 10}.xl\:bui-col-span-11{grid-column:span 11/span 11}.xl\:bui-col-span-12{grid-column:span 12/span 12}.xl\:bui-col-span-auto{grid-column:span auto/span auto}.xl\:bui-col-start-1{grid-column-start:1}.xl\:bui-col-start-2{grid-column-start:2}.xl\:bui-col-start-3{grid-column-start:3}.xl\:bui-col-start-4{grid-column-start:4}.xl\:bui-col-start-5{grid-column-start:5}.xl\:bui-col-start-6{grid-column-start:6}.xl\:bui-col-start-7{grid-column-start:7}.xl\:bui-col-start-8{grid-column-start:8}.xl\:bui-col-start-9{grid-column-start:9}.xl\:bui-col-start-10{grid-column-start:10}.xl\:bui-col-start-11{grid-column-start:11}.xl\:bui-col-start-12{grid-column-start:12}.xl\:bui-col-start-13{grid-column-start:13}.xl\:bui-col-start-auto{grid-column-start:auto}.xl\:bui-col-end-1{grid-column-end:1}.xl\:bui-col-end-2{grid-column-end:2}.xl\:bui-col-end-3{grid-column-end:3}.xl\:bui-col-end-4{grid-column-end:4}.xl\:bui-col-end-5{grid-column-end:5}.xl\:bui-col-end-6{grid-column-end:6}.xl\:bui-col-end-7{grid-column-end:7}.xl\:bui-col-end-8{grid-column-end:8}.xl\:bui-col-end-9{grid-column-end:9}.xl\:bui-col-end-10{grid-column-end:10}.xl\:bui-col-end-11{grid-column-end:11}.xl\:bui-col-end-12{grid-column-end:12}.xl\:bui-col-end-13{grid-column-end:13}.xl\:bui-col-end-auto{grid-column-end:auto}.xl\:bui-row-span-1{grid-row:span 1/span 1}.xl\:bui-row-span-2{grid-row:span 2/span 2}.xl\:bui-row-span-3{grid-row:span 3/span 3}.xl\:bui-row-span-4{grid-row:span 4/span 4}.xl\:bui-row-span-5{grid-row:span 5/span 5}.xl\:bui-row-span-6{grid-row:span 6/span 6}.xl\:bui-row-span-7{grid-row:span 7/span 7}.xl\:bui-row-span-8{grid-row:span 8/span 8}.xl\:bui-row-span-9{grid-row:span 9/span 9}.xl\:bui-row-span-10{grid-row:span 10/span 10}.xl\:bui-row-span-11{grid-row:span 11/span 11}.xl\:bui-row-span-12{grid-row:span 12/span 12}.xl\:bui-row-span-auto{grid-row:span auto/span auto}}.bui-gap{gap:var(--gap)}.bui-gap-0\.5{gap:var(--bui-space-0_5)}.bui-gap-1{gap:var(--bui-space-1)}.bui-gap-1\.5{gap:var(--bui-space-1_5)}.bui-gap-2{gap:var(--bui-space-2)}.bui-gap-3{gap:var(--bui-space-3)}.bui-gap-4{gap:var(--bui-space-4)}.bui-gap-5{gap:var(--bui-space-5)}.bui-gap-6{gap:var(--bui-space-6)}.bui-gap-7{gap:var(--bui-space-7)}.bui-gap-8{gap:var(--bui-space-8)}.bui-gap-9{gap:var(--bui-space-9)}.bui-gap-10{gap:var(--bui-space-10)}.bui-gap-11{gap:var(--bui-space-11)}.bui-gap-12{gap:var(--bui-space-12)}.bui-gap-13{gap:var(--bui-space-13)}.bui-gap-14{gap:var(--bui-space-14)}@media (width>=640px){.xs\:bui-gap{gap:var(--gap-xs)}.xs\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.xs\:bui-gap-1{gap:var(--bui-space-1)}.xs\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.xs\:bui-gap-2{gap:var(--bui-space-2)}.xs\:bui-gap-3{gap:var(--bui-space-3)}.xs\:bui-gap-4{gap:var(--bui-space-4)}.xs\:bui-gap-5{gap:var(--bui-space-5)}.xs\:bui-gap-6{gap:var(--bui-space-6)}.xs\:bui-gap-7{gap:var(--bui-space-7)}.xs\:bui-gap-8{gap:var(--bui-space-8)}.xs\:bui-gap-9{gap:var(--bui-space-9)}.xs\:bui-gap-10{gap:var(--bui-space-10)}.xs\:bui-gap-11{gap:var(--bui-space-11)}.xs\:bui-gap-12{gap:var(--bui-space-12)}.xs\:bui-gap-13{gap:var(--bui-space-13)}.xs\:bui-gap-14{gap:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-gap{gap:var(--gap-sm)}.sm\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.sm\:bui-gap-1{gap:var(--bui-space-1)}.sm\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.sm\:bui-gap-2{gap:var(--bui-space-2)}.sm\:bui-gap-3{gap:var(--bui-space-3)}.sm\:bui-gap-4{gap:var(--bui-space-4)}.sm\:bui-gap-5{gap:var(--bui-space-5)}.sm\:bui-gap-6{gap:var(--bui-space-6)}.sm\:bui-gap-7{gap:var(--bui-space-7)}.sm\:bui-gap-8{gap:var(--bui-space-8)}.sm\:bui-gap-9{gap:var(--bui-space-9)}.sm\:bui-gap-10{gap:var(--bui-space-10)}.sm\:bui-gap-11{gap:var(--bui-space-11)}.sm\:bui-gap-12{gap:var(--bui-space-12)}.sm\:bui-gap-13{gap:var(--bui-space-13)}.sm\:bui-gap-14{gap:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-gap{gap:var(--gap-md)}.md\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.md\:bui-gap-1{gap:var(--bui-space-1)}.md\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.md\:bui-gap-2{gap:var(--bui-space-2)}.md\:bui-gap-3{gap:var(--bui-space-3)}.md\:bui-gap-4{gap:var(--bui-space-4)}.md\:bui-gap-5{gap:var(--bui-space-5)}.md\:bui-gap-6{gap:var(--bui-space-6)}.md\:bui-gap-7{gap:var(--bui-space-7)}.md\:bui-gap-8{gap:var(--bui-space-8)}.md\:bui-gap-9{gap:var(--bui-space-9)}.md\:bui-gap-10{gap:var(--bui-space-10)}.md\:bui-gap-11{gap:var(--bui-space-11)}.md\:bui-gap-12{gap:var(--bui-space-12)}.md\:bui-gap-13{gap:var(--bui-space-13)}.md\:bui-gap-14{gap:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-gap{gap:var(--gap-lg)}.lg\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.lg\:bui-gap-1{gap:var(--bui-space-1)}.lg\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.lg\:bui-gap-2{gap:var(--bui-space-2)}.lg\:bui-gap-3{gap:var(--bui-space-3)}.lg\:bui-gap-4{gap:var(--bui-space-4)}.lg\:bui-gap-5{gap:var(--bui-space-5)}.lg\:bui-gap-6{gap:var(--bui-space-6)}.lg\:bui-gap-7{gap:var(--bui-space-7)}.lg\:bui-gap-8{gap:var(--bui-space-8)}.lg\:bui-gap-9{gap:var(--bui-space-9)}.lg\:bui-gap-10{gap:var(--bui-space-10)}.lg\:bui-gap-11{gap:var(--bui-space-11)}.lg\:bui-gap-12{gap:var(--bui-space-12)}.lg\:bui-gap-13{gap:var(--bui-space-13)}.lg\:bui-gap-14{gap:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-gap{gap:var(--gap-xl)}.xl\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.xl\:bui-gap-1{gap:var(--bui-space-1)}.xl\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.xl\:bui-gap-2{gap:var(--bui-space-2)}.xl\:bui-gap-3{gap:var(--bui-space-3)}.xl\:bui-gap-4{gap:var(--bui-space-4)}.xl\:bui-gap-5{gap:var(--bui-space-5)}.xl\:bui-gap-6{gap:var(--bui-space-6)}.xl\:bui-gap-7{gap:var(--bui-space-7)}.xl\:bui-gap-8{gap:var(--bui-space-8)}.xl\:bui-gap-9{gap:var(--bui-space-9)}.xl\:bui-gap-10{gap:var(--bui-space-10)}.xl\:bui-gap-11{gap:var(--bui-space-11)}.xl\:bui-gap-12{gap:var(--bui-space-12)}.xl\:bui-gap-13{gap:var(--bui-space-13)}.xl\:bui-gap-14{gap:var(--bui-space-14)}}.bui-align-start{align-items:start}.bui-align-center{align-items:center}.bui-align-end{align-items:end}.bui-align-baseline{align-items:baseline}.bui-align-stretch{align-items:stretch}.bui-jc-start{justify-content:start}.bui-jc-center{justify-content:center}.bui-jc-end{justify-content:end}.bui-jc-between{justify-content:space-between}.bui-fd-row{flex-direction:row}.bui-fd-column{flex-direction:column}.bui-fd-row-reverse{flex-direction:row-reverse}.bui-fd-column-reverse{flex-direction:column-reverse}@media (width>=640px){.xs\:bui-align-start{align-items:start}.xs\:bui-align-center{align-items:center}.xs\:bui-align-end{align-items:end}.xs\:bui-align-stretch{align-items:stretch}.xs\:bui-jc-start{justify-content:start}.xs\:bui-jc-center{justify-content:center}.xs\:bui-jc-end{justify-content:end}.xs\:bui-jc-between{justify-content:space-between}.xs\:bui-fd-row{flex-direction:row}.xs\:bui-fd-column{flex-direction:column}.xs\:bui-fd-row-reverse{flex-direction:row-reverse}.xs\:bui-fd-column-reverse{flex-direction:column-reverse}}@media (width>=768px){.sm\:bui-align-start{align-items:start}.sm\:bui-align-center{align-items:center}.sm\:bui-align-end{align-items:end}.sm\:bui-align-stretch{align-items:stretch}.sm\:bui-jc-start{justify-content:start}.sm\:bui-jc-center{justify-content:center}.sm\:bui-jc-end{justify-content:end}.sm\:bui-jc-between{justify-content:space-between}.sm\:bui-fd-row{flex-direction:row}.sm\:bui-fd-column{flex-direction:column}.sm\:bui-fd-row-reverse{flex-direction:row-reverse}.sm\:bui-fd-column-reverse{flex-direction:column-reverse}}@media (width>=1024px){.md\:bui-align-start{align-items:start}.md\:bui-align-center{align-items:center}.md\:bui-align-end{align-items:end}.md\:bui-align-stretch{align-items:stretch}.md\:bui-jc-start{justify-content:start}.md\:bui-jc-center{justify-content:center}.md\:bui-jc-end{justify-content:end}.md\:bui-jc-between{justify-content:space-between}.md\:bui-fd-row{flex-direction:row}.md\:bui-fd-column{flex-direction:column}.md\:bui-fd-row-reverse{flex-direction:row-reverse}.md\:bui-fd-column-reverse{flex-direction:column-reverse}}@media (width>=1280px){.lg\:bui-align-start{align-items:start}.lg\:bui-align-center{align-items:center}.lg\:bui-align-end{align-items:end}.lg\:bui-align-stretch{align-items:stretch}.lg\:bui-jc-start{justify-content:start}.lg\:bui-jc-center{justify-content:center}.lg\:bui-jc-end{justify-content:end}.lg\:bui-jc-between{justify-content:space-between}.lg\:bui-fd-row{flex-direction:row}.lg\:bui-fd-column{flex-direction:column}.lg\:bui-fd-row-reverse{flex-direction:row-reverse}.lg\:bui-fd-column-reverse{flex-direction:column-reverse}}@media (width>=1536px){.xl\:bui-align-start{align-items:start}.xl\:bui-align-center{align-items:center}.xl\:bui-align-end{align-items:end}.xl\:bui-align-stretch{align-items:stretch}.xl\:bui-jc-start{justify-content:start}.xl\:bui-jc-center{justify-content:center}.xl\:bui-jc-end{justify-content:end}.xl\:bui-jc-between{justify-content:space-between}.xl\:bui-fd-row{flex-direction:row}.xl\:bui-fd-column{flex-direction:column}.xl\:bui-fd-row-reverse{flex-direction:row-reverse}.xl\:bui-fd-column-reverse{flex-direction:column-reverse}}} \ No newline at end of file +@layer tokens{:root{--bui-font-regular:system-ui;--bui-font-monospace:ui-monospace,"Menlo","Monaco","Consolas","Liberation Mono","Courier New",monospace;--bui-font-weight-regular:400;--bui-font-weight-bold:600;--bui-font-size-1:.625rem;--bui-font-size-2:.75rem;--bui-font-size-3:.875rem;--bui-font-size-4:1rem;--bui-font-size-5:1.25rem;--bui-font-size-6:1.5rem;--bui-font-size-7:2rem;--bui-font-size-8:3rem;--bui-font-size-9:4rem;--bui-font-size-10:5.75rem;--bui-space:.25rem;--bui-space-0_5:calc(var(--bui-space)*.5);--bui-space-1:var(--bui-space);--bui-space-1_5:calc(var(--bui-space)*1.5);--bui-space-2:calc(var(--bui-space)*2);--bui-space-3:calc(var(--bui-space)*3);--bui-space-4:calc(var(--bui-space)*4);--bui-space-5:calc(var(--bui-space)*5);--bui-space-6:calc(var(--bui-space)*6);--bui-space-7:calc(var(--bui-space)*7);--bui-space-8:calc(var(--bui-space)*8);--bui-space-9:calc(var(--bui-space)*9);--bui-space-10:calc(var(--bui-space)*10);--bui-space-11:calc(var(--bui-space)*11);--bui-space-12:calc(var(--bui-space)*12);--bui-space-13:calc(var(--bui-space)*13);--bui-space-14:calc(var(--bui-space)*14);--bui-radius-1:calc(.125rem);--bui-radius-2:calc(.25rem);--bui-radius-3:calc(.5rem);--bui-radius-4:calc(.75rem);--bui-radius-5:calc(1rem);--bui-radius-6:calc(1.25rem);--bui-radius-full:9999px;--bui-black:#000;--bui-white:#fff;--bui-gray-1:#f8f8f8;--bui-gray-2:#ececec;--bui-gray-3:#d9d9d9;--bui-gray-4:#c1c1c1;--bui-gray-5:#9e9e9e;--bui-gray-6:#8c8c8c;--bui-gray-7:#757575;--bui-gray-8:#595959;--bui-bg-surface-0:var(--bui-gray-1);--bui-bg-surface-1:var(--bui-white);--bui-bg-surface-2:var(--bui-gray-1);--bui-bg-surface-3:var(--bui-gray-2);--bui-bg-solid:#1f5493;--bui-bg-solid-hover:#163a66;--bui-bg-solid-pressed:#0f2b4e;--bui-bg-solid-disabled:#ebebeb;--bui-bg-tint:transparent;--bui-bg-tint-hover:#1f549366;--bui-bg-tint-pressed:#1f549399;--bui-bg-tint-disabled:#ebebeb;--bui-bg-danger:#feebe7;--bui-bg-warning:#fff2b2;--bui-bg-success:#e6f6eb;--bui-fg-primary:var(--bui-black);--bui-fg-secondary:var(--bui-gray-7);--bui-fg-link:#1f5493;--bui-fg-link-hover:#1f2d5c;--bui-fg-disabled:#9e9e9e;--bui-fg-solid:var(--bui-white);--bui-fg-solid-disabled:#9c9c9c;--bui-fg-tint:#1f5493;--bui-fg-tint-disabled:var(--bui-gray-5);--bui-fg-danger:#e22b2b;--bui-fg-warning:#e36d05;--bui-fg-success:#1db954;--bui-border:#0000001a;--bui-border-hover:#0003;--bui-border-pressed:#0006;--bui-border-disabled:#0000001a;--bui-border-danger:#f87a7a;--bui-border-warning:#e36d05;--bui-border-success:#53db83;--bui-ring:#1f5493;--bui-scrollbar:#a0a0a03b;--bui-scrollbar-thumb:#a0a0a0;--bui-animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite}[data-theme-mode=dark]{--bui-gray-1:#191919;--bui-gray-2:#242424;--bui-gray-3:#373737;--bui-gray-4:#464646;--bui-gray-5:#575757;--bui-gray-6:#7b7b7b;--bui-gray-7:#9e9e9e;--bui-gray-8:#b4b4b4;--bui-bg-surface-0:#333;--bui-bg-surface-1:var(--bui-gray-1);--bui-bg-surface-2:var(--bui-gray-2);--bui-bg-surface-3:var(--bui-gray-3);--bui-bg-solid:#9cc9ff;--bui-bg-solid-hover:#83b9fd;--bui-bg-solid-pressed:#83b9fd;--bui-bg-solid-disabled:#222;--bui-bg-tint:transparent;--bui-bg-tint-hover:#9cc9ff1f;--bui-bg-tint-pressed:#9cc9ff29;--bui-bg-tint-disabled:transparent;--bui-bg-danger:#3b1219;--bui-bg-warning:#302008;--bui-bg-success:#132d21;--bui-fg-primary:var(--bui-white);--bui-fg-secondary:var(--bui-gray-7);--bui-fg-link:#9cc9ff;--bui-fg-link-hover:#7eb5f7;--bui-fg-disabled:var(--bui-gray-7);--bui-fg-solid:#101821;--bui-fg-solid-disabled:var(--bui-gray-5);--bui-fg-tint:#9cc9ff;--bui-fg-tint-disabled:var(--bui-gray-5);--bui-fg-danger:#e22b2b;--bui-fg-warning:#e36d05;--bui-fg-success:#1db954;--bui-border:#ffffff1f;--bui-border-hover:#fff6;--bui-border-pressed:#ffffff80;--bui-border-disabled:#fff3;--bui-border-danger:#f87a7a;--bui-border-warning:#e36d05;--bui-border-success:#53db83;--bui-ring:#1f5493;--bui-scrollbar:#3636363a;--bui-scrollbar-thumb:#575757}}@layer base{*,:before,:after{box-sizing:border-box}html{-webkit-text-size-adjust:100%;tab-size:4;font-family:system-ui,Segoe UI,Roboto,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji;line-height:1.15}body{margin:0}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{border-color:currentColor}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:100%;line-height:1.15}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}legend{padding:0}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}:where(a){color:inherit;text-decoration:none}@keyframes pulse{50%{opacity:.5}}body{background-color:var(--bui-bg-surface-0);color:var(--bui-fg-primary);font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);font-size:var(--bui-font-size-3);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}[data-theme-mode=dark]{color-scheme:dark}[data-theme-mode=light]{color-scheme:light}}@layer components;@layer utilities{.bui-p{padding:var(--p)}.bui-p-0\.5{padding:var(--bui-space-0_5)}.bui-p-1{padding:var(--bui-space-1)}.bui-p-1\.5{padding:var(--bui-space-1_5)}.bui-p-2{padding:var(--bui-space-2)}.bui-p-3{padding:var(--bui-space-3)}.bui-p-4{padding:var(--bui-space-4)}.bui-p-5{padding:var(--bui-space-5)}.bui-p-6{padding:var(--bui-space-6)}.bui-p-7{padding:var(--bui-space-7)}.bui-p-8{padding:var(--bui-space-8)}.bui-p-9{padding:var(--bui-space-9)}.bui-p-10{padding:var(--bui-space-10)}.bui-p-11{padding:var(--bui-space-11)}.bui-p-12{padding:var(--bui-space-12)}.bui-p-13{padding:var(--bui-space-13)}.bui-p-14{padding:var(--bui-space-14)}@media (width>=640px){.xs\:bui-p{padding:var(--p-xs)}.xs\:bui-p-0\.5{padding:var(--bui-space-0_5)}.xs\:bui-p-1{padding:var(--bui-space-1)}.xs\:bui-p-1\.5{padding:var(--bui-space-1_5)}.xs\:bui-p-2{padding:var(--bui-space-2)}.xs\:bui-p-3{padding:var(--bui-space-3)}.xs\:bui-p-4{padding:var(--bui-space-4)}.xs\:bui-p-5{padding:var(--bui-space-5)}.xs\:bui-p-6{padding:var(--bui-space-6)}.xs\:bui-p-7{padding:var(--bui-space-7)}.xs\:bui-p-8{padding:var(--bui-space-8)}.xs\:bui-p-9{padding:var(--bui-space-9)}.xs\:bui-p-10{padding:var(--bui-space-10)}.xs\:bui-p-11{padding:var(--bui-space-11)}.xs\:bui-p-12{padding:var(--bui-space-12)}.xs\:bui-p-13{padding:var(--bui-space-13)}.xs\:bui-p-14{padding:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-p{padding:var(--p-sm)}.sm\:bui-p-0\.5{padding:var(--bui-space-0_5)}.sm\:bui-p-1{padding:var(--bui-space-1)}.sm\:bui-p-1\.5{padding:var(--bui-space-1_5)}.sm\:bui-p-2{padding:var(--bui-space-2)}.sm\:bui-p-3{padding:var(--bui-space-3)}.sm\:bui-p-4{padding:var(--bui-space-4)}.sm\:bui-p-5{padding:var(--bui-space-5)}.sm\:bui-p-6{padding:var(--bui-space-6)}.sm\:bui-p-7{padding:var(--bui-space-7)}.sm\:bui-p-8{padding:var(--bui-space-8)}.sm\:bui-p-9{padding:var(--bui-space-9)}.sm\:bui-p-10{padding:var(--bui-space-10)}.sm\:bui-p-11{padding:var(--bui-space-11)}.sm\:bui-p-12{padding:var(--bui-space-12)}.sm\:bui-p-13{padding:var(--bui-space-13)}.sm\:bui-p-14{padding:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-p{padding:var(--p-md)}.md\:bui-p-0\.5{padding:var(--bui-space-0_5)}.md\:bui-p-1{padding:var(--bui-space-1)}.md\:bui-p-1\.5{padding:var(--bui-space-1_5)}.md\:bui-p-2{padding:var(--bui-space-2)}.md\:bui-p-3{padding:var(--bui-space-3)}.md\:bui-p-4{padding:var(--bui-space-4)}.md\:bui-p-5{padding:var(--bui-space-5)}.md\:bui-p-6{padding:var(--bui-space-6)}.md\:bui-p-7{padding:var(--bui-space-7)}.md\:bui-p-8{padding:var(--bui-space-8)}.md\:bui-p-9{padding:var(--bui-space-9)}.md\:bui-p-10{padding:var(--bui-space-10)}.md\:bui-p-11{padding:var(--bui-space-11)}.md\:bui-p-12{padding:var(--bui-space-12)}.md\:bui-p-13{padding:var(--bui-space-13)}.md\:bui-p-14{padding:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-p{padding:var(--p-lg)}.lg\:bui-p-0\.5{padding:var(--bui-space-0_5)}.lg\:bui-p-1{padding:var(--bui-space-1)}.lg\:bui-p-1\.5{padding:var(--bui-space-1_5)}.lg\:bui-p-2{padding:var(--bui-space-2)}.lg\:bui-p-3{padding:var(--bui-space-3)}.lg\:bui-p-4{padding:var(--bui-space-4)}.lg\:bui-p-5{padding:var(--bui-space-5)}.lg\:bui-p-6{padding:var(--bui-space-6)}.lg\:bui-p-7{padding:var(--bui-space-7)}.lg\:bui-p-8{padding:var(--bui-space-8)}.lg\:bui-p-9{padding:var(--bui-space-9)}.lg\:bui-p-10{padding:var(--bui-space-10)}.lg\:bui-p-11{padding:var(--bui-space-11)}.lg\:bui-p-12{padding:var(--bui-space-12)}.lg\:bui-p-13{padding:var(--bui-space-13)}.lg\:bui-p-14{padding:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-p{padding:var(--p-xl)}.xl\:bui-p-0\.5{padding:var(--bui-space-0_5)}.xl\:bui-p-1{padding:var(--bui-space-1)}.xl\:bui-p-1\.5{padding:var(--bui-space-1_5)}.xl\:bui-p-2{padding:var(--bui-space-2)}.xl\:bui-p-3{padding:var(--bui-space-3)}.xl\:bui-p-4{padding:var(--bui-space-4)}.xl\:bui-p-5{padding:var(--bui-space-5)}.xl\:bui-p-6{padding:var(--bui-space-6)}.xl\:bui-p-7{padding:var(--bui-space-7)}.xl\:bui-p-8{padding:var(--bui-space-8)}.xl\:bui-p-9{padding:var(--bui-space-9)}.xl\:bui-p-10{padding:var(--bui-space-10)}.xl\:bui-p-11{padding:var(--bui-space-11)}.xl\:bui-p-12{padding:var(--bui-space-12)}.xl\:bui-p-13{padding:var(--bui-space-13)}.xl\:bui-p-14{padding:var(--bui-space-14)}}.bui-pl{padding-left:var(--pl)}.bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.bui-pl-1{padding-left:var(--bui-space-1)}.bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.bui-pl-2{padding-left:var(--bui-space-2)}.bui-pl-3{padding-left:var(--bui-space-3)}.bui-pl-4{padding-left:var(--bui-space-4)}.bui-pl-5{padding-left:var(--bui-space-5)}.bui-pl-6{padding-left:var(--bui-space-6)}.bui-pl-7{padding-left:var(--bui-space-7)}.bui-pl-8{padding-left:var(--bui-space-8)}.bui-pl-9{padding-left:var(--bui-space-9)}.bui-pl-10{padding-left:var(--bui-space-10)}.bui-pl-11{padding-left:var(--bui-space-11)}.bui-pl-12{padding-left:var(--bui-space-12)}.bui-pl-13{padding-left:var(--bui-space-13)}.bui-pl-14{padding-left:var(--bui-space-14)}@media (width>=640px){.xs\:bui-pl{padding-left:var(--pl-xs)}.xs\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.xs\:bui-pl-1{padding-left:var(--bui-space-1)}.xs\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.xs\:bui-pl-2{padding-left:var(--bui-space-2)}.xs\:bui-pl-3{padding-left:var(--bui-space-3)}.xs\:bui-pl-4{padding-left:var(--bui-space-4)}.xs\:bui-pl-5{padding-left:var(--bui-space-5)}.xs\:bui-pl-6{padding-left:var(--bui-space-6)}.xs\:bui-pl-7{padding-left:var(--bui-space-7)}.xs\:bui-pl-8{padding-left:var(--bui-space-8)}.xs\:bui-pl-9{padding-left:var(--bui-space-9)}.xs\:bui-pl-10{padding-left:var(--bui-space-10)}.xs\:bui-pl-11{padding-left:var(--bui-space-11)}.xs\:bui-pl-12{padding-left:var(--bui-space-12)}.xs\:bui-pl-13{padding-left:var(--bui-space-13)}.xs\:bui-pl-14{padding-left:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-pl{padding-left:var(--pl-sm)}.sm\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.sm\:bui-pl-1{padding-left:var(--bui-space-1)}.sm\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.sm\:bui-pl-2{padding-left:var(--bui-space-2)}.sm\:bui-pl-3{padding-left:var(--bui-space-3)}.sm\:bui-pl-4{padding-left:var(--bui-space-4)}.sm\:bui-pl-5{padding-left:var(--bui-space-5)}.sm\:bui-pl-6{padding-left:var(--bui-space-6)}.sm\:bui-pl-7{padding-left:var(--bui-space-7)}.sm\:bui-pl-8{padding-left:var(--bui-space-8)}.sm\:bui-pl-9{padding-left:var(--bui-space-9)}.sm\:bui-pl-10{padding-left:var(--bui-space-10)}.sm\:bui-pl-11{padding-left:var(--bui-space-11)}.sm\:bui-pl-12{padding-left:var(--bui-space-12)}.sm\:bui-pl-13{padding-left:var(--bui-space-13)}.sm\:bui-pl-14{padding-left:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-pl{padding-left:var(--pl-md)}.md\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.md\:bui-pl-1{padding-left:var(--bui-space-1)}.md\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.md\:bui-pl-2{padding-left:var(--bui-space-2)}.md\:bui-pl-3{padding-left:var(--bui-space-3)}.md\:bui-pl-4{padding-left:var(--bui-space-4)}.md\:bui-pl-5{padding-left:var(--bui-space-5)}.md\:bui-pl-6{padding-left:var(--bui-space-6)}.md\:bui-pl-7{padding-left:var(--bui-space-7)}.md\:bui-pl-8{padding-left:var(--bui-space-8)}.md\:bui-pl-9{padding-left:var(--bui-space-9)}.md\:bui-pl-10{padding-left:var(--bui-space-10)}.md\:bui-pl-11{padding-left:var(--bui-space-11)}.md\:bui-pl-12{padding-left:var(--bui-space-12)}.md\:bui-pl-13{padding-left:var(--bui-space-13)}.md\:bui-pl-14{padding-left:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-pl{padding-left:var(--pl-lg)}.lg\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.lg\:bui-pl-1{padding-left:var(--bui-space-1)}.lg\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.lg\:bui-pl-2{padding-left:var(--bui-space-2)}.lg\:bui-pl-3{padding-left:var(--bui-space-3)}.lg\:bui-pl-4{padding-left:var(--bui-space-4)}.lg\:bui-pl-5{padding-left:var(--bui-space-5)}.lg\:bui-pl-6{padding-left:var(--bui-space-6)}.lg\:bui-pl-7{padding-left:var(--bui-space-7)}.lg\:bui-pl-8{padding-left:var(--bui-space-8)}.lg\:bui-pl-9{padding-left:var(--bui-space-9)}.lg\:bui-pl-10{padding-left:var(--bui-space-10)}.lg\:bui-pl-11{padding-left:var(--bui-space-11)}.lg\:bui-pl-12{padding-left:var(--bui-space-12)}.lg\:bui-pl-13{padding-left:var(--bui-space-13)}.lg\:bui-pl-14{padding-left:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-pl{padding-left:var(--pl-xl)}.xl\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.xl\:bui-pl-1{padding-left:var(--bui-space-1)}.xl\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.xl\:bui-pl-2{padding-left:var(--bui-space-2)}.xl\:bui-pl-3{padding-left:var(--bui-space-3)}.xl\:bui-pl-4{padding-left:var(--bui-space-4)}.xl\:bui-pl-5{padding-left:var(--bui-space-5)}.xl\:bui-pl-6{padding-left:var(--bui-space-6)}.xl\:bui-pl-7{padding-left:var(--bui-space-7)}.xl\:bui-pl-8{padding-left:var(--bui-space-8)}.xl\:bui-pl-9{padding-left:var(--bui-space-9)}.xl\:bui-pl-10{padding-left:var(--bui-space-10)}.xl\:bui-pl-11{padding-left:var(--bui-space-11)}.xl\:bui-pl-12{padding-left:var(--bui-space-12)}.xl\:bui-pl-13{padding-left:var(--bui-space-13)}.xl\:bui-pl-14{padding-left:var(--bui-space-14)}}.bui-pr{padding-right:var(--pr)}.bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.bui-pr-1{padding-right:var(--bui-space-1)}.bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.bui-pr-2{padding-right:var(--bui-space-2)}.bui-pr-3{padding-right:var(--bui-space-3)}.bui-pr-4{padding-right:var(--bui-space-4)}.bui-pr-5{padding-right:var(--bui-space-5)}.bui-pr-6{padding-right:var(--bui-space-6)}.bui-pr-7{padding-right:var(--bui-space-7)}.bui-pr-8{padding-right:var(--bui-space-8)}.bui-pr-9{padding-right:var(--bui-space-9)}.bui-pr-10{padding-right:var(--bui-space-10)}.bui-pr-11{padding-right:var(--bui-space-11)}.bui-pr-12{padding-right:var(--bui-space-12)}.bui-pr-13{padding-right:var(--bui-space-13)}.bui-pr-14{padding-right:var(--bui-space-14)}@media (width>=640px){.xs\:bui-pr{padding-right:var(--pr-xs)}.xs\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.xs\:bui-pr-1{padding-right:var(--bui-space-1)}.xs\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.xs\:bui-pr-2{padding-right:var(--bui-space-2)}.xs\:bui-pr-3{padding-right:var(--bui-space-3)}.xs\:bui-pr-4{padding-right:var(--bui-space-4)}.xs\:bui-pr-5{padding-right:var(--bui-space-5)}.xs\:bui-pr-6{padding-right:var(--bui-space-6)}.xs\:bui-pr-7{padding-right:var(--bui-space-7)}.xs\:bui-pr-8{padding-right:var(--bui-space-8)}.xs\:bui-pr-9{padding-right:var(--bui-space-9)}.xs\:bui-pr-10{padding-right:var(--bui-space-10)}.xs\:bui-pr-11{padding-right:var(--bui-space-11)}.xs\:bui-pr-12{padding-right:var(--bui-space-12)}.xs\:bui-pr-13{padding-right:var(--bui-space-13)}.xs\:bui-pr-14{padding-right:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-pr{padding-right:var(--pr-sm)}.sm\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.sm\:bui-pr-1{padding-right:var(--bui-space-1)}.sm\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.sm\:bui-pr-2{padding-right:var(--bui-space-2)}.sm\:bui-pr-3{padding-right:var(--bui-space-3)}.sm\:bui-pr-4{padding-right:var(--bui-space-4)}.sm\:bui-pr-5{padding-right:var(--bui-space-5)}.sm\:bui-pr-6{padding-right:var(--bui-space-6)}.sm\:bui-pr-7{padding-right:var(--bui-space-7)}.sm\:bui-pr-8{padding-right:var(--bui-space-8)}.sm\:bui-pr-9{padding-right:var(--bui-space-9)}.sm\:bui-pr-10{padding-right:var(--bui-space-10)}.sm\:bui-pr-11{padding-right:var(--bui-space-11)}.sm\:bui-pr-12{padding-right:var(--bui-space-12)}.sm\:bui-pr-13{padding-right:var(--bui-space-13)}.sm\:bui-pr-14{padding-right:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-pr{padding-right:var(--pr-md)}.md\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.md\:bui-pr-1{padding-right:var(--bui-space-1)}.md\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.md\:bui-pr-2{padding-right:var(--bui-space-2)}.md\:bui-pr-3{padding-right:var(--bui-space-3)}.md\:bui-pr-4{padding-right:var(--bui-space-4)}.md\:bui-pr-5{padding-right:var(--bui-space-5)}.md\:bui-pr-6{padding-right:var(--bui-space-6)}.md\:bui-pr-7{padding-right:var(--bui-space-7)}.md\:bui-pr-8{padding-right:var(--bui-space-8)}.md\:bui-pr-9{padding-right:var(--bui-space-9)}.md\:bui-pr-10{padding-right:var(--bui-space-10)}.md\:bui-pr-11{padding-right:var(--bui-space-11)}.md\:bui-pr-12{padding-right:var(--bui-space-12)}.md\:bui-pr-13{padding-right:var(--bui-space-13)}.md\:bui-pr-14{padding-right:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-pr{padding-right:var(--pr-lg)}.lg\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.lg\:bui-pr-1{padding-right:var(--bui-space-1)}.lg\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.lg\:bui-pr-2{padding-right:var(--bui-space-2)}.lg\:bui-pr-3{padding-right:var(--bui-space-3)}.lg\:bui-pr-4{padding-right:var(--bui-space-4)}.lg\:bui-pr-5{padding-right:var(--bui-space-5)}.lg\:bui-pr-6{padding-right:var(--bui-space-6)}.lg\:bui-pr-7{padding-right:var(--bui-space-7)}.lg\:bui-pr-8{padding-right:var(--bui-space-8)}.lg\:bui-pr-9{padding-right:var(--bui-space-9)}.lg\:bui-pr-10{padding-right:var(--bui-space-10)}.lg\:bui-pr-11{padding-right:var(--bui-space-11)}.lg\:bui-pr-12{padding-right:var(--bui-space-12)}.lg\:bui-pr-13{padding-right:var(--bui-space-13)}.lg\:bui-pr-14{padding-right:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-pr{padding-right:var(--pr-xl)}.xl\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.xl\:bui-pr-1{padding-right:var(--bui-space-1)}.xl\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.xl\:bui-pr-2{padding-right:var(--bui-space-2)}.xl\:bui-pr-3{padding-right:var(--bui-space-3)}.xl\:bui-pr-4{padding-right:var(--bui-space-4)}.xl\:bui-pr-5{padding-right:var(--bui-space-5)}.xl\:bui-pr-6{padding-right:var(--bui-space-6)}.xl\:bui-pr-7{padding-right:var(--bui-space-7)}.xl\:bui-pr-8{padding-right:var(--bui-space-8)}.xl\:bui-pr-9{padding-right:var(--bui-space-9)}.xl\:bui-pr-10{padding-right:var(--bui-space-10)}.xl\:bui-pr-11{padding-right:var(--bui-space-11)}.xl\:bui-pr-12{padding-right:var(--bui-space-12)}.xl\:bui-pr-13{padding-right:var(--bui-space-13)}.xl\:bui-pr-14{padding-right:var(--bui-space-14)}}.bui-pt{padding-top:var(--pt)}.bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.bui-pt-1{padding-top:var(--bui-space-1)}.bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.bui-pt-2{padding-top:var(--bui-space-2)}.bui-pt-3{padding-top:var(--bui-space-3)}.bui-pt-4{padding-top:var(--bui-space-4)}.bui-pt-5{padding-top:var(--bui-space-5)}.bui-pt-6{padding-top:var(--bui-space-6)}.bui-pt-7{padding-top:var(--bui-space-7)}.bui-pt-8{padding-top:var(--bui-space-8)}.bui-pt-9{padding-top:var(--bui-space-9)}.bui-pt-10{padding-top:var(--bui-space-10)}.bui-pt-11{padding-top:var(--bui-space-11)}.bui-pt-12{padding-top:var(--bui-space-12)}.bui-pt-13{padding-top:var(--bui-space-13)}.bui-pt-14{padding-top:var(--bui-space-14)}@media (width>=640px){.xs\:bui-pt{padding-top:var(--pt-xs)}.xs\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.xs\:bui-pt-1{padding-top:var(--bui-space-1)}.xs\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.xs\:bui-pt-2{padding-top:var(--bui-space-2)}.xs\:bui-pt-3{padding-top:var(--bui-space-3)}.xs\:bui-pt-4{padding-top:var(--bui-space-4)}.xs\:bui-pt-5{padding-top:var(--bui-space-5)}.xs\:bui-pt-6{padding-top:var(--bui-space-6)}.xs\:bui-pt-7{padding-top:var(--bui-space-7)}.xs\:bui-pt-8{padding-top:var(--bui-space-8)}.xs\:bui-pt-9{padding-top:var(--bui-space-9)}.xs\:bui-pt-10{padding-top:var(--bui-space-10)}.xs\:bui-pt-11{padding-top:var(--bui-space-11)}.xs\:bui-pt-12{padding-top:var(--bui-space-12)}.xs\:bui-pt-13{padding-top:var(--bui-space-13)}.xs\:bui-pt-14{padding-top:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-pt{padding-top:var(--pt-sm)}.sm\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.sm\:bui-pt-1{padding-top:var(--bui-space-1)}.sm\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.sm\:bui-pt-2{padding-top:var(--bui-space-2)}.sm\:bui-pt-3{padding-top:var(--bui-space-3)}.sm\:bui-pt-4{padding-top:var(--bui-space-4)}.sm\:bui-pt-5{padding-top:var(--bui-space-5)}.sm\:bui-pt-6{padding-top:var(--bui-space-6)}.sm\:bui-pt-7{padding-top:var(--bui-space-7)}.sm\:bui-pt-8{padding-top:var(--bui-space-8)}.sm\:bui-pt-9{padding-top:var(--bui-space-9)}.sm\:bui-pt-10{padding-top:var(--bui-space-10)}.sm\:bui-pt-11{padding-top:var(--bui-space-11)}.sm\:bui-pt-12{padding-top:var(--bui-space-12)}.sm\:bui-pt-13{padding-top:var(--bui-space-13)}.sm\:bui-pt-14{padding-top:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-pt{padding-top:var(--pt-md)}.md\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.md\:bui-pt-1{padding-top:var(--bui-space-1)}.md\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.md\:bui-pt-2{padding-top:var(--bui-space-2)}.md\:bui-pt-3{padding-top:var(--bui-space-3)}.md\:bui-pt-4{padding-top:var(--bui-space-4)}.md\:bui-pt-5{padding-top:var(--bui-space-5)}.md\:bui-pt-6{padding-top:var(--bui-space-6)}.md\:bui-pt-7{padding-top:var(--bui-space-7)}.md\:bui-pt-8{padding-top:var(--bui-space-8)}.md\:bui-pt-9{padding-top:var(--bui-space-9)}.md\:bui-pt-10{padding-top:var(--bui-space-10)}.md\:bui-pt-11{padding-top:var(--bui-space-11)}.md\:bui-pt-12{padding-top:var(--bui-space-12)}.md\:bui-pt-13{padding-top:var(--bui-space-13)}.md\:bui-pt-14{padding-top:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-pt{padding-top:var(--pt-lg)}.lg\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.lg\:bui-pt-1{padding-top:var(--bui-space-1)}.lg\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.lg\:bui-pt-2{padding-top:var(--bui-space-2)}.lg\:bui-pt-3{padding-top:var(--bui-space-3)}.lg\:bui-pt-4{padding-top:var(--bui-space-4)}.lg\:bui-pt-5{padding-top:var(--bui-space-5)}.lg\:bui-pt-6{padding-top:var(--bui-space-6)}.lg\:bui-pt-7{padding-top:var(--bui-space-7)}.lg\:bui-pt-8{padding-top:var(--bui-space-8)}.lg\:bui-pt-9{padding-top:var(--bui-space-9)}.lg\:bui-pt-10{padding-top:var(--bui-space-10)}.lg\:bui-pt-11{padding-top:var(--bui-space-11)}.lg\:bui-pt-12{padding-top:var(--bui-space-12)}.lg\:bui-pt-13{padding-top:var(--bui-space-13)}.lg\:bui-pt-14{padding-top:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-pt{padding-top:var(--pt-xl)}.xl\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.xl\:bui-pt-1{padding-top:var(--bui-space-1)}.xl\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.xl\:bui-pt-2{padding-top:var(--bui-space-2)}.xl\:bui-pt-3{padding-top:var(--bui-space-3)}.xl\:bui-pt-4{padding-top:var(--bui-space-4)}.xl\:bui-pt-5{padding-top:var(--bui-space-5)}.xl\:bui-pt-6{padding-top:var(--bui-space-6)}.xl\:bui-pt-7{padding-top:var(--bui-space-7)}.xl\:bui-pt-8{padding-top:var(--bui-space-8)}.xl\:bui-pt-9{padding-top:var(--bui-space-9)}.xl\:bui-pt-10{padding-top:var(--bui-space-10)}.xl\:bui-pt-11{padding-top:var(--bui-space-11)}.xl\:bui-pt-12{padding-top:var(--bui-space-12)}.xl\:bui-pt-13{padding-top:var(--bui-space-13)}.xl\:bui-pt-14{padding-top:var(--bui-space-14)}}.bui-pb{padding-bottom:var(--pb)}.bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.bui-pb-1{padding-bottom:var(--bui-space-1)}.bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.bui-pb-2{padding-bottom:var(--bui-space-2)}.bui-pb-3{padding-bottom:var(--bui-space-3)}.bui-pb-4{padding-bottom:var(--bui-space-4)}.bui-pb-5{padding-bottom:var(--bui-space-5)}.bui-pb-6{padding-bottom:var(--bui-space-6)}.bui-pb-7{padding-bottom:var(--bui-space-7)}.bui-pb-8{padding-bottom:var(--bui-space-8)}.bui-pb-9{padding-bottom:var(--bui-space-9)}.bui-pb-10{padding-bottom:var(--bui-space-10)}.bui-pb-11{padding-bottom:var(--bui-space-11)}.bui-pb-12{padding-bottom:var(--bui-space-12)}.bui-pb-13{padding-bottom:var(--bui-space-13)}.bui-pb-14{padding-bottom:var(--bui-space-14)}@media (width>=640px){.xs\:bui-pb{padding-bottom:var(--pb-xs)}.xs\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.xs\:bui-pb-1{padding-bottom:var(--bui-space-1)}.xs\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.xs\:bui-pb-2{padding-bottom:var(--bui-space-2)}.xs\:bui-pb-3{padding-bottom:var(--bui-space-3)}.xs\:bui-pb-4{padding-bottom:var(--bui-space-4)}.xs\:bui-pb-5{padding-bottom:var(--bui-space-5)}.xs\:bui-pb-6{padding-bottom:var(--bui-space-6)}.xs\:bui-pb-7{padding-bottom:var(--bui-space-7)}.xs\:bui-pb-8{padding-bottom:var(--bui-space-8)}.xs\:bui-pb-9{padding-bottom:var(--bui-space-9)}.xs\:bui-pb-10{padding-bottom:var(--bui-space-10)}.xs\:bui-pb-11{padding-bottom:var(--bui-space-11)}.xs\:bui-pb-12{padding-bottom:var(--bui-space-12)}.xs\:bui-pb-13{padding-bottom:var(--bui-space-13)}.xs\:bui-pb-14{padding-bottom:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-pb{padding-bottom:var(--pb-sm)}.sm\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.sm\:bui-pb-1{padding-bottom:var(--bui-space-1)}.sm\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.sm\:bui-pb-2{padding-bottom:var(--bui-space-2)}.sm\:bui-pb-3{padding-bottom:var(--bui-space-3)}.sm\:bui-pb-4{padding-bottom:var(--bui-space-4)}.sm\:bui-pb-5{padding-bottom:var(--bui-space-5)}.sm\:bui-pb-6{padding-bottom:var(--bui-space-6)}.sm\:bui-pb-7{padding-bottom:var(--bui-space-7)}.sm\:bui-pb-8{padding-bottom:var(--bui-space-8)}.sm\:bui-pb-9{padding-bottom:var(--bui-space-9)}.sm\:bui-pb-10{padding-bottom:var(--bui-space-10)}.sm\:bui-pb-11{padding-bottom:var(--bui-space-11)}.sm\:bui-pb-12{padding-bottom:var(--bui-space-12)}.sm\:bui-pb-13{padding-bottom:var(--bui-space-13)}.sm\:bui-pb-14{padding-bottom:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-pb{padding-bottom:var(--pb-md)}.md\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.md\:bui-pb-1{padding-bottom:var(--bui-space-1)}.md\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.md\:bui-pb-2{padding-bottom:var(--bui-space-2)}.md\:bui-pb-3{padding-bottom:var(--bui-space-3)}.md\:bui-pb-4{padding-bottom:var(--bui-space-4)}.md\:bui-pb-5{padding-bottom:var(--bui-space-5)}.md\:bui-pb-6{padding-bottom:var(--bui-space-6)}.md\:bui-pb-7{padding-bottom:var(--bui-space-7)}.md\:bui-pb-8{padding-bottom:var(--bui-space-8)}.md\:bui-pb-9{padding-bottom:var(--bui-space-9)}.md\:bui-pb-10{padding-bottom:var(--bui-space-10)}.md\:bui-pb-11{padding-bottom:var(--bui-space-11)}.md\:bui-pb-12{padding-bottom:var(--bui-space-12)}.md\:bui-pb-13{padding-bottom:var(--bui-space-13)}.md\:bui-pb-14{padding-bottom:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-pb{padding-bottom:var(--pb-lg)}.lg\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.lg\:bui-pb-1{padding-bottom:var(--bui-space-1)}.lg\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.lg\:bui-pb-2{padding-bottom:var(--bui-space-2)}.lg\:bui-pb-3{padding-bottom:var(--bui-space-3)}.lg\:bui-pb-4{padding-bottom:var(--bui-space-4)}.lg\:bui-pb-5{padding-bottom:var(--bui-space-5)}.lg\:bui-pb-6{padding-bottom:var(--bui-space-6)}.lg\:bui-pb-7{padding-bottom:var(--bui-space-7)}.lg\:bui-pb-8{padding-bottom:var(--bui-space-8)}.lg\:bui-pb-9{padding-bottom:var(--bui-space-9)}.lg\:bui-pb-10{padding-bottom:var(--bui-space-10)}.lg\:bui-pb-11{padding-bottom:var(--bui-space-11)}.lg\:bui-pb-12{padding-bottom:var(--bui-space-12)}.lg\:bui-pb-13{padding-bottom:var(--bui-space-13)}.lg\:bui-pb-14{padding-bottom:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-pb{padding-bottom:var(--pb-xl)}.xl\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.xl\:bui-pb-1{padding-bottom:var(--bui-space-1)}.xl\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.xl\:bui-pb-2{padding-bottom:var(--bui-space-2)}.xl\:bui-pb-3{padding-bottom:var(--bui-space-3)}.xl\:bui-pb-4{padding-bottom:var(--bui-space-4)}.xl\:bui-pb-5{padding-bottom:var(--bui-space-5)}.xl\:bui-pb-6{padding-bottom:var(--bui-space-6)}.xl\:bui-pb-7{padding-bottom:var(--bui-space-7)}.xl\:bui-pb-8{padding-bottom:var(--bui-space-8)}.xl\:bui-pb-9{padding-bottom:var(--bui-space-9)}.xl\:bui-pb-10{padding-bottom:var(--bui-space-10)}.xl\:bui-pb-11{padding-bottom:var(--bui-space-11)}.xl\:bui-pb-12{padding-bottom:var(--bui-space-12)}.xl\:bui-pb-13{padding-bottom:var(--bui-space-13)}.xl\:bui-pb-14{padding-bottom:var(--bui-space-14)}}.bui-py{padding-top:var(--py);padding-bottom:var(--py)}.bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}@media (width>=640px){.xs\:bui-py{padding-top:var(--py-xs);padding-bottom:var(--py-xs)}.xs\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.xs\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.xs\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.xs\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.xs\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.xs\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.xs\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.xs\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.xs\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.xs\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.xs\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.xs\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.xs\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.xs\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.xs\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.xs\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-py{padding-top:var(--py-sm);padding-bottom:var(--py-sm)}.sm\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.sm\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.sm\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.sm\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.sm\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.sm\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.sm\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.sm\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.sm\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.sm\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.sm\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.sm\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.sm\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.sm\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.sm\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.sm\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-py{padding-top:var(--py-md);padding-bottom:var(--py-md)}.md\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.md\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.md\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.md\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.md\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.md\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.md\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.md\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.md\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.md\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.md\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.md\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.md\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.md\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.md\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.md\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-py{padding-top:var(--py-lg);padding-bottom:var(--py-lg)}.lg\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.lg\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.lg\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.lg\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.lg\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.lg\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.lg\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.lg\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.lg\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.lg\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.lg\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.lg\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.lg\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.lg\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.lg\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.lg\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-py{padding-top:var(--py-xl);padding-bottom:var(--py-xl)}.xl\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.xl\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.xl\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.xl\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.xl\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.xl\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.xl\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.xl\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.xl\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.xl\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.xl\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.xl\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.xl\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.xl\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.xl\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.xl\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}.bui-px{padding-left:var(--px);padding-right:var(--px)}.bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}@media (width>=640px){.xs\:bui-px{padding-left:var(--px-xs);padding-right:var(--px-xs)}.xs\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.xs\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.xs\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.xs\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.xs\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.xs\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.xs\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.xs\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.xs\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.xs\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.xs\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.xs\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.xs\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.xs\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.xs\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.xs\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-px{padding-left:var(--px-sm);padding-right:var(--px-sm)}.sm\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.sm\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.sm\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.sm\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.sm\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.sm\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.sm\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.sm\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.sm\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.sm\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.sm\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.sm\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.sm\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.sm\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.sm\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.sm\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-px{padding-left:var(--px-md);padding-right:var(--px-md)}.md\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.md\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.md\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.md\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.md\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.md\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.md\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.md\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.md\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.md\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.md\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.md\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.md\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.md\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.md\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.md\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-px{padding-left:var(--px-lg);padding-right:var(--px-lg)}.lg\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.lg\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.lg\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.lg\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.lg\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.lg\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.lg\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.lg\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.lg\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.lg\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.lg\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.lg\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.lg\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.lg\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.lg\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.lg\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-px{padding-left:var(--px-xl);padding-right:var(--px-xl)}.xl\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.xl\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.xl\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.xl\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.xl\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.xl\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.xl\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.xl\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.xl\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.xl\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.xl\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.xl\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.xl\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.xl\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.xl\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.xl\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}.bui-m{margin:var(--m)}.bui-m-0\.5{margin:var(--bui-space-0_5)}.bui-m-1{margin:var(--bui-space-1)}.bui-m-1\.5{margin:var(--bui-space-1_5)}.bui-m-2{margin:var(--bui-space-2)}.bui-m-3{margin:var(--bui-space-3)}.bui-m-4{margin:var(--bui-space-4)}.bui-m-5{margin:var(--bui-space-5)}.bui-m-6{margin:var(--bui-space-6)}.bui-m-7{margin:var(--bui-space-7)}.bui-m-8{margin:var(--bui-space-8)}.bui-m-9{margin:var(--bui-space-9)}.bui-m-10{margin:var(--bui-space-10)}.bui-m-11{margin:var(--bui-space-11)}.bui-m-12{margin:var(--bui-space-12)}.bui-m-13{margin:var(--bui-space-13)}.bui-m-14{margin:var(--bui-space-14)}@media (width>=640px){.xs\:bui-m{margin:var(--p-xs)}.xs\:bui-m-0\.5{margin:var(--bui-space-0_5)}.xs\:bui-m-1{margin:var(--bui-space-1)}.xs\:bui-m-1\.5{margin:var(--bui-space-1_5)}.xs\:bui-m-2{margin:var(--bui-space-2)}.xs\:bui-m-3{margin:var(--bui-space-3)}.xs\:bui-m-4{margin:var(--bui-space-4)}.xs\:bui-m-5{margin:var(--bui-space-5)}.xs\:bui-m-6{margin:var(--bui-space-6)}.xs\:bui-m-7{margin:var(--bui-space-7)}.xs\:bui-m-8{margin:var(--bui-space-8)}.xs\:bui-m-9{margin:var(--bui-space-9)}.xs\:bui-m-10{margin:var(--bui-space-10)}.xs\:bui-m-11{margin:var(--bui-space-11)}.xs\:bui-m-12{margin:var(--bui-space-12)}.xs\:bui-m-13{margin:var(--bui-space-13)}.xs\:bui-m-14{margin:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-m{margin:var(--p-sm)}.sm\:bui-m-0\.5{margin:var(--bui-space-0_5)}.sm\:bui-m-1{margin:var(--bui-space-1)}.sm\:bui-m-1\.5{margin:var(--bui-space-1_5)}.sm\:bui-m-2{margin:var(--bui-space-2)}.sm\:bui-m-3{margin:var(--bui-space-3)}.sm\:bui-m-4{margin:var(--bui-space-4)}.sm\:bui-m-5{margin:var(--bui-space-5)}.sm\:bui-m-6{margin:var(--bui-space-6)}.sm\:bui-m-7{margin:var(--bui-space-7)}.sm\:bui-m-8{margin:var(--bui-space-8)}.sm\:bui-m-9{margin:var(--bui-space-9)}.sm\:bui-m-10{margin:var(--bui-space-10)}.sm\:bui-m-11{margin:var(--bui-space-11)}.sm\:bui-m-12{margin:var(--bui-space-12)}.sm\:bui-m-13{margin:var(--bui-space-13)}.sm\:bui-m-14{margin:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-m{margin:var(--p-md)}.md\:bui-m-0\.5{margin:var(--bui-space-0_5)}.md\:bui-m-1{margin:var(--bui-space-1)}.md\:bui-m-1\.5{margin:var(--bui-space-1_5)}.md\:bui-m-2{margin:var(--bui-space-2)}.md\:bui-m-3{margin:var(--bui-space-3)}.md\:bui-m-4{margin:var(--bui-space-4)}.md\:bui-m-5{margin:var(--bui-space-5)}.md\:bui-m-6{margin:var(--bui-space-6)}.md\:bui-m-7{margin:var(--bui-space-7)}.md\:bui-m-8{margin:var(--bui-space-8)}.md\:bui-m-9{margin:var(--bui-space-9)}.md\:bui-m-10{margin:var(--bui-space-10)}.md\:bui-m-11{margin:var(--bui-space-11)}.md\:bui-m-12{margin:var(--bui-space-12)}.md\:bui-m-13{margin:var(--bui-space-13)}.md\:bui-m-14{margin:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-m{margin:var(--p-lg)}.lg\:bui-m-0\.5{margin:var(--bui-space-0_5)}.lg\:bui-m-1{margin:var(--bui-space-1)}.lg\:bui-m-1\.5{margin:var(--bui-space-1_5)}.lg\:bui-m-2{margin:var(--bui-space-2)}.lg\:bui-m-3{margin:var(--bui-space-3)}.lg\:bui-m-4{margin:var(--bui-space-4)}.lg\:bui-m-5{margin:var(--bui-space-5)}.lg\:bui-m-6{margin:var(--bui-space-6)}.lg\:bui-m-7{margin:var(--bui-space-7)}.lg\:bui-m-8{margin:var(--bui-space-8)}.lg\:bui-m-9{margin:var(--bui-space-9)}.lg\:bui-m-10{margin:var(--bui-space-10)}.lg\:bui-m-11{margin:var(--bui-space-11)}.lg\:bui-m-12{margin:var(--bui-space-12)}.lg\:bui-m-13{margin:var(--bui-space-13)}.lg\:bui-m-14{margin:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-m{margin:var(--p-xl)}.xl\:bui-m-0\.5{margin:var(--bui-space-0_5)}.xl\:bui-m-1{margin:var(--bui-space-1)}.xl\:bui-m-1\.5{margin:var(--bui-space-1_5)}.xl\:bui-m-2{margin:var(--bui-space-2)}.xl\:bui-m-3{margin:var(--bui-space-3)}.xl\:bui-m-4{margin:var(--bui-space-4)}.xl\:bui-m-5{margin:var(--bui-space-5)}.xl\:bui-m-6{margin:var(--bui-space-6)}.xl\:bui-m-7{margin:var(--bui-space-7)}.xl\:bui-m-8{margin:var(--bui-space-8)}.xl\:bui-m-9{margin:var(--bui-space-9)}.xl\:bui-m-10{margin:var(--bui-space-10)}.xl\:bui-m-11{margin:var(--bui-space-11)}.xl\:bui-m-12{margin:var(--bui-space-12)}.xl\:bui-m-13{margin:var(--bui-space-13)}.xl\:bui-m-14{margin:var(--bui-space-14)}}.bui-ml{margin-left:var(--ml)}.bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.bui-ml-1{margin-left:var(--bui-space-1)}.bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.bui-ml-2{margin-left:var(--bui-space-2)}.bui-ml-3{margin-left:var(--bui-space-3)}.bui-ml-4{margin-left:var(--bui-space-4)}.bui-ml-5{margin-left:var(--bui-space-5)}.bui-ml-6{margin-left:var(--bui-space-6)}.bui-ml-7{margin-left:var(--bui-space-7)}.bui-ml-8{margin-left:var(--bui-space-8)}.bui-ml-9{margin-left:var(--bui-space-9)}.bui-ml-10{margin-left:var(--bui-space-10)}.bui-ml-11{margin-left:var(--bui-space-11)}.bui-ml-12{margin-left:var(--bui-space-12)}.bui-ml-13{margin-left:var(--bui-space-13)}.bui-ml-14{margin-left:var(--bui-space-14)}@media (width>=640px){.xs\:bui-ml{margin-left:var(--ml-xs)}.xs\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.xs\:bui-ml-1{margin-left:var(--bui-space-1)}.xs\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.xs\:bui-ml-2{margin-left:var(--bui-space-2)}.xs\:bui-ml-3{margin-left:var(--bui-space-3)}.xs\:bui-ml-4{margin-left:var(--bui-space-4)}.xs\:bui-ml-5{margin-left:var(--bui-space-5)}.xs\:bui-ml-6{margin-left:var(--bui-space-6)}.xs\:bui-ml-7{margin-left:var(--bui-space-7)}.xs\:bui-ml-8{margin-left:var(--bui-space-8)}.xs\:bui-ml-9{margin-left:var(--bui-space-9)}.xs\:bui-ml-10{margin-left:var(--bui-space-10)}.xs\:bui-ml-11{margin-left:var(--bui-space-11)}.xs\:bui-ml-12{margin-left:var(--bui-space-12)}.xs\:bui-ml-13{margin-left:var(--bui-space-13)}.xs\:bui-ml-14{margin-left:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-ml{margin-left:var(--ml-sm)}.sm\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.sm\:bui-ml-1{margin-left:var(--bui-space-1)}.sm\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.sm\:bui-ml-2{margin-left:var(--bui-space-2)}.sm\:bui-ml-3{margin-left:var(--bui-space-3)}.sm\:bui-ml-4{margin-left:var(--bui-space-4)}.sm\:bui-ml-5{margin-left:var(--bui-space-5)}.sm\:bui-ml-6{margin-left:var(--bui-space-6)}.sm\:bui-ml-7{margin-left:var(--bui-space-7)}.sm\:bui-ml-8{margin-left:var(--bui-space-8)}.sm\:bui-ml-9{margin-left:var(--bui-space-9)}.sm\:bui-ml-10{margin-left:var(--bui-space-10)}.sm\:bui-ml-11{margin-left:var(--bui-space-11)}.sm\:bui-ml-12{margin-left:var(--bui-space-12)}.sm\:bui-ml-13{margin-left:var(--bui-space-13)}.sm\:bui-ml-14{margin-left:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-ml{margin-left:var(--ml-md)}.md\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.md\:bui-ml-1{margin-left:var(--bui-space-1)}.md\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.md\:bui-ml-2{margin-left:var(--bui-space-2)}.md\:bui-ml-3{margin-left:var(--bui-space-3)}.md\:bui-ml-4{margin-left:var(--bui-space-4)}.md\:bui-ml-5{margin-left:var(--bui-space-5)}.md\:bui-ml-6{margin-left:var(--bui-space-6)}.md\:bui-ml-7{margin-left:var(--bui-space-7)}.md\:bui-ml-8{margin-left:var(--bui-space-8)}.md\:bui-ml-9{margin-left:var(--bui-space-9)}.md\:bui-ml-10{margin-left:var(--bui-space-10)}.md\:bui-ml-11{margin-left:var(--bui-space-11)}.md\:bui-ml-12{margin-left:var(--bui-space-12)}.md\:bui-ml-13{margin-left:var(--bui-space-13)}.md\:bui-ml-14{margin-left:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-ml{margin-left:var(--ml-lg)}.lg\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.lg\:bui-ml-1{margin-left:var(--bui-space-1)}.lg\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.lg\:bui-ml-2{margin-left:var(--bui-space-2)}.lg\:bui-ml-3{margin-left:var(--bui-space-3)}.lg\:bui-ml-4{margin-left:var(--bui-space-4)}.lg\:bui-ml-5{margin-left:var(--bui-space-5)}.lg\:bui-ml-6{margin-left:var(--bui-space-6)}.lg\:bui-ml-7{margin-left:var(--bui-space-7)}.lg\:bui-ml-8{margin-left:var(--bui-space-8)}.lg\:bui-ml-9{margin-left:var(--bui-space-9)}.lg\:bui-ml-10{margin-left:var(--bui-space-10)}.lg\:bui-ml-11{margin-left:var(--bui-space-11)}.lg\:bui-ml-12{margin-left:var(--bui-space-12)}.lg\:bui-ml-13{margin-left:var(--bui-space-13)}.lg\:bui-ml-14{margin-left:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-ml{margin-left:var(--ml-xl)}.xl\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.xl\:bui-ml-1{margin-left:var(--bui-space-1)}.xl\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.xl\:bui-ml-2{margin-left:var(--bui-space-2)}.xl\:bui-ml-3{margin-left:var(--bui-space-3)}.xl\:bui-ml-4{margin-left:var(--bui-space-4)}.xl\:bui-ml-5{margin-left:var(--bui-space-5)}.xl\:bui-ml-6{margin-left:var(--bui-space-6)}.xl\:bui-ml-7{margin-left:var(--bui-space-7)}.xl\:bui-ml-8{margin-left:var(--bui-space-8)}.xl\:bui-ml-9{margin-left:var(--bui-space-9)}.xl\:bui-ml-10{margin-left:var(--bui-space-10)}.xl\:bui-ml-11{margin-left:var(--bui-space-11)}.xl\:bui-ml-12{margin-left:var(--bui-space-12)}.xl\:bui-ml-13{margin-left:var(--bui-space-13)}.xl\:bui-ml-14{margin-left:var(--bui-space-14)}}.bui-mr{margin-right:var(--mr)}.bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.bui-mr-1{margin-right:var(--bui-space-1)}.bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.bui-mr-2{margin-right:var(--bui-space-2)}.bui-mr-3{margin-right:var(--bui-space-3)}.bui-mr-4{margin-right:var(--bui-space-4)}.bui-mr-5{margin-right:var(--bui-space-5)}.bui-mr-6{margin-right:var(--bui-space-6)}.bui-mr-7{margin-right:var(--bui-space-7)}.bui-mr-8{margin-right:var(--bui-space-8)}.bui-mr-9{margin-right:var(--bui-space-9)}.bui-mr-10{margin-right:var(--bui-space-10)}.bui-mr-11{margin-right:var(--bui-space-11)}.bui-mr-12{margin-right:var(--bui-space-12)}.bui-mr-13{margin-right:var(--bui-space-13)}.bui-mr-14{margin-right:var(--bui-space-14)}@media (width>=640px){.xs\:bui-mr{margin-right:var(--mr-xs)}.xs\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.xs\:bui-mr-1{margin-right:var(--bui-space-1)}.xs\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.xs\:bui-mr-2{margin-right:var(--bui-space-2)}.xs\:bui-mr-3{margin-right:var(--bui-space-3)}.xs\:bui-mr-4{margin-right:var(--bui-space-4)}.xs\:bui-mr-5{margin-right:var(--bui-space-5)}.xs\:bui-mr-6{margin-right:var(--bui-space-6)}.xs\:bui-mr-7{margin-right:var(--bui-space-7)}.xs\:bui-mr-8{margin-right:var(--bui-space-8)}.xs\:bui-mr-9{margin-right:var(--bui-space-9)}.xs\:bui-mr-10{margin-right:var(--bui-space-10)}.xs\:bui-mr-11{margin-right:var(--bui-space-11)}.xs\:bui-mr-12{margin-right:var(--bui-space-12)}.xs\:bui-mr-13{margin-right:var(--bui-space-13)}.xs\:bui-mr-14{margin-right:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-mr{margin-right:var(--mr-sm)}.sm\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.sm\:bui-mr-1{margin-right:var(--bui-space-1)}.sm\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.sm\:bui-mr-2{margin-right:var(--bui-space-2)}.sm\:bui-mr-3{margin-right:var(--bui-space-3)}.sm\:bui-mr-4{margin-right:var(--bui-space-4)}.sm\:bui-mr-5{margin-right:var(--bui-space-5)}.sm\:bui-mr-6{margin-right:var(--bui-space-6)}.sm\:bui-mr-7{margin-right:var(--bui-space-7)}.sm\:bui-mr-8{margin-right:var(--bui-space-8)}.sm\:bui-mr-9{margin-right:var(--bui-space-9)}.sm\:bui-mr-10{margin-right:var(--bui-space-10)}.sm\:bui-mr-11{margin-right:var(--bui-space-11)}.sm\:bui-mr-12{margin-right:var(--bui-space-12)}.sm\:bui-mr-13{margin-right:var(--bui-space-13)}.sm\:bui-mr-14{margin-right:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-mr{margin-right:var(--mr-md)}.md\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.md\:bui-mr-1{margin-right:var(--bui-space-1)}.md\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.md\:bui-mr-2{margin-right:var(--bui-space-2)}.md\:bui-mr-3{margin-right:var(--bui-space-3)}.md\:bui-mr-4{margin-right:var(--bui-space-4)}.md\:bui-mr-5{margin-right:var(--bui-space-5)}.md\:bui-mr-6{margin-right:var(--bui-space-6)}.md\:bui-mr-7{margin-right:var(--bui-space-7)}.md\:bui-mr-8{margin-right:var(--bui-space-8)}.md\:bui-mr-9{margin-right:var(--bui-space-9)}.md\:bui-mr-10{margin-right:var(--bui-space-10)}.md\:bui-mr-11{margin-right:var(--bui-space-11)}.md\:bui-mr-12{margin-right:var(--bui-space-12)}.md\:bui-mr-13{margin-right:var(--bui-space-13)}.md\:bui-mr-14{margin-right:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-mr{margin-right:var(--mr-lg)}.lg\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.lg\:bui-mr-1{margin-right:var(--bui-space-1)}.lg\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.lg\:bui-mr-2{margin-right:var(--bui-space-2)}.lg\:bui-mr-3{margin-right:var(--bui-space-3)}.lg\:bui-mr-4{margin-right:var(--bui-space-4)}.lg\:bui-mr-5{margin-right:var(--bui-space-5)}.lg\:bui-mr-6{margin-right:var(--bui-space-6)}.lg\:bui-mr-7{margin-right:var(--bui-space-7)}.lg\:bui-mr-8{margin-right:var(--bui-space-8)}.lg\:bui-mr-9{margin-right:var(--bui-space-9)}.lg\:bui-mr-10{margin-right:var(--bui-space-10)}.lg\:bui-mr-11{margin-right:var(--bui-space-11)}.lg\:bui-mr-12{margin-right:var(--bui-space-12)}.lg\:bui-mr-13{margin-right:var(--bui-space-13)}.lg\:bui-mr-14{margin-right:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-mr{margin-right:var(--mr-xl)}.xl\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.xl\:bui-mr-1{margin-right:var(--bui-space-1)}.xl\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.xl\:bui-mr-2{margin-right:var(--bui-space-2)}.xl\:bui-mr-3{margin-right:var(--bui-space-3)}.xl\:bui-mr-4{margin-right:var(--bui-space-4)}.xl\:bui-mr-5{margin-right:var(--bui-space-5)}.xl\:bui-mr-6{margin-right:var(--bui-space-6)}.xl\:bui-mr-7{margin-right:var(--bui-space-7)}.xl\:bui-mr-8{margin-right:var(--bui-space-8)}.xl\:bui-mr-9{margin-right:var(--bui-space-9)}.xl\:bui-mr-10{margin-right:var(--bui-space-10)}.xl\:bui-mr-11{margin-right:var(--bui-space-11)}.xl\:bui-mr-12{margin-right:var(--bui-space-12)}.xl\:bui-mr-13{margin-right:var(--bui-space-13)}.xl\:bui-mr-14{margin-right:var(--bui-space-14)}}.bui-mt{margin-top:var(--mt)}.bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.bui-mt-1{margin-top:var(--bui-space-1)}.bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.bui-mt-2{margin-top:var(--bui-space-2)}.bui-mt-3{margin-top:var(--bui-space-3)}.bui-mt-4{margin-top:var(--bui-space-4)}.bui-mt-5{margin-top:var(--bui-space-5)}.bui-mt-6{margin-top:var(--bui-space-6)}.bui-mt-7{margin-top:var(--bui-space-7)}.bui-mt-8{margin-top:var(--bui-space-8)}.bui-mt-9{margin-top:var(--bui-space-9)}.bui-mt-10{margin-top:var(--bui-space-10)}.bui-mt-11{margin-top:var(--bui-space-11)}.bui-mt-12{margin-top:var(--bui-space-12)}.bui-mt-13{margin-top:var(--bui-space-13)}.bui-mt-14{margin-top:var(--bui-space-14)}@media (width>=640px){.xs\:bui-mt{margin-top:var(--mt-xs)}.xs\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.xs\:bui-mt-1{margin-top:var(--bui-space-1)}.xs\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.xs\:bui-mt-2{margin-top:var(--bui-space-2)}.xs\:bui-mt-3{margin-top:var(--bui-space-3)}.xs\:bui-mt-4{margin-top:var(--bui-space-4)}.xs\:bui-mt-5{margin-top:var(--bui-space-5)}.xs\:bui-mt-6{margin-top:var(--bui-space-6)}.xs\:bui-mt-7{margin-top:var(--bui-space-7)}.xs\:bui-mt-8{margin-top:var(--bui-space-8)}.xs\:bui-mt-9{margin-top:var(--bui-space-9)}.xs\:bui-mt-10{margin-top:var(--bui-space-10)}.xs\:bui-mt-11{margin-top:var(--bui-space-11)}.xs\:bui-mt-12{margin-top:var(--bui-space-12)}.xs\:bui-mt-13{margin-top:var(--bui-space-13)}.xs\:bui-mt-14{margin-top:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-mt{margin-top:var(--mt-sm)}.sm\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.sm\:bui-mt-1{margin-top:var(--bui-space-1)}.sm\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.sm\:bui-mt-2{margin-top:var(--bui-space-2)}.sm\:bui-mt-3{margin-top:var(--bui-space-3)}.sm\:bui-mt-4{margin-top:var(--bui-space-4)}.sm\:bui-mt-5{margin-top:var(--bui-space-5)}.sm\:bui-mt-6{margin-top:var(--bui-space-6)}.sm\:bui-mt-7{margin-top:var(--bui-space-7)}.sm\:bui-mt-8{margin-top:var(--bui-space-8)}.sm\:bui-mt-9{margin-top:var(--bui-space-9)}.sm\:bui-mt-10{margin-top:var(--bui-space-10)}.sm\:bui-mt-11{margin-top:var(--bui-space-11)}.sm\:bui-mt-12{margin-top:var(--bui-space-12)}.sm\:bui-mt-13{margin-top:var(--bui-space-13)}.sm\:bui-mt-14{margin-top:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-mt{margin-top:var(--mt-md)}.md\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.md\:bui-mt-1{margin-top:var(--bui-space-1)}.md\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.md\:bui-mt-2{margin-top:var(--bui-space-2)}.md\:bui-mt-3{margin-top:var(--bui-space-3)}.md\:bui-mt-4{margin-top:var(--bui-space-4)}.md\:bui-mt-5{margin-top:var(--bui-space-5)}.md\:bui-mt-6{margin-top:var(--bui-space-6)}.md\:bui-mt-7{margin-top:var(--bui-space-7)}.md\:bui-mt-8{margin-top:var(--bui-space-8)}.md\:bui-mt-9{margin-top:var(--bui-space-9)}.md\:bui-mt-10{margin-top:var(--bui-space-10)}.md\:bui-mt-11{margin-top:var(--bui-space-11)}.md\:bui-mt-12{margin-top:var(--bui-space-12)}.md\:bui-mt-13{margin-top:var(--bui-space-13)}.md\:bui-mt-14{margin-top:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-mt{margin-top:var(--mt-lg)}.lg\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.lg\:bui-mt-1{margin-top:var(--bui-space-1)}.lg\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.lg\:bui-mt-2{margin-top:var(--bui-space-2)}.lg\:bui-mt-3{margin-top:var(--bui-space-3)}.lg\:bui-mt-4{margin-top:var(--bui-space-4)}.lg\:bui-mt-5{margin-top:var(--bui-space-5)}.lg\:bui-mt-6{margin-top:var(--bui-space-6)}.lg\:bui-mt-7{margin-top:var(--bui-space-7)}.lg\:bui-mt-8{margin-top:var(--bui-space-8)}.lg\:bui-mt-9{margin-top:var(--bui-space-9)}.lg\:bui-mt-10{margin-top:var(--bui-space-10)}.lg\:bui-mt-11{margin-top:var(--bui-space-11)}.lg\:bui-mt-12{margin-top:var(--bui-space-12)}.lg\:bui-mt-13{margin-top:var(--bui-space-13)}.lg\:bui-mt-14{margin-top:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-mt{margin-top:var(--mt-xl)}.xl\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.xl\:bui-mt-1{margin-top:var(--bui-space-1)}.xl\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.xl\:bui-mt-2{margin-top:var(--bui-space-2)}.xl\:bui-mt-3{margin-top:var(--bui-space-3)}.xl\:bui-mt-4{margin-top:var(--bui-space-4)}.xl\:bui-mt-5{margin-top:var(--bui-space-5)}.xl\:bui-mt-6{margin-top:var(--bui-space-6)}.xl\:bui-mt-7{margin-top:var(--bui-space-7)}.xl\:bui-mt-8{margin-top:var(--bui-space-8)}.xl\:bui-mt-9{margin-top:var(--bui-space-9)}.xl\:bui-mt-10{margin-top:var(--bui-space-10)}.xl\:bui-mt-11{margin-top:var(--bui-space-11)}.xl\:bui-mt-12{margin-top:var(--bui-space-12)}.xl\:bui-mt-13{margin-top:var(--bui-space-13)}.xl\:bui-mt-14{margin-top:var(--bui-space-14)}}.bui-mb{margin-bottom:var(--mb)}.bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.bui-mb-1{margin-bottom:var(--bui-space-1)}.bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.bui-mb-2{margin-bottom:var(--bui-space-2)}.bui-mb-3{margin-bottom:var(--bui-space-3)}.bui-mb-4{margin-bottom:var(--bui-space-4)}.bui-mb-5{margin-bottom:var(--bui-space-5)}.bui-mb-6{margin-bottom:var(--bui-space-6)}.bui-mb-7{margin-bottom:var(--bui-space-7)}.bui-mb-8{margin-bottom:var(--bui-space-8)}.bui-mb-9{margin-bottom:var(--bui-space-9)}.bui-mb-10{margin-bottom:var(--bui-space-10)}.bui-mb-11{margin-bottom:var(--bui-space-11)}.bui-mb-12{margin-bottom:var(--bui-space-12)}.bui-mb-13{margin-bottom:var(--bui-space-13)}.bui-mb-14{margin-bottom:var(--bui-space-14)}@media (width>=640px){.xs\:bui-mb{margin-bottom:var(--mb-xs)}.xs\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.xs\:bui-mb-1{margin-bottom:var(--bui-space-1)}.xs\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.xs\:bui-mb-2{margin-bottom:var(--bui-space-2)}.xs\:bui-mb-3{margin-bottom:var(--bui-space-3)}.xs\:bui-mb-4{margin-bottom:var(--bui-space-4)}.xs\:bui-mb-5{margin-bottom:var(--bui-space-5)}.xs\:bui-mb-6{margin-bottom:var(--bui-space-6)}.xs\:bui-mb-7{margin-bottom:var(--bui-space-7)}.xs\:bui-mb-8{margin-bottom:var(--bui-space-8)}.xs\:bui-mb-9{margin-bottom:var(--bui-space-9)}.xs\:bui-mb-10{margin-bottom:var(--bui-space-10)}.xs\:bui-mb-11{margin-bottom:var(--bui-space-11)}.xs\:bui-mb-12{margin-bottom:var(--bui-space-12)}.xs\:bui-mb-13{margin-bottom:var(--bui-space-13)}.xs\:bui-mb-14{margin-bottom:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-mb{margin-bottom:var(--mb-sm)}.sm\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.sm\:bui-mb-1{margin-bottom:var(--bui-space-1)}.sm\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.sm\:bui-mb-2{margin-bottom:var(--bui-space-2)}.sm\:bui-mb-3{margin-bottom:var(--bui-space-3)}.sm\:bui-mb-4{margin-bottom:var(--bui-space-4)}.sm\:bui-mb-5{margin-bottom:var(--bui-space-5)}.sm\:bui-mb-6{margin-bottom:var(--bui-space-6)}.sm\:bui-mb-7{margin-bottom:var(--bui-space-7)}.sm\:bui-mb-8{margin-bottom:var(--bui-space-8)}.sm\:bui-mb-9{margin-bottom:var(--bui-space-9)}.sm\:bui-mb-10{margin-bottom:var(--bui-space-10)}.sm\:bui-mb-11{margin-bottom:var(--bui-space-11)}.sm\:bui-mb-12{margin-bottom:var(--bui-space-12)}.sm\:bui-mb-13{margin-bottom:var(--bui-space-13)}.sm\:bui-mb-14{margin-bottom:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-mb{margin-bottom:var(--mb-md)}.md\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.md\:bui-mb-1{margin-bottom:var(--bui-space-1)}.md\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.md\:bui-mb-2{margin-bottom:var(--bui-space-2)}.md\:bui-mb-3{margin-bottom:var(--bui-space-3)}.md\:bui-mb-4{margin-bottom:var(--bui-space-4)}.md\:bui-mb-5{margin-bottom:var(--bui-space-5)}.md\:bui-mb-6{margin-bottom:var(--bui-space-6)}.md\:bui-mb-7{margin-bottom:var(--bui-space-7)}.md\:bui-mb-8{margin-bottom:var(--bui-space-8)}.md\:bui-mb-9{margin-bottom:var(--bui-space-9)}.md\:bui-mb-10{margin-bottom:var(--bui-space-10)}.md\:bui-mb-11{margin-bottom:var(--bui-space-11)}.md\:bui-mb-12{margin-bottom:var(--bui-space-12)}.md\:bui-mb-13{margin-bottom:var(--bui-space-13)}.md\:bui-mb-14{margin-bottom:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-mb{margin-bottom:var(--mb-lg)}.lg\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.lg\:bui-mb-1{margin-bottom:var(--bui-space-1)}.lg\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.lg\:bui-mb-2{margin-bottom:var(--bui-space-2)}.lg\:bui-mb-3{margin-bottom:var(--bui-space-3)}.lg\:bui-mb-4{margin-bottom:var(--bui-space-4)}.lg\:bui-mb-5{margin-bottom:var(--bui-space-5)}.lg\:bui-mb-6{margin-bottom:var(--bui-space-6)}.lg\:bui-mb-7{margin-bottom:var(--bui-space-7)}.lg\:bui-mb-8{margin-bottom:var(--bui-space-8)}.lg\:bui-mb-9{margin-bottom:var(--bui-space-9)}.lg\:bui-mb-10{margin-bottom:var(--bui-space-10)}.lg\:bui-mb-11{margin-bottom:var(--bui-space-11)}.lg\:bui-mb-12{margin-bottom:var(--bui-space-12)}.lg\:bui-mb-13{margin-bottom:var(--bui-space-13)}.lg\:bui-mb-14{margin-bottom:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-mb{margin-bottom:var(--mb-xl)}.xl\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.xl\:bui-mb-1{margin-bottom:var(--bui-space-1)}.xl\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.xl\:bui-mb-2{margin-bottom:var(--bui-space-2)}.xl\:bui-mb-3{margin-bottom:var(--bui-space-3)}.xl\:bui-mb-4{margin-bottom:var(--bui-space-4)}.xl\:bui-mb-5{margin-bottom:var(--bui-space-5)}.xl\:bui-mb-6{margin-bottom:var(--bui-space-6)}.xl\:bui-mb-7{margin-bottom:var(--bui-space-7)}.xl\:bui-mb-8{margin-bottom:var(--bui-space-8)}.xl\:bui-mb-9{margin-bottom:var(--bui-space-9)}.xl\:bui-mb-10{margin-bottom:var(--bui-space-10)}.xl\:bui-mb-11{margin-bottom:var(--bui-space-11)}.xl\:bui-mb-12{margin-bottom:var(--bui-space-12)}.xl\:bui-mb-13{margin-bottom:var(--bui-space-13)}.xl\:bui-mb-14{margin-bottom:var(--bui-space-14)}}.bui-my{margin-top:var(--my);margin-bottom:var(--my)}.bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}@media (width>=640px){.xs\:bui-my{margin-top:var(--my-xs);margin-bottom:var(--my-xs)}.xs\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.xs\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.xs\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.xs\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.xs\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.xs\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.xs\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.xs\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.xs\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.xs\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.xs\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.xs\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.xs\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.xs\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.xs\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.xs\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-my{margin-top:var(--my-sm);margin-bottom:var(--my-sm)}.sm\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.sm\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.sm\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.sm\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.sm\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.sm\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.sm\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.sm\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.sm\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.sm\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.sm\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.sm\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.sm\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.sm\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.sm\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.sm\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-my{margin-top:var(--my-md);margin-bottom:var(--my-md)}.md\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.md\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.md\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.md\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.md\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.md\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.md\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.md\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.md\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.md\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.md\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.md\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.md\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.md\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.md\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.md\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-my{margin-top:var(--my-lg);margin-bottom:var(--my-lg)}.lg\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.lg\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.lg\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.lg\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.lg\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.lg\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.lg\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.lg\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.lg\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.lg\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.lg\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.lg\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.lg\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.lg\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.lg\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.lg\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-my{margin-top:var(--my-xl);margin-bottom:var(--my-xl)}.xl\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.xl\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.xl\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.xl\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.xl\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.xl\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.xl\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.xl\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.xl\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.xl\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.xl\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.xl\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.xl\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.xl\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.xl\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.xl\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}.bui-mx{margin-left:var(--mx);margin-right:var(--mx)}.bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}@media (width>=640px){.xs\:bui-mx{margin-left:var(--mx-xs);margin-right:var(--mx-xs)}.xs\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.xs\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.xs\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.xs\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.xs\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.xs\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.xs\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.xs\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.xs\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.xs\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.xs\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.xs\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.xs\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.xs\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.xs\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.xs\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-mx{margin-left:var(--mx-sm);margin-right:var(--mx-sm)}.sm\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.sm\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.sm\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.sm\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.sm\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.sm\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.sm\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.sm\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.sm\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.sm\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.sm\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.sm\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.sm\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.sm\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.sm\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.sm\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-mx{margin-left:var(--mx-md);margin-right:var(--mx-md)}.md\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.md\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.md\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.md\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.md\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.md\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.md\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.md\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.md\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.md\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.md\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.md\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.md\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.md\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.md\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.md\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-mx{margin-left:var(--mx-lg);margin-right:var(--mx-lg)}.lg\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.lg\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.lg\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.lg\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.lg\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.lg\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.lg\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.lg\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.lg\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.lg\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.lg\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.lg\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.lg\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.lg\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.lg\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.lg\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-mx{margin-left:var(--mx-xl);margin-right:var(--mx-xl)}.xl\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.xl\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.xl\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.xl\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.xl\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.xl\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.xl\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.xl\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.xl\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.xl\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.xl\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.xl\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.xl\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.xl\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.xl\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.xl\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}.bui-display-none{display:none}.bui-display-inline{display:inline}.bui-display-inline-block{display:inline-block}.bui-display-block{display:block}@media (width>=640px){.xs\:bui-display-none{display:none}.xs\:bui-display-inline{display:inline}.xs\:bui-display-inline-block{display:inline-block}.xs\:bui-display-block{display:block}}@media (width>=768px){.sm\:bui-display-none{display:none}.sm\:bui-display-inline{display:inline}.sm\:bui-display-inline-block{display:inline-block}.sm\:bui-display-block{display:block}}@media (width>=1024px){.md\:bui-display-none{display:none}.md\:bui-display-inline{display:inline}.md\:bui-display-inline-block{display:inline-block}.md\:bui-display-block{display:block}}@media (width>=1280px){.lg\:bui-display-none{display:none}.lg\:bui-display-inline{display:inline}.lg\:bui-display-inline-block{display:inline-block}.lg\:bui-display-block{display:block}}@media (width>=1536px){.xl\:bui-display-none{display:none}.xl\:bui-display-inline{display:inline}.xl\:bui-display-inline-block{display:inline-block}.xl\:bui-display-block{display:block}}.bui-w{width:var(--width)}.bui-min-w{min-width:var(--min-width)}.bui-max-w{max-width:var(--max-width)}@media (width>=640px){.xs\:bui-w{width:var(--width)}.xs\:bui-min-w{min-width:var(--min-width)}.xs\:bui-max-w{max-width:var(--max-width)}}@media (width>=768px){.sm\:bui-w{width:var(--width)}.sm\:bui-min-w{min-width:var(--min-width)}.sm\:bui-max-w{max-width:var(--max-width)}}@media (width>=1024px){.md\:bui-w{width:var(--width)}.md\:bui-min-w{min-width:var(--min-width)}.md\:bui-max-w{max-width:var(--max-width)}}@media (width>=1280px){.lg\:bui-w{width:var(--width)}.lg\:bui-min-w{min-width:var(--min-width)}.lg\:bui-max-w{max-width:var(--max-width)}}@media (width>=1536px){.xl\:bui-w{width:var(--width)}.xl\:bui-min-w{min-width:var(--min-width)}.xl\:bui-max-w{max-width:var(--max-width)}}.bui-h{height:var(--height)}.bui-min-h{min-height:var(--min-height)}.bui-max-h{max-height:var(--max-height)}@media (width>=640px){.xs\:bui-h{height:var(--height)}.xs\:bui-min-h{min-height:var(--min-height)}.xs\:bui-max-h{max-height:var(--max-height)}}@media (width>=768px){.sm\:bui-h{height:var(--height)}.sm\:bui-min-h{min-height:var(--min-height)}.sm\:bui-max-h{max-height:var(--max-height)}}@media (width>=1024px){.md\:bui-h{height:var(--height)}.md\:bui-min-h{min-height:var(--min-height)}.md\:bui-max-h{max-height:var(--max-height)}}@media (width>=1280px){.lg\:bui-h{height:var(--height)}.lg\:bui-min-h{min-height:var(--min-height)}.lg\:bui-max-h{max-height:var(--max-height)}}@media (width>=1536px){.xl\:bui-h{height:var(--height)}.xl\:bui-min-h{min-height:var(--min-height)}.xl\:bui-max-h{max-height:var(--max-height)}}.bui-position-absolute{position:absolute}.bui-position-fixed{position:fixed}.bui-position-sticky{position:sticky}.bui-position-relative{position:relative}.bui-position-static{position:static}@media (width>=640px){.xs\:bui-position-absolute{position:absolute}.xs\:bui-position-fixed{position:fixed}.xs\:bui-position-sticky{position:sticky}.xs\:bui-position-relative{position:relative}.xs\:bui-position-static{position:static}}@media (width>=768px){.sm\:bui-position-absolute{position:absolute}.sm\:bui-position-fixed{position:fixed}.sm\:bui-position-sticky{position:sticky}.sm\:bui-position-relative{position:relative}.sm\:bui-position-static{position:static}}@media (width>=1024px){.md\:bui-position-absolute{position:absolute}.md\:bui-position-fixed{position:fixed}.md\:bui-position-sticky{position:sticky}.md\:bui-position-relative{position:relative}.md\:bui-position-static{position:static}}@media (width>=1280px){.lg\:bui-position-absolute{position:absolute}.lg\:bui-position-fixed{position:fixed}.lg\:bui-position-sticky{position:sticky}.lg\:bui-position-relative{position:relative}.lg\:bui-position-static{position:static}}@media (width>=1536px){.xl\:bui-position-absolute{position:absolute}.xl\:bui-position-fixed{position:fixed}.xl\:bui-position-sticky{position:sticky}.xl\:bui-position-relative{position:relative}.xl\:bui-position-static{position:static}}.bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.bui-col-span-1{grid-column:span 1/span 1}.bui-col-span-2{grid-column:span 2/span 2}.bui-col-span-3{grid-column:span 3/span 3}.bui-col-span-4{grid-column:span 4/span 4}.bui-col-span-5{grid-column:span 5/span 5}.bui-col-span-6{grid-column:span 6/span 6}.bui-col-span-7{grid-column:span 7/span 7}.bui-col-span-8{grid-column:span 8/span 8}.bui-col-span-9{grid-column:span 9/span 9}.bui-col-span-10{grid-column:span 10/span 10}.bui-col-span-11{grid-column:span 11/span 11}.bui-col-span-12{grid-column:span 12/span 12}.bui-col-span-auto{grid-column:span auto/span auto}.bui-col-start-1{grid-column-start:1}.bui-col-start-2{grid-column-start:2}.bui-col-start-3{grid-column-start:3}.bui-col-start-4{grid-column-start:4}.bui-col-start-5{grid-column-start:5}.bui-col-start-6{grid-column-start:6}.bui-col-start-7{grid-column-start:7}.bui-col-start-8{grid-column-start:8}.bui-col-start-9{grid-column-start:9}.bui-col-start-10{grid-column-start:10}.bui-col-start-11{grid-column-start:11}.bui-col-start-12{grid-column-start:12}.bui-col-start-13{grid-column-start:13}.bui-col-start-auto{grid-column-start:auto}.bui-col-end-1{grid-column-end:1}.bui-col-end-2{grid-column-end:2}.bui-col-end-3{grid-column-end:3}.bui-col-end-4{grid-column-end:4}.bui-col-end-5{grid-column-end:5}.bui-col-end-6{grid-column-end:6}.bui-col-end-7{grid-column-end:7}.bui-col-end-8{grid-column-end:8}.bui-col-end-9{grid-column-end:9}.bui-col-end-10{grid-column-end:10}.bui-col-end-11{grid-column-end:11}.bui-col-end-12{grid-column-end:12}.bui-col-end-13{grid-column-end:13}.bui-col-end-auto{grid-column-end:auto}.bui-row-span-1{grid-row:span 1/span 1}.bui-row-span-2{grid-row:span 2/span 2}.bui-row-span-3{grid-row:span 3/span 3}.bui-row-span-4{grid-row:span 4/span 4}.bui-row-span-5{grid-row:span 5/span 5}.bui-row-span-6{grid-row:span 6/span 6}.bui-row-span-7{grid-row:span 7/span 7}.bui-row-span-8{grid-row:span 8/span 8}.bui-row-span-9{grid-row:span 9/span 9}.bui-row-span-10{grid-row:span 10/span 10}.bui-row-span-11{grid-row:span 11/span 11}.bui-row-span-12{grid-row:span 12/span 12}.bui-row-span-auto{grid-row:span auto/span auto}@media (width>=640px){.xs\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.xs\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.xs\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.xs\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.xs\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.xs\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.xs\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.xs\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.xs\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.xs\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.xs\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.xs\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.xs\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.xs\:bui-col-span-1{grid-column:span 1/span 1}.xs\:bui-col-span-2{grid-column:span 2/span 2}.xs\:bui-col-span-3{grid-column:span 3/span 3}.xs\:bui-col-span-4{grid-column:span 4/span 4}.xs\:bui-col-span-5{grid-column:span 5/span 5}.xs\:bui-col-span-6{grid-column:span 6/span 6}.xs\:bui-col-span-7{grid-column:span 7/span 7}.xs\:bui-col-span-8{grid-column:span 8/span 8}.xs\:bui-col-span-9{grid-column:span 9/span 9}.xs\:bui-col-span-10{grid-column:span 10/span 10}.xs\:bui-col-span-11{grid-column:span 11/span 11}.xs\:bui-col-span-12{grid-column:span 12/span 12}.xs\:bui-col-span-auto{grid-column:span auto/span auto}.xs\:bui-col-start-1{grid-column-start:1}.xs\:bui-col-start-2{grid-column-start:2}.xs\:bui-col-start-3{grid-column-start:3}.xs\:bui-col-start-4{grid-column-start:4}.xs\:bui-col-start-5{grid-column-start:5}.xs\:bui-col-start-6{grid-column-start:6}.xs\:bui-col-start-7{grid-column-start:7}.xs\:bui-col-start-8{grid-column-start:8}.xs\:bui-col-start-9{grid-column-start:9}.xs\:bui-col-start-10{grid-column-start:10}.xs\:bui-col-start-11{grid-column-start:11}.xs\:bui-col-start-12{grid-column-start:12}.xs\:bui-col-start-13{grid-column-start:13}.xs\:bui-col-start-auto{grid-column-start:auto}.xs\:bui-col-end-1{grid-column-end:1}.xs\:bui-col-end-2{grid-column-end:2}.xs\:bui-col-end-3{grid-column-end:3}.xs\:bui-col-end-4{grid-column-end:4}.xs\:bui-col-end-5{grid-column-end:5}.xs\:bui-col-end-6{grid-column-end:6}.xs\:bui-col-end-7{grid-column-end:7}.xs\:bui-col-end-8{grid-column-end:8}.xs\:bui-col-end-9{grid-column-end:9}.xs\:bui-col-end-10{grid-column-end:10}.xs\:bui-col-end-11{grid-column-end:11}.xs\:bui-col-end-12{grid-column-end:12}.xs\:bui-col-end-13{grid-column-end:13}.xs\:bui-col-end-auto{grid-column-end:auto}.xs\:bui-row-span-1{grid-row:span 1/span 1}.xs\:bui-row-span-2{grid-row:span 2/span 2}.xs\:bui-row-span-3{grid-row:span 3/span 3}.xs\:bui-row-span-4{grid-row:span 4/span 4}.xs\:bui-row-span-5{grid-row:span 5/span 5}.xs\:bui-row-span-6{grid-row:span 6/span 6}.xs\:bui-row-span-7{grid-row:span 7/span 7}.xs\:bui-row-span-8{grid-row:span 8/span 8}.xs\:bui-row-span-9{grid-row:span 9/span 9}.xs\:bui-row-span-10{grid-row:span 10/span 10}.xs\:bui-row-span-11{grid-row:span 11/span 11}.xs\:bui-row-span-12{grid-row:span 12/span 12}.xs\:bui-row-span-auto{grid-row:span auto/span auto}}@media (width>=768px){.sm\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.sm\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.sm\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.sm\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.sm\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.sm\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.sm\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.sm\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.sm\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.sm\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.sm\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.sm\:bui-col-span-1{grid-column:span 1/span 1}.sm\:bui-col-span-2{grid-column:span 2/span 2}.sm\:bui-col-span-3{grid-column:span 3/span 3}.sm\:bui-col-span-4{grid-column:span 4/span 4}.sm\:bui-col-span-5{grid-column:span 5/span 5}.sm\:bui-col-span-6{grid-column:span 6/span 6}.sm\:bui-col-span-7{grid-column:span 7/span 7}.sm\:bui-col-span-8{grid-column:span 8/span 8}.sm\:bui-col-span-9{grid-column:span 9/span 9}.sm\:bui-col-span-10{grid-column:span 10/span 10}.sm\:bui-col-span-11{grid-column:span 11/span 11}.sm\:bui-col-span-12{grid-column:span 12/span 12}.sm\:bui-col-span-auto{grid-column:span auto/span auto}.sm\:bui-col-start-1{grid-column-start:1}.sm\:bui-col-start-2{grid-column-start:2}.sm\:bui-col-start-3{grid-column-start:3}.sm\:bui-col-start-4{grid-column-start:4}.sm\:bui-col-start-5{grid-column-start:5}.sm\:bui-col-start-6{grid-column-start:6}.sm\:bui-col-start-7{grid-column-start:7}.sm\:bui-col-start-8{grid-column-start:8}.sm\:bui-col-start-9{grid-column-start:9}.sm\:bui-col-start-10{grid-column-start:10}.sm\:bui-col-start-11{grid-column-start:11}.sm\:bui-col-start-12{grid-column-start:12}.sm\:bui-col-start-13{grid-column-start:13}.sm\:bui-col-start-auto{grid-column-start:auto}.sm\:bui-col-end-1{grid-column-end:1}.sm\:bui-col-end-2{grid-column-end:2}.sm\:bui-col-end-3{grid-column-end:3}.sm\:bui-col-end-4{grid-column-end:4}.sm\:bui-col-end-5{grid-column-end:5}.sm\:bui-col-end-6{grid-column-end:6}.sm\:bui-col-end-7{grid-column-end:7}.sm\:bui-col-end-8{grid-column-end:8}.sm\:bui-col-end-9{grid-column-end:9}.sm\:bui-col-end-10{grid-column-end:10}.sm\:bui-col-end-11{grid-column-end:11}.sm\:bui-col-end-12{grid-column-end:12}.sm\:bui-col-end-13{grid-column-end:13}.sm\:bui-col-end-auto{grid-column-end:auto}.sm\:bui-row-span-1{grid-row:span 1/span 1}.sm\:bui-row-span-2{grid-row:span 2/span 2}.sm\:bui-row-span-3{grid-row:span 3/span 3}.sm\:bui-row-span-4{grid-row:span 4/span 4}.sm\:bui-row-span-5{grid-row:span 5/span 5}.sm\:bui-row-span-6{grid-row:span 6/span 6}.sm\:bui-row-span-7{grid-row:span 7/span 7}.sm\:bui-row-span-8{grid-row:span 8/span 8}.sm\:bui-row-span-9{grid-row:span 9/span 9}.sm\:bui-row-span-10{grid-row:span 10/span 10}.sm\:bui-row-span-11{grid-row:span 11/span 11}.sm\:bui-row-span-12{grid-row:span 12/span 12}.sm\:bui-row-span-auto{grid-row:span auto/span auto}}@media (width>=1024px){.md\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.md\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.md\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.md\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.md\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.md\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.md\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.md\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.md\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.md\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.md\:bui-col-span-1{grid-column:span 1/span 1}.md\:bui-col-span-2{grid-column:span 2/span 2}.md\:bui-col-span-3{grid-column:span 3/span 3}.md\:bui-col-span-4{grid-column:span 4/span 4}.md\:bui-col-span-5{grid-column:span 5/span 5}.md\:bui-col-span-6{grid-column:span 6/span 6}.md\:bui-col-span-7{grid-column:span 7/span 7}.md\:bui-col-span-8{grid-column:span 8/span 8}.md\:bui-col-span-9{grid-column:span 9/span 9}.md\:bui-col-span-10{grid-column:span 10/span 10}.md\:bui-col-span-11{grid-column:span 11/span 11}.md\:bui-col-span-12{grid-column:span 12/span 12}.md\:bui-col-span-auto{grid-column:span auto/span auto}.md\:bui-col-start-1{grid-column-start:1}.md\:bui-col-start-2{grid-column-start:2}.md\:bui-col-start-3{grid-column-start:3}.md\:bui-col-start-4{grid-column-start:4}.md\:bui-col-start-5{grid-column-start:5}.md\:bui-col-start-6{grid-column-start:6}.md\:bui-col-start-7{grid-column-start:7}.md\:bui-col-start-8{grid-column-start:8}.md\:bui-col-start-9{grid-column-start:9}.md\:bui-col-start-10{grid-column-start:10}.md\:bui-col-start-11{grid-column-start:11}.md\:bui-col-start-12{grid-column-start:12}.md\:bui-col-start-13{grid-column-start:13}.md\:bui-col-start-auto{grid-column-start:auto}.md\:bui-col-end-1{grid-column-end:1}.md\:bui-col-end-2{grid-column-end:2}.md\:bui-col-end-3{grid-column-end:3}.md\:bui-col-end-4{grid-column-end:4}.md\:bui-col-end-5{grid-column-end:5}.md\:bui-col-end-6{grid-column-end:6}.md\:bui-col-end-7{grid-column-end:7}.md\:bui-col-end-8{grid-column-end:8}.md\:bui-col-end-9{grid-column-end:9}.md\:bui-col-end-10{grid-column-end:10}.md\:bui-col-end-11{grid-column-end:11}.md\:bui-col-end-12{grid-column-end:12}.md\:bui-col-end-13{grid-column-end:13}.md\:bui-col-end-auto{grid-column-end:auto}.md\:bui-row-span-1{grid-row:span 1/span 1}.md\:bui-row-span-2{grid-row:span 2/span 2}.md\:bui-row-span-3{grid-row:span 3/span 3}.md\:bui-row-span-4{grid-row:span 4/span 4}.md\:bui-row-span-5{grid-row:span 5/span 5}.md\:bui-row-span-6{grid-row:span 6/span 6}.md\:bui-row-span-7{grid-row:span 7/span 7}.md\:bui-row-span-8{grid-row:span 8/span 8}.md\:bui-row-span-9{grid-row:span 9/span 9}.md\:bui-row-span-10{grid-row:span 10/span 10}.md\:bui-row-span-11{grid-row:span 11/span 11}.md\:bui-row-span-12{grid-row:span 12/span 12}.md\:bui-row-span-auto{grid-row:span auto/span auto}}@media (width>=1280px){.lg\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.lg\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.lg\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.lg\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.lg\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.lg\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.lg\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.lg\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.lg\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.lg\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.lg\:bui-col-span-1{grid-column:span 1/span 1}.lg\:bui-col-span-2{grid-column:span 2/span 2}.lg\:bui-col-span-3{grid-column:span 3/span 3}.lg\:bui-col-span-4{grid-column:span 4/span 4}.lg\:bui-col-span-5{grid-column:span 5/span 5}.lg\:bui-col-span-6{grid-column:span 6/span 6}.lg\:bui-col-span-7{grid-column:span 7/span 7}.lg\:bui-col-span-8{grid-column:span 8/span 8}.lg\:bui-col-span-9{grid-column:span 9/span 9}.lg\:bui-col-span-10{grid-column:span 10/span 10}.lg\:bui-col-span-11{grid-column:span 11/span 11}.lg\:bui-col-span-12{grid-column:span 12/span 12}.lg\:bui-col-span-auto{grid-column:span auto/span auto}.lg\:bui-col-start-1{grid-column-start:1}.lg\:bui-col-start-2{grid-column-start:2}.lg\:bui-col-start-3{grid-column-start:3}.lg\:bui-col-start-4{grid-column-start:4}.lg\:bui-col-start-5{grid-column-start:5}.lg\:bui-col-start-6{grid-column-start:6}.lg\:bui-col-start-7{grid-column-start:7}.lg\:bui-col-start-8{grid-column-start:8}.lg\:bui-col-start-9{grid-column-start:9}.lg\:bui-col-start-10{grid-column-start:10}.lg\:bui-col-start-11{grid-column-start:11}.lg\:bui-col-start-12{grid-column-start:12}.lg\:bui-col-start-13{grid-column-start:13}.lg\:bui-col-start-auto{grid-column-start:auto}.lg\:bui-col-end-1{grid-column-end:1}.lg\:bui-col-end-2{grid-column-end:2}.lg\:bui-col-end-3{grid-column-end:3}.lg\:bui-col-end-4{grid-column-end:4}.lg\:bui-col-end-5{grid-column-end:5}.lg\:bui-col-end-6{grid-column-end:6}.lg\:bui-col-end-7{grid-column-end:7}.lg\:bui-col-end-8{grid-column-end:8}.lg\:bui-col-end-9{grid-column-end:9}.lg\:bui-col-end-10{grid-column-end:10}.lg\:bui-col-end-11{grid-column-end:11}.lg\:bui-col-end-12{grid-column-end:12}.lg\:bui-col-end-13{grid-column-end:13}.lg\:bui-col-end-auto{grid-column-end:auto}.lg\:bui-row-span-1{grid-row:span 1/span 1}.lg\:bui-row-span-2{grid-row:span 2/span 2}.lg\:bui-row-span-3{grid-row:span 3/span 3}.lg\:bui-row-span-4{grid-row:span 4/span 4}.lg\:bui-row-span-5{grid-row:span 5/span 5}.lg\:bui-row-span-6{grid-row:span 6/span 6}.lg\:bui-row-span-7{grid-row:span 7/span 7}.lg\:bui-row-span-8{grid-row:span 8/span 8}.lg\:bui-row-span-9{grid-row:span 9/span 9}.lg\:bui-row-span-10{grid-row:span 10/span 10}.lg\:bui-row-span-11{grid-row:span 11/span 11}.lg\:bui-row-span-12{grid-row:span 12/span 12}.lg\:bui-row-span-auto{grid-row:span auto/span auto}}@media (width>=1536px){.xl\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.xl\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.xl\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.xl\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.xl\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.xl\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.xl\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.xl\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.xl\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.xl\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.xl\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.xl\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.xl\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.xl\:bui-col-span-1{grid-column:span 1/span 1}.xl\:bui-col-span-2{grid-column:span 2/span 2}.xl\:bui-col-span-3{grid-column:span 3/span 3}.xl\:bui-col-span-4{grid-column:span 4/span 4}.xl\:bui-col-span-5{grid-column:span 5/span 5}.xl\:bui-col-span-6{grid-column:span 6/span 6}.xl\:bui-col-span-7{grid-column:span 7/span 7}.xl\:bui-col-span-8{grid-column:span 8/span 8}.xl\:bui-col-span-9{grid-column:span 9/span 9}.xl\:bui-col-span-10{grid-column:span 10/span 10}.xl\:bui-col-span-11{grid-column:span 11/span 11}.xl\:bui-col-span-12{grid-column:span 12/span 12}.xl\:bui-col-span-auto{grid-column:span auto/span auto}.xl\:bui-col-start-1{grid-column-start:1}.xl\:bui-col-start-2{grid-column-start:2}.xl\:bui-col-start-3{grid-column-start:3}.xl\:bui-col-start-4{grid-column-start:4}.xl\:bui-col-start-5{grid-column-start:5}.xl\:bui-col-start-6{grid-column-start:6}.xl\:bui-col-start-7{grid-column-start:7}.xl\:bui-col-start-8{grid-column-start:8}.xl\:bui-col-start-9{grid-column-start:9}.xl\:bui-col-start-10{grid-column-start:10}.xl\:bui-col-start-11{grid-column-start:11}.xl\:bui-col-start-12{grid-column-start:12}.xl\:bui-col-start-13{grid-column-start:13}.xl\:bui-col-start-auto{grid-column-start:auto}.xl\:bui-col-end-1{grid-column-end:1}.xl\:bui-col-end-2{grid-column-end:2}.xl\:bui-col-end-3{grid-column-end:3}.xl\:bui-col-end-4{grid-column-end:4}.xl\:bui-col-end-5{grid-column-end:5}.xl\:bui-col-end-6{grid-column-end:6}.xl\:bui-col-end-7{grid-column-end:7}.xl\:bui-col-end-8{grid-column-end:8}.xl\:bui-col-end-9{grid-column-end:9}.xl\:bui-col-end-10{grid-column-end:10}.xl\:bui-col-end-11{grid-column-end:11}.xl\:bui-col-end-12{grid-column-end:12}.xl\:bui-col-end-13{grid-column-end:13}.xl\:bui-col-end-auto{grid-column-end:auto}.xl\:bui-row-span-1{grid-row:span 1/span 1}.xl\:bui-row-span-2{grid-row:span 2/span 2}.xl\:bui-row-span-3{grid-row:span 3/span 3}.xl\:bui-row-span-4{grid-row:span 4/span 4}.xl\:bui-row-span-5{grid-row:span 5/span 5}.xl\:bui-row-span-6{grid-row:span 6/span 6}.xl\:bui-row-span-7{grid-row:span 7/span 7}.xl\:bui-row-span-8{grid-row:span 8/span 8}.xl\:bui-row-span-9{grid-row:span 9/span 9}.xl\:bui-row-span-10{grid-row:span 10/span 10}.xl\:bui-row-span-11{grid-row:span 11/span 11}.xl\:bui-row-span-12{grid-row:span 12/span 12}.xl\:bui-row-span-auto{grid-row:span auto/span auto}}.bui-gap{gap:var(--gap)}.bui-gap-0\.5{gap:var(--bui-space-0_5)}.bui-gap-1{gap:var(--bui-space-1)}.bui-gap-1\.5{gap:var(--bui-space-1_5)}.bui-gap-2{gap:var(--bui-space-2)}.bui-gap-3{gap:var(--bui-space-3)}.bui-gap-4{gap:var(--bui-space-4)}.bui-gap-5{gap:var(--bui-space-5)}.bui-gap-6{gap:var(--bui-space-6)}.bui-gap-7{gap:var(--bui-space-7)}.bui-gap-8{gap:var(--bui-space-8)}.bui-gap-9{gap:var(--bui-space-9)}.bui-gap-10{gap:var(--bui-space-10)}.bui-gap-11{gap:var(--bui-space-11)}.bui-gap-12{gap:var(--bui-space-12)}.bui-gap-13{gap:var(--bui-space-13)}.bui-gap-14{gap:var(--bui-space-14)}@media (width>=640px){.xs\:bui-gap{gap:var(--gap-xs)}.xs\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.xs\:bui-gap-1{gap:var(--bui-space-1)}.xs\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.xs\:bui-gap-2{gap:var(--bui-space-2)}.xs\:bui-gap-3{gap:var(--bui-space-3)}.xs\:bui-gap-4{gap:var(--bui-space-4)}.xs\:bui-gap-5{gap:var(--bui-space-5)}.xs\:bui-gap-6{gap:var(--bui-space-6)}.xs\:bui-gap-7{gap:var(--bui-space-7)}.xs\:bui-gap-8{gap:var(--bui-space-8)}.xs\:bui-gap-9{gap:var(--bui-space-9)}.xs\:bui-gap-10{gap:var(--bui-space-10)}.xs\:bui-gap-11{gap:var(--bui-space-11)}.xs\:bui-gap-12{gap:var(--bui-space-12)}.xs\:bui-gap-13{gap:var(--bui-space-13)}.xs\:bui-gap-14{gap:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-gap{gap:var(--gap-sm)}.sm\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.sm\:bui-gap-1{gap:var(--bui-space-1)}.sm\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.sm\:bui-gap-2{gap:var(--bui-space-2)}.sm\:bui-gap-3{gap:var(--bui-space-3)}.sm\:bui-gap-4{gap:var(--bui-space-4)}.sm\:bui-gap-5{gap:var(--bui-space-5)}.sm\:bui-gap-6{gap:var(--bui-space-6)}.sm\:bui-gap-7{gap:var(--bui-space-7)}.sm\:bui-gap-8{gap:var(--bui-space-8)}.sm\:bui-gap-9{gap:var(--bui-space-9)}.sm\:bui-gap-10{gap:var(--bui-space-10)}.sm\:bui-gap-11{gap:var(--bui-space-11)}.sm\:bui-gap-12{gap:var(--bui-space-12)}.sm\:bui-gap-13{gap:var(--bui-space-13)}.sm\:bui-gap-14{gap:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-gap{gap:var(--gap-md)}.md\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.md\:bui-gap-1{gap:var(--bui-space-1)}.md\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.md\:bui-gap-2{gap:var(--bui-space-2)}.md\:bui-gap-3{gap:var(--bui-space-3)}.md\:bui-gap-4{gap:var(--bui-space-4)}.md\:bui-gap-5{gap:var(--bui-space-5)}.md\:bui-gap-6{gap:var(--bui-space-6)}.md\:bui-gap-7{gap:var(--bui-space-7)}.md\:bui-gap-8{gap:var(--bui-space-8)}.md\:bui-gap-9{gap:var(--bui-space-9)}.md\:bui-gap-10{gap:var(--bui-space-10)}.md\:bui-gap-11{gap:var(--bui-space-11)}.md\:bui-gap-12{gap:var(--bui-space-12)}.md\:bui-gap-13{gap:var(--bui-space-13)}.md\:bui-gap-14{gap:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-gap{gap:var(--gap-lg)}.lg\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.lg\:bui-gap-1{gap:var(--bui-space-1)}.lg\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.lg\:bui-gap-2{gap:var(--bui-space-2)}.lg\:bui-gap-3{gap:var(--bui-space-3)}.lg\:bui-gap-4{gap:var(--bui-space-4)}.lg\:bui-gap-5{gap:var(--bui-space-5)}.lg\:bui-gap-6{gap:var(--bui-space-6)}.lg\:bui-gap-7{gap:var(--bui-space-7)}.lg\:bui-gap-8{gap:var(--bui-space-8)}.lg\:bui-gap-9{gap:var(--bui-space-9)}.lg\:bui-gap-10{gap:var(--bui-space-10)}.lg\:bui-gap-11{gap:var(--bui-space-11)}.lg\:bui-gap-12{gap:var(--bui-space-12)}.lg\:bui-gap-13{gap:var(--bui-space-13)}.lg\:bui-gap-14{gap:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-gap{gap:var(--gap-xl)}.xl\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.xl\:bui-gap-1{gap:var(--bui-space-1)}.xl\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.xl\:bui-gap-2{gap:var(--bui-space-2)}.xl\:bui-gap-3{gap:var(--bui-space-3)}.xl\:bui-gap-4{gap:var(--bui-space-4)}.xl\:bui-gap-5{gap:var(--bui-space-5)}.xl\:bui-gap-6{gap:var(--bui-space-6)}.xl\:bui-gap-7{gap:var(--bui-space-7)}.xl\:bui-gap-8{gap:var(--bui-space-8)}.xl\:bui-gap-9{gap:var(--bui-space-9)}.xl\:bui-gap-10{gap:var(--bui-space-10)}.xl\:bui-gap-11{gap:var(--bui-space-11)}.xl\:bui-gap-12{gap:var(--bui-space-12)}.xl\:bui-gap-13{gap:var(--bui-space-13)}.xl\:bui-gap-14{gap:var(--bui-space-14)}}.bui-align-start{align-items:start}.bui-align-center{align-items:center}.bui-align-end{align-items:end}.bui-align-baseline{align-items:baseline}.bui-align-stretch{align-items:stretch}.bui-jc-start{justify-content:start}.bui-jc-center{justify-content:center}.bui-jc-end{justify-content:end}.bui-jc-between{justify-content:space-between}.bui-fd-row{flex-direction:row}.bui-fd-column{flex-direction:column}.bui-fd-row-reverse{flex-direction:row-reverse}.bui-fd-column-reverse{flex-direction:column-reverse}@media (width>=640px){.xs\:bui-align-start{align-items:start}.xs\:bui-align-center{align-items:center}.xs\:bui-align-end{align-items:end}.xs\:bui-align-stretch{align-items:stretch}.xs\:bui-jc-start{justify-content:start}.xs\:bui-jc-center{justify-content:center}.xs\:bui-jc-end{justify-content:end}.xs\:bui-jc-between{justify-content:space-between}.xs\:bui-fd-row{flex-direction:row}.xs\:bui-fd-column{flex-direction:column}.xs\:bui-fd-row-reverse{flex-direction:row-reverse}.xs\:bui-fd-column-reverse{flex-direction:column-reverse}}@media (width>=768px){.sm\:bui-align-start{align-items:start}.sm\:bui-align-center{align-items:center}.sm\:bui-align-end{align-items:end}.sm\:bui-align-stretch{align-items:stretch}.sm\:bui-jc-start{justify-content:start}.sm\:bui-jc-center{justify-content:center}.sm\:bui-jc-end{justify-content:end}.sm\:bui-jc-between{justify-content:space-between}.sm\:bui-fd-row{flex-direction:row}.sm\:bui-fd-column{flex-direction:column}.sm\:bui-fd-row-reverse{flex-direction:row-reverse}.sm\:bui-fd-column-reverse{flex-direction:column-reverse}}@media (width>=1024px){.md\:bui-align-start{align-items:start}.md\:bui-align-center{align-items:center}.md\:bui-align-end{align-items:end}.md\:bui-align-stretch{align-items:stretch}.md\:bui-jc-start{justify-content:start}.md\:bui-jc-center{justify-content:center}.md\:bui-jc-end{justify-content:end}.md\:bui-jc-between{justify-content:space-between}.md\:bui-fd-row{flex-direction:row}.md\:bui-fd-column{flex-direction:column}.md\:bui-fd-row-reverse{flex-direction:row-reverse}.md\:bui-fd-column-reverse{flex-direction:column-reverse}}@media (width>=1280px){.lg\:bui-align-start{align-items:start}.lg\:bui-align-center{align-items:center}.lg\:bui-align-end{align-items:end}.lg\:bui-align-stretch{align-items:stretch}.lg\:bui-jc-start{justify-content:start}.lg\:bui-jc-center{justify-content:center}.lg\:bui-jc-end{justify-content:end}.lg\:bui-jc-between{justify-content:space-between}.lg\:bui-fd-row{flex-direction:row}.lg\:bui-fd-column{flex-direction:column}.lg\:bui-fd-row-reverse{flex-direction:row-reverse}.lg\:bui-fd-column-reverse{flex-direction:column-reverse}}@media (width>=1536px){.xl\:bui-align-start{align-items:start}.xl\:bui-align-center{align-items:center}.xl\:bui-align-end{align-items:end}.xl\:bui-align-stretch{align-items:stretch}.xl\:bui-jc-start{justify-content:start}.xl\:bui-jc-center{justify-content:center}.xl\:bui-jc-end{justify-content:end}.xl\:bui-jc-between{justify-content:space-between}.xl\:bui-fd-row{flex-direction:row}.xl\:bui-fd-column{flex-direction:column}.xl\:bui-fd-row-reverse{flex-direction:row-reverse}.xl\:bui-fd-column-reverse{flex-direction:column-reverse}}} \ No newline at end of file diff --git a/docs-ui/public/theme-spotify.css b/docs-ui/public/theme-spotify.css index b0bf517701..0f2ecc6081 100644 --- a/docs-ui/public/theme-spotify.css +++ b/docs-ui/public/theme-spotify.css @@ -1 +1 @@ -@font-face{font-family:CircularSpTitle;font-weight:900;font-display:swap;unicode-range:U+0,U+D,U+20-7E,U+A0-17E,U+18F,U+192,U+1A0-1A1,U+1AF-1B0,U+1B5-1B6,U+1C4-1C6,U+1F1-1F3,U+1FA-1FF,U+218-21B,U+237,U+259,U+2BB-2BC,U+2C6-2C7,U+2C9,U+2D8-2DD,U+300-301,U+303,U+309,U+323,U+394,U+3A9,U+3BC,U+3C0,U+1E80-1E85,U+1E8A-1E8B,U+1EA0-1EF9,U+1FD6,U+2007-2008,U+200B,U+2010-2011,U+2013-2014,U+2018-201A,U+201C-201E,U+2020-2022,U+2026,U+2030,U+2032-2033,U+2039-203A,U+2042,U+2044,U+2051,U+2070,U+2074-2079,U+2080-2089,U+20AB-20AC,U+2113,U+2117,U+2122,U+2126,U+2160-2169,U+216C-216F,U+2190-2193,U+2196-2199,U+21A9,U+21B0-21B5,U+21C6,U+2202,U+2206,U+220F,U+2211-2212,U+2215,U+2219-221A,U+221E,U+222B,U+2248,U+2260,U+2264-2265,U+22C5,U+24C5,U+25A0-25A1,U+25AF,U+25B2-25B3,U+25CA-25CB,U+25CF,U+262E,U+2713,U+2715,U+2780-2788,U+E000,U+E002,U+F6C3,U+FB00-FB04,U+FEFF,U+FF0C,U+FF0E,U+FF1A-FF1B,U+FFFF;src:url(https://encore.scdn.co/fonts/CircularSpTitle-Black-4588c99025b967475c31695b0743dd1a.woff2)format("woff2"),url(https://encore.scdn.co/fonts/CircularSpTitle-Black-506746f387a26f25aa3d023b3e501d34.woff)format("woff")}@font-face{font-family:CircularSpTitle;font-weight:700;font-display:swap;unicode-range:U+0,U+D,U+20-7E,U+A0-17E,U+18F,U+192,U+1A0-1A1,U+1AF-1B0,U+1B5-1B6,U+1C4-1C6,U+1F1-1F3,U+1FA-1FF,U+218-21B,U+237,U+259,U+2BB-2BC,U+2C6-2C7,U+2C9,U+2D8-2DD,U+300-301,U+303,U+309,U+323,U+394,U+3A9,U+3BC,U+3C0,U+1E80-1E85,U+1E8A-1E8B,U+1EA0-1EF9,U+1FD6,U+2007-2008,U+200B,U+2010-2011,U+2013-2014,U+2018-201A,U+201C-201E,U+2020-2022,U+2026,U+2030,U+2032-2033,U+2039-203A,U+2042,U+2044,U+2051,U+2070,U+2074-2079,U+2080-2089,U+20AB-20AC,U+2113,U+2117,U+2122,U+2126,U+2160-2169,U+216C-216F,U+2190-2193,U+2196-2199,U+21A9,U+21B0-21B5,U+21C6,U+2202,U+2206,U+220F,U+2211-2212,U+2215,U+2219-221A,U+221E,U+222B,U+2248,U+2260,U+2264-2265,U+22C5,U+24C5,U+25A0-25A1,U+25AF,U+25B2-25B3,U+25CA-25CB,U+25CF,U+262E,U+2713,U+2715,U+2780-2788,U+E000,U+E002,U+F6C3,U+FB00-FB04,U+FEFF,U+FF0C,U+FF0E,U+FF1A-FF1B,U+FFFF;src:url(https://encore.scdn.co/fonts/CircularSpTitle-Bold-b2586b06a2e1522e9d879d84c2792a58.woff2)format("woff2"),url(https://encore.scdn.co/fonts/CircularSpTitle-Bold-1624fb2df28c20d7203d7fb86ce8b481.woff)format("woff")}@font-face{font-family:CircularSp;font-weight:700;font-display:swap;unicode-range:U+0,U+D,U+20-7E,U+A0-17E,U+18F,U+192,U+1A0-1A1,U+1AF-1B0,U+1B5-1B6,U+1C4-1C6,U+1F1-1F3,U+1FA-1FF,U+218-21B,U+237,U+259,U+2BB-2BC,U+2C6-2C7,U+2C9,U+2D8-2DD,U+300-301,U+303,U+309,U+323,U+394,U+3A9,U+3BC,U+3C0,U+1E80-1E85,U+1E8A-1E8B,U+1EA0-1EF9,U+1FD6,U+2007-2008,U+200B,U+2010-2011,U+2013-2014,U+2018-201A,U+201C-201E,U+2020-2022,U+2026,U+2030,U+2032-2033,U+2039-203A,U+2042,U+2044,U+2051,U+2070,U+2074-2079,U+2080-2089,U+20AB-20AC,U+2113,U+2117,U+2122,U+2126,U+2160-2169,U+216C-216F,U+2190-2193,U+2196-2199,U+21A9,U+21B0-21B5,U+21C6,U+2202,U+2206,U+220F,U+2211-2212,U+2215,U+2219-221A,U+221E,U+222B,U+2248,U+2260,U+2264-2265,U+22C5,U+24C5,U+25A0-25A1,U+25AF,U+25B2-25B3,U+25CA-25CB,U+25CF,U+262E,U+2713,U+2715,U+2780-2788,U+E000,U+E002,U+F6C3,U+FB00-FB04,U+FEFF,U+FF0C,U+FF0E,U+FF1A-FF1B,U+FFFF;src:url(https://encore.scdn.co/fonts/CircularSp-Bold-602e7aefc706aa36c6ec1324b9bbc461.woff2)format("woff2"),url(https://encore.scdn.co/fonts/CircularSp-Bold-856afe2da4ba4e61239b129e2c16d633.woff)format("woff")}@font-face{font-family:CircularSp;font-weight:400;font-display:swap;unicode-range:U+0,U+D,U+20-7E,U+A0-17E,U+18F,U+192,U+1A0-1A1,U+1AF-1B0,U+1B5-1B6,U+1C4-1C6,U+1F1-1F3,U+1FA-1FF,U+218-21B,U+237,U+259,U+2BB-2BC,U+2C6-2C7,U+2C9,U+2D8-2DD,U+300-301,U+303,U+309,U+323,U+394,U+3A9,U+3BC,U+3C0,U+1E80-1E85,U+1E8A-1E8B,U+1EA0-1EF9,U+1FD6,U+2007-2008,U+200B,U+2010-2011,U+2013-2014,U+2018-201A,U+201C-201E,U+2020-2022,U+2026,U+2030,U+2032-2033,U+2039-203A,U+2042,U+2044,U+2051,U+2070,U+2074-2079,U+2080-2089,U+20AB-20AC,U+2113,U+2117,U+2122,U+2126,U+2160-2169,U+216C-216F,U+2190-2193,U+2196-2199,U+21A9,U+21B0-21B5,U+21C6,U+2202,U+2206,U+220F,U+2211-2212,U+2215,U+2219-221A,U+221E,U+222B,U+2248,U+2260,U+2264-2265,U+22C5,U+24C5,U+25A0-25A1,U+25AF,U+25B2-25B3,U+25CA-25CB,U+25CF,U+262E,U+2713,U+2715,U+2780-2788,U+E000,U+E002,U+F6C3,U+FB00-FB04,U+FEFF,U+FF0C,U+FF0E,U+FF1A-FF1B,U+FFFF;src:url(https://encore.scdn.co/fonts/CircularSp-Book-a00e99ef9996a3a157fb6b746856d04f.woff2)format("woff2"),url(https://encore.scdn.co/fonts/CircularSp-Book-3f73da7d35bd81c706bce7bbb84964de.woff)format("woff")}@font-face{font-family:CircularSp;font-weight:700;font-display:swap;unicode-range:U+0,U+D,U+20-7E,U+A0-17E,U+18F,U+192,U+1A0-1A1,U+1AF-1B0,U+1B5-1B6,U+1C4-1C6,U+1F1-1F3,U+1FA-1FF,U+218-21B,U+237,U+259,U+2BB-2BC,U+2C6-2C7,U+2C9,U+2D8-2DD,U+300-301,U+303,U+309,U+323,U+394,U+3A9,U+3BC,U+3C0,U+1E80-1E85,U+1E8A-1E8B,U+1EA0-1EF9,U+1FD6,U+2007-2008,U+200B,U+2010-2011,U+2013-2014,U+2018-201A,U+201C-201E,U+2020-2022,U+2026,U+2030,U+2032-2033,U+2039-203A,U+2042,U+2044,U+2051,U+2070,U+2074-2079,U+2080-2089,U+20AB-20AC,U+2113,U+2117,U+2122,U+2126,U+2160-2169,U+216C-216F,U+2190-2193,U+2196-2199,U+21A9,U+21B0-21B5,U+21C6,U+2202,U+2206,U+220F,U+2211-2212,U+2215,U+2219-221A,U+221E,U+222B,U+2248,U+2260,U+2264-2265,U+22C5,U+24C5,U+25A0-25A1,U+25AF,U+25B2-25B3,U+25CA-25CB,U+25CF,U+262E,U+2713,U+2715,U+2780-2788,U+E000,U+E002,U+F6C3,U+FB00-FB04,U+FEFF,U+FF0C,U+FF0E,U+FF1A-FF1B,U+FFFF;src:url(https://encore.scdn.co/fonts/CircularSp-Bold-602e7aefc706aa36c6ec1324b9bbc461.woff2)format("woff2"),url(https://encore.scdn.co/fonts/CircularSp-Bold-856afe2da4ba4e61239b129e2c16d633.woff)format("woff")}[data-theme-name=spotify]{--bui-font-text:CircularSp,CircularSp-Arab,CircularSp-Hebr,CircularSp-Cyrl,CircularSp-Grek,CircularSp-Deva;--bui-font-title:CircularSpTitle,CircularSp-Arab,CircularSp-Hebr,CircularSp-Cyrl,CircularSp-Grek,CircularSp-Deva;--bui-font-regular:CircularSp,CircularSp-Arab,CircularSp-Hebr,CircularSp-Cyrl,CircularSp-Grek,CircularSp-Deva;& .bui-Button{border-radius:var(--bui-radius-3);padding-inline:var(--bui-space-3)}& .bui-ButtonIcon{padding:0}& .bui-MenuPopup{box-sizing:border-box;max-width:21.25rem}& .bui-MenuSubmenuTrigger,& .bui-MenuItem{height:auto;min-height:2rem}& .bui-Text{font-family:var(--bui-font-text)}& .bui-Heading{font-family:var(--bui-font-title)}& .bui-TableRow{border-radius:var(--bui-radius-4);border:none}& .bui-TableRow:hover td:first-child{border-top-left-radius:var(--bui-radius-2);border-bottom-left-radius:var(--bui-radius-2)}& .bui-TableRow:hover td:last-child{border-top-right-radius:var(--bui-radius-2);border-bottom-right-radius:var(--bui-radius-2)}& .bui-TableBody:before,& .bui-TableBody:after{line-height:var(--bui-space-1);content:"‌";display:block}& .bui-TableHeader .bui-TableRow{border-bottom:1px solid var(--bui-border)}& .bui-TableHead{font-size:var(--bui-font-size-2);color:var(--bui-fg-secondary);font-weight:var(--bui-font-weight-regular)}& .bui-HeaderToolbar{padding-top:var(--bui-space-2);padding-inline:var(--bui-space-2)}& .bui-HeaderToolbarWrapper{border-radius:var(--bui-radius-3);padding-inline:var(--bui-space-3);border:none}& .bui-HeaderToolbarControls{right:calc(var(--bui-space-3) - 1px)}& .bui-HeaderTabsWrapper{margin-top:var(--bui-space-2);margin-inline:var(--bui-space-2);border-radius:var(--bui-radius-3);padding-inline:var(--bui-space-1);border:none}& .bui-Input{border-radius:var(--bui-radius-3)}& .bui-Tag{border-radius:var(--bui-radius-full)}}[data-theme-mode=light][data-theme-name=spotify]{--bui-bg:var(--bui-gray-1);--bui-bg-surface-1:var(--bui-white);--bui-bg-surface-2:var(--bui-gray-2);--bui-bg-solid:#1ed760;--bui-bg-solid-hover:#3be477;--bui-bg-solid-pressed:#1abc54;--bui-bg-solid-disabled:var(--bui-gray-2);--bui-fg-primary:var(--bui-black);--bui-fg-secondary:var(--bui-gray-7);--bui-fg-solid:var(--bui-black);--bui-border:var(--bui-gray-3);--bui-border-hover:#0000004d;--bui-border-pressed:#00000080;--bui-border-disabled:#0000001a;--bui-border-danger:#f87a7a;--bui-border-warning:#e36d05;--bui-border-success:#53db83;--bui-ring:#0003;& .bui-HeaderToolbarWrapper,& .bui-HeaderTabsWrapper{border:1px solid var(--bui-border)}}[data-theme-mode=dark][data-theme-name=spotify]{--bui-bg:var(--bui-black);--bui-bg-surface-1:var(--bui-gray-1);--bui-bg-surface-2:var(--bui-gray-2);--bui-bg-solid:#1ed760;--bui-bg-solid-hover:#3be477;--bui-bg-solid-pressed:#1abc54;--bui-bg-solid-disabled:#0f6c30;--bui-bg-tint:#242424;--bui-bg-tint-hover:#202020;--bui-bg-tint-pressed:#292929;--bui-bg-tint-disabled:#fffc;--bui-bg-danger:#3b1219;--bui-bg-warning:#302008;--bui-bg-success:#132d21;--bui-fg-primary:var(--bui-white);--bui-fg-secondary:var(--bui-gray-7);--bui-fg-link:var(--bui-white);--bui-fg-link-hover:var(--bui-white);--bui-fg-disabled:var(--bui-gray-5);--bui-fg-solid:var(--bui-black);--bui-fg-solid-disabled:#083618;--bui-fg-tint:var(--bui-white);--bui-fg-tint-disabled:var(--bui-gray-5);--bui-fg-danger:#e22b2b;--bui-fg-warning:#e36d05;--bui-fg-success:#1db954;--bui-border:var(--bui-gray-3);--bui-border-hover:#fff6;--bui-border-pressed:#ffffff80;--bui-border-disabled:#fff3;--bui-border-danger:#f87a7a;--bui-border-warning:#e36d05;--bui-border-success:#53db83;--bui-ring:#fff3} \ No newline at end of file +@font-face{font-family:CircularSpTitle;font-weight:900;font-display:swap;unicode-range:U+0,U+D,U+20-7E,U+A0-17E,U+18F,U+192,U+1A0-1A1,U+1AF-1B0,U+1B5-1B6,U+1C4-1C6,U+1F1-1F3,U+1FA-1FF,U+218-21B,U+237,U+259,U+2BB-2BC,U+2C6-2C7,U+2C9,U+2D8-2DD,U+300-301,U+303,U+309,U+323,U+394,U+3A9,U+3BC,U+3C0,U+1E80-1E85,U+1E8A-1E8B,U+1EA0-1EF9,U+1FD6,U+2007-2008,U+200B,U+2010-2011,U+2013-2014,U+2018-201A,U+201C-201E,U+2020-2022,U+2026,U+2030,U+2032-2033,U+2039-203A,U+2042,U+2044,U+2051,U+2070,U+2074-2079,U+2080-2089,U+20AB-20AC,U+2113,U+2117,U+2122,U+2126,U+2160-2169,U+216C-216F,U+2190-2193,U+2196-2199,U+21A9,U+21B0-21B5,U+21C6,U+2202,U+2206,U+220F,U+2211-2212,U+2215,U+2219-221A,U+221E,U+222B,U+2248,U+2260,U+2264-2265,U+22C5,U+24C5,U+25A0-25A1,U+25AF,U+25B2-25B3,U+25CA-25CB,U+25CF,U+262E,U+2713,U+2715,U+2780-2788,U+E000,U+E002,U+F6C3,U+FB00-FB04,U+FEFF,U+FF0C,U+FF0E,U+FF1A-FF1B,U+FFFF;src:url(https://encore.scdn.co/fonts/CircularSpTitle-Black-4588c99025b967475c31695b0743dd1a.woff2)format("woff2"),url(https://encore.scdn.co/fonts/CircularSpTitle-Black-506746f387a26f25aa3d023b3e501d34.woff)format("woff")}@font-face{font-family:CircularSpTitle;font-weight:700;font-display:swap;unicode-range:U+0,U+D,U+20-7E,U+A0-17E,U+18F,U+192,U+1A0-1A1,U+1AF-1B0,U+1B5-1B6,U+1C4-1C6,U+1F1-1F3,U+1FA-1FF,U+218-21B,U+237,U+259,U+2BB-2BC,U+2C6-2C7,U+2C9,U+2D8-2DD,U+300-301,U+303,U+309,U+323,U+394,U+3A9,U+3BC,U+3C0,U+1E80-1E85,U+1E8A-1E8B,U+1EA0-1EF9,U+1FD6,U+2007-2008,U+200B,U+2010-2011,U+2013-2014,U+2018-201A,U+201C-201E,U+2020-2022,U+2026,U+2030,U+2032-2033,U+2039-203A,U+2042,U+2044,U+2051,U+2070,U+2074-2079,U+2080-2089,U+20AB-20AC,U+2113,U+2117,U+2122,U+2126,U+2160-2169,U+216C-216F,U+2190-2193,U+2196-2199,U+21A9,U+21B0-21B5,U+21C6,U+2202,U+2206,U+220F,U+2211-2212,U+2215,U+2219-221A,U+221E,U+222B,U+2248,U+2260,U+2264-2265,U+22C5,U+24C5,U+25A0-25A1,U+25AF,U+25B2-25B3,U+25CA-25CB,U+25CF,U+262E,U+2713,U+2715,U+2780-2788,U+E000,U+E002,U+F6C3,U+FB00-FB04,U+FEFF,U+FF0C,U+FF0E,U+FF1A-FF1B,U+FFFF;src:url(https://encore.scdn.co/fonts/CircularSpTitle-Bold-b2586b06a2e1522e9d879d84c2792a58.woff2)format("woff2"),url(https://encore.scdn.co/fonts/CircularSpTitle-Bold-1624fb2df28c20d7203d7fb86ce8b481.woff)format("woff")}@font-face{font-family:CircularSp;font-weight:700;font-display:swap;unicode-range:U+0,U+D,U+20-7E,U+A0-17E,U+18F,U+192,U+1A0-1A1,U+1AF-1B0,U+1B5-1B6,U+1C4-1C6,U+1F1-1F3,U+1FA-1FF,U+218-21B,U+237,U+259,U+2BB-2BC,U+2C6-2C7,U+2C9,U+2D8-2DD,U+300-301,U+303,U+309,U+323,U+394,U+3A9,U+3BC,U+3C0,U+1E80-1E85,U+1E8A-1E8B,U+1EA0-1EF9,U+1FD6,U+2007-2008,U+200B,U+2010-2011,U+2013-2014,U+2018-201A,U+201C-201E,U+2020-2022,U+2026,U+2030,U+2032-2033,U+2039-203A,U+2042,U+2044,U+2051,U+2070,U+2074-2079,U+2080-2089,U+20AB-20AC,U+2113,U+2117,U+2122,U+2126,U+2160-2169,U+216C-216F,U+2190-2193,U+2196-2199,U+21A9,U+21B0-21B5,U+21C6,U+2202,U+2206,U+220F,U+2211-2212,U+2215,U+2219-221A,U+221E,U+222B,U+2248,U+2260,U+2264-2265,U+22C5,U+24C5,U+25A0-25A1,U+25AF,U+25B2-25B3,U+25CA-25CB,U+25CF,U+262E,U+2713,U+2715,U+2780-2788,U+E000,U+E002,U+F6C3,U+FB00-FB04,U+FEFF,U+FF0C,U+FF0E,U+FF1A-FF1B,U+FFFF;src:url(https://encore.scdn.co/fonts/CircularSp-Bold-602e7aefc706aa36c6ec1324b9bbc461.woff2)format("woff2"),url(https://encore.scdn.co/fonts/CircularSp-Bold-856afe2da4ba4e61239b129e2c16d633.woff)format("woff")}@font-face{font-family:CircularSp;font-weight:400;font-display:swap;unicode-range:U+0,U+D,U+20-7E,U+A0-17E,U+18F,U+192,U+1A0-1A1,U+1AF-1B0,U+1B5-1B6,U+1C4-1C6,U+1F1-1F3,U+1FA-1FF,U+218-21B,U+237,U+259,U+2BB-2BC,U+2C6-2C7,U+2C9,U+2D8-2DD,U+300-301,U+303,U+309,U+323,U+394,U+3A9,U+3BC,U+3C0,U+1E80-1E85,U+1E8A-1E8B,U+1EA0-1EF9,U+1FD6,U+2007-2008,U+200B,U+2010-2011,U+2013-2014,U+2018-201A,U+201C-201E,U+2020-2022,U+2026,U+2030,U+2032-2033,U+2039-203A,U+2042,U+2044,U+2051,U+2070,U+2074-2079,U+2080-2089,U+20AB-20AC,U+2113,U+2117,U+2122,U+2126,U+2160-2169,U+216C-216F,U+2190-2193,U+2196-2199,U+21A9,U+21B0-21B5,U+21C6,U+2202,U+2206,U+220F,U+2211-2212,U+2215,U+2219-221A,U+221E,U+222B,U+2248,U+2260,U+2264-2265,U+22C5,U+24C5,U+25A0-25A1,U+25AF,U+25B2-25B3,U+25CA-25CB,U+25CF,U+262E,U+2713,U+2715,U+2780-2788,U+E000,U+E002,U+F6C3,U+FB00-FB04,U+FEFF,U+FF0C,U+FF0E,U+FF1A-FF1B,U+FFFF;src:url(https://encore.scdn.co/fonts/CircularSp-Book-a00e99ef9996a3a157fb6b746856d04f.woff2)format("woff2"),url(https://encore.scdn.co/fonts/CircularSp-Book-3f73da7d35bd81c706bce7bbb84964de.woff)format("woff")}@font-face{font-family:CircularSp;font-weight:700;font-display:swap;unicode-range:U+0,U+D,U+20-7E,U+A0-17E,U+18F,U+192,U+1A0-1A1,U+1AF-1B0,U+1B5-1B6,U+1C4-1C6,U+1F1-1F3,U+1FA-1FF,U+218-21B,U+237,U+259,U+2BB-2BC,U+2C6-2C7,U+2C9,U+2D8-2DD,U+300-301,U+303,U+309,U+323,U+394,U+3A9,U+3BC,U+3C0,U+1E80-1E85,U+1E8A-1E8B,U+1EA0-1EF9,U+1FD6,U+2007-2008,U+200B,U+2010-2011,U+2013-2014,U+2018-201A,U+201C-201E,U+2020-2022,U+2026,U+2030,U+2032-2033,U+2039-203A,U+2042,U+2044,U+2051,U+2070,U+2074-2079,U+2080-2089,U+20AB-20AC,U+2113,U+2117,U+2122,U+2126,U+2160-2169,U+216C-216F,U+2190-2193,U+2196-2199,U+21A9,U+21B0-21B5,U+21C6,U+2202,U+2206,U+220F,U+2211-2212,U+2215,U+2219-221A,U+221E,U+222B,U+2248,U+2260,U+2264-2265,U+22C5,U+24C5,U+25A0-25A1,U+25AF,U+25B2-25B3,U+25CA-25CB,U+25CF,U+262E,U+2713,U+2715,U+2780-2788,U+E000,U+E002,U+F6C3,U+FB00-FB04,U+FEFF,U+FF0C,U+FF0E,U+FF1A-FF1B,U+FFFF;src:url(https://encore.scdn.co/fonts/CircularSp-Bold-602e7aefc706aa36c6ec1324b9bbc461.woff2)format("woff2"),url(https://encore.scdn.co/fonts/CircularSp-Bold-856afe2da4ba4e61239b129e2c16d633.woff)format("woff")}[data-theme-name=spotify]{--bui-font-text:CircularSp,CircularSp-Arab,CircularSp-Hebr,CircularSp-Cyrl,CircularSp-Grek,CircularSp-Deva;--bui-font-title:CircularSpTitle,CircularSp-Arab,CircularSp-Hebr,CircularSp-Cyrl,CircularSp-Grek,CircularSp-Deva;--bui-font-regular:CircularSp,CircularSp-Arab,CircularSp-Hebr,CircularSp-Cyrl,CircularSp-Grek,CircularSp-Deva;& .bui-Button{border-radius:var(--bui-radius-3);padding-inline:var(--bui-space-3)}& .bui-ButtonIcon{padding:0}& .bui-MenuPopup{box-sizing:border-box;max-width:21.25rem}& .bui-MenuSubmenuTrigger,& .bui-MenuItem{height:auto;min-height:2rem}& .bui-Text{font-family:var(--bui-font-text)}& .bui-Heading{font-family:var(--bui-font-title)}& .bui-TableRow{border-radius:var(--bui-radius-4);border:none}& .bui-TableRow:hover td:first-child{border-top-left-radius:var(--bui-radius-2);border-bottom-left-radius:var(--bui-radius-2)}& .bui-TableRow:hover td:last-child{border-top-right-radius:var(--bui-radius-2);border-bottom-right-radius:var(--bui-radius-2)}& .bui-TableBody:before,& .bui-TableBody:after{line-height:var(--bui-space-1);content:"‌";display:block}& .bui-TableHeader .bui-TableRow{border-bottom:1px solid var(--bui-border)}& .bui-TableHead{font-size:var(--bui-font-size-2);color:var(--bui-fg-secondary);font-weight:var(--bui-font-weight-regular)}& .bui-HeaderToolbar{padding-top:var(--bui-space-2);padding-inline:var(--bui-space-2)}& .bui-HeaderToolbarWrapper{border-radius:var(--bui-radius-3);padding-inline:var(--bui-space-3);border:none}& .bui-HeaderToolbarControls{right:calc(var(--bui-space-3) - 1px)}& .bui-HeaderTabsWrapper{margin-top:var(--bui-space-2);margin-inline:var(--bui-space-2);border-radius:var(--bui-radius-3);padding-inline:var(--bui-space-1);border:none}& .bui-Input{border-radius:var(--bui-radius-3)}& .bui-Tag{border-radius:var(--bui-radius-full)}}[data-theme-mode=light][data-theme-name=spotify]{--bui-bg-solid:#1ed760;--bui-bg-solid-hover:#3be477;--bui-bg-solid-pressed:#1abc54;--bui-bg-solid-disabled:var(--bui-gray-2);--bui-fg-primary:var(--bui-black);--bui-fg-secondary:var(--bui-gray-7);--bui-fg-solid:var(--bui-black);--bui-border:var(--bui-gray-3);--bui-border-hover:#0000004d;--bui-border-pressed:#00000080;--bui-border-disabled:#0000001a;--bui-border-danger:#f87a7a;--bui-border-warning:#e36d05;--bui-border-success:#53db83;--bui-ring:#0003;& .bui-HeaderToolbarWrapper,& .bui-HeaderTabsWrapper{border:1px solid var(--bui-border)}}[data-theme-mode=dark][data-theme-name=spotify]{--bui-bg-surface-0:var(--bui-black);--bui-bg-solid:#1ed760;--bui-bg-solid-hover:#3be477;--bui-bg-solid-pressed:#1abc54;--bui-bg-solid-disabled:#0f6c30;--bui-bg-tint:#242424;--bui-bg-tint-hover:#202020;--bui-bg-tint-pressed:#292929;--bui-bg-tint-disabled:#fffc;--bui-bg-danger:#3b1219;--bui-bg-warning:#302008;--bui-bg-success:#132d21;--bui-fg-primary:var(--bui-white);--bui-fg-secondary:var(--bui-gray-7);--bui-fg-link:var(--bui-white);--bui-fg-link-hover:var(--bui-white);--bui-fg-disabled:var(--bui-gray-5);--bui-fg-solid:var(--bui-black);--bui-fg-solid-disabled:#083618;--bui-fg-tint:var(--bui-white);--bui-fg-tint-disabled:var(--bui-gray-5);--bui-fg-danger:#e22b2b;--bui-fg-warning:#e36d05;--bui-fg-success:#1db954;--bui-border:var(--bui-gray-3);--bui-border-hover:#fff6;--bui-border-pressed:#ffffff80;--bui-border-disabled:#fff3;--bui-border-danger:#f87a7a;--bui-border-warning:#e36d05;--bui-border-success:#53db83;--bui-ring:#fff3} \ No newline at end of file diff --git a/docs-ui/src/app/tokens/page.mdx b/docs-ui/src/app/tokens/page.mdx index 8e9031c81c..97266afbf4 100644 --- a/docs-ui/src/app/tokens/page.mdx +++ b/docs-ui/src/app/tokens/page.mdx @@ -187,7 +187,7 @@ These colors are used for special purposes like ring, scrollbar, ... ## Core background colors These colors are used for the background of your application. We are mostly using for now a -single elevated background for panels. `--bui-bg` should mostly use as the main background +single elevated background for panels. `--bui-bg-surface-0` should mostly use as the main background color of your app. @@ -200,7 +200,7 @@ color of your app. - --bui-bg + --bui-bg-surface-0 The background color of your Backstage instance. diff --git a/docs-ui/src/components/Snippet/styles.module.css b/docs-ui/src/components/Snippet/styles.module.css index 3141564293..ed5bd22def 100644 --- a/docs-ui/src/components/Snippet/styles.module.css +++ b/docs-ui/src/components/Snippet/styles.module.css @@ -7,7 +7,7 @@ .preview { border-radius: 8px; box-shadow: inset 0 0 0 1px var(--border); - background-color: var(--bui-bg); + background-color: var(--bui-bg-surface-0); padding: 1px; position: relative; } diff --git a/docs-ui/src/snippets/code-snippets.ts b/docs-ui/src/snippets/code-snippets.ts index 1a22a24340..57169ae32a 100644 --- a/docs-ui/src/snippets/code-snippets.ts +++ b/docs-ui/src/snippets/code-snippets.ts @@ -4,7 +4,7 @@ export const customTheme = `:root { --bui-font-regular: system-ui; --bui-font-weight-regular: 400; --bui-font-weight-bold: 600; - --bui-bg: #f8f8f8; + --bui-bg-surface-0: #f8f8f8; --bui-bg-surface-1: #fff; /* ... other CSS variables */ @@ -19,7 +19,7 @@ export const customTheme = `:root { --bui-font-regular: system-ui; --bui-font-weight-regular: 400; --bui-font-weight-bold: 600; - --bui-bg: #f8f8f8; + --bui-bg-surface-0: #f8f8f8; --bui-bg-surface-1: #fff; /* ... other CSS variables */ diff --git a/docs-ui/yarn.lock b/docs-ui/yarn.lock index 3634aca929..755b88ec09 100644 --- a/docs-ui/yarn.lock +++ b/docs-ui/yarn.lock @@ -854,10 +854,10 @@ __metadata: languageName: node linkType: hard -"@next/env@npm:15.5.7": - version: 15.5.7 - resolution: "@next/env@npm:15.5.7" - checksum: 10/11f971691018bd62a5bf253fc843fb2a6cf1431468f5c3a9d4d41753a6ff3e8bf7f539f46aba3f58f8bac59e681bf05fb5d771ac08d7dbd966a601257e1368bf +"@next/env@npm:15.5.9": + version: 15.5.9 + resolution: "@next/env@npm:15.5.9" + checksum: 10/962329701343c2617c85ae99ef35adfd9e8f7b58d9c0316f2f0857f82875a91ef3151ef0743c50964b0066aa3d1214c5193cf229f7757d7c9329f7fb95605a4a languageName: node linkType: hard @@ -1240,11 +1240,11 @@ __metadata: languageName: node linkType: hard -"@storybook/core@npm:8.6.14": - version: 8.6.14 - resolution: "@storybook/core@npm:8.6.14" +"@storybook/core@npm:8.6.15": + version: 8.6.15 + resolution: "@storybook/core@npm:8.6.15" dependencies: - "@storybook/theming": "npm:8.6.14" + "@storybook/theming": "npm:8.6.15" better-opn: "npm:^3.0.2" browser-assert: "npm:^1.2.1" esbuild: "npm:^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0" @@ -1260,7 +1260,7 @@ __metadata: peerDependenciesMeta: prettier: optional: true - checksum: 10/8f8c811edd4ea8dcedcc63a79b3168dc83aa0401e3760990cb5995ea6beaac4026c6ccc1046182f41eed7c09333005f3348d8b42f89fc5dd5b2ce011a9d2a48f + checksum: 10/d268d6fa00c38b35e5c363ee33779c2e087ab8e4681e0e205baa2fdb2780ea9feda3c9f6db35d60092778878d2782b2093c744bdf1af173c5688c3e1e0e960ac languageName: node linkType: hard @@ -1334,6 +1334,15 @@ __metadata: languageName: node linkType: hard +"@storybook/theming@npm:8.6.15": + version: 8.6.15 + resolution: "@storybook/theming@npm:8.6.15" + peerDependencies: + storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 + checksum: 10/f02760831a13d7af9dbfeb6feea949f4c13c897861cbc75253a6776d133891567889c8d99c7e91a99124d0772c3bde1f978984c83b19117d1d7c908ed7eb8409 + languageName: node + linkType: hard + "@swc/helpers@npm:0.5.15": version: 0.5.15 resolution: "@swc/helpers@npm:0.5.15" @@ -1416,12 +1425,12 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^20": - version: 20.19.11 - resolution: "@types/node@npm:20.19.11" +"@types/node@npm:^22.13.14": + version: 22.19.2 + resolution: "@types/node@npm:22.19.2" dependencies: undici-types: "npm:~6.21.0" - checksum: 10/7179ed464a781cad20117362df58c12839b40922b53356e1a74f86c99d9d1ef9a27edce360901608f896c247c9c4131ba9c7222331e92cde17b723c75d5c8f2e + checksum: 10/c7e72fde4aef120d984416f4aa01d23b0704eeed7a0a63cdf6178783361f3985abb02a65133b80f47226ad61f38a27fe82c3cd6dd6a62d5b82bc643fe54b9c97 languageName: node linkType: hard @@ -1618,8 +1627,8 @@ __metadata: linkType: hard "@uiw/codemirror-themes@npm:^4.23.7": - version: 4.25.3 - resolution: "@uiw/codemirror-themes@npm:4.25.3" + version: 4.25.4 + resolution: "@uiw/codemirror-themes@npm:4.25.4" dependencies: "@codemirror/language": "npm:^6.0.0" "@codemirror/state": "npm:^6.0.0" @@ -1628,7 +1637,7 @@ __metadata: "@codemirror/language": ">=6.0.0" "@codemirror/state": ">=6.0.0" "@codemirror/view": ">=6.0.0" - checksum: 10/f808ac3c4763f623ed6ea6215cc1421bb87234e0a05e7b6d9e917ab304fc6a4977c238996ca538e22093af8136c02bb27512aeeac653cb8fe82b4917ba1668a3 + checksum: 10/aab62e2c16a10dbde4592cef704d386c1a9e3caece4ff0eed85e9d9a5acdeaf3fd8717e2cb6a6795e12e890b8600956effb52d453aacbc618934e7ae8c3e59e3 languageName: node linkType: hard @@ -2188,9 +2197,9 @@ __metadata: linkType: hard "caniuse-lite@npm:^1.0.30001579": - version: 1.0.30001735 - resolution: "caniuse-lite@npm:1.0.30001735" - checksum: 10/4b404ed363a5ccf3ec07144c2360106aa47dcec1f896ea6705a2773c6977e9ffb19a2b58be9492462733170e29b4823211533b0986d5a25f0f65f7ff702470ab + version: 1.0.30001760 + resolution: "caniuse-lite@npm:1.0.30001760" + checksum: 10/ac5c13d00b946c3ace331d25379ed9d85743b1028aba79ae80402cb128b4b491122585144898fefb836d4d9879c13c717a081ae241a00420cbbc7e1b934ec685 languageName: node linkType: hard @@ -2521,7 +2530,7 @@ __metadata: "@shikijs/transformers": "npm:^3.13.0" "@storybook/react": "npm:^8.6.12" "@types/mdx": "npm:^2.0.13" - "@types/node": "npm:^20" + "@types/node": "npm:^22.13.14" "@types/react": "npm:19.1.9" "@types/react-dom": "npm:19.1.7" "@uiw/codemirror-themes": "npm:^4.23.7" @@ -2533,13 +2542,13 @@ __metadata: html-react-parser: "npm:^5.2.5" lightningcss: "npm:^1.28.2" motion: "npm:^12.4.1" - next: "npm:15.5.7" + next: "npm:15.5.9" next-mdx-remote-client: "npm:^2.1.2" prop-types: "npm:^15.8.1" react: "npm:19.1.1" react-dom: "npm:19.1.1" shiki: "npm:^3.13.0" - storybook: "npm:^8.6.12" + storybook: "npm:^8.6.15" typescript: "npm:^5" unified: "npm:^11.0.4" languageName: unknown @@ -3451,9 +3460,9 @@ __metadata: languageName: node linkType: hard -"framer-motion@npm:^12.23.25": - version: 12.23.25 - resolution: "framer-motion@npm:12.23.25" +"framer-motion@npm:^12.23.26": + version: 12.23.26 + resolution: "framer-motion@npm:12.23.26" dependencies: motion-dom: "npm:^12.23.23" motion-utils: "npm:^12.23.6" @@ -3469,7 +3478,7 @@ __metadata: optional: true react-dom: optional: true - checksum: 10/0b55dc0a5319cd923cdddcb42726352f0d74a8160f5222a3f090af53bbb2ed0d93c8482da41c9ffa875a3f7f666586e43be7594dca3612e70a1dea6bfbefebb4 + checksum: 10/29d51ac57ce8c2599664bf706d7a83c2aba4fe1dee1c0c7d75d5c45c120b1c2ca5d257c3ff608992b26bf8e9cf258cacf231b0873d7b16f01c5eeb42b9831f78 languageName: node linkType: hard @@ -5265,10 +5274,10 @@ __metadata: linkType: hard "motion@npm:^12.4.1": - version: 12.23.25 - resolution: "motion@npm:12.23.25" + version: 12.23.26 + resolution: "motion@npm:12.23.26" dependencies: - framer-motion: "npm:^12.23.25" + framer-motion: "npm:^12.23.26" tslib: "npm:^2.4.0" peerDependencies: "@emotion/is-prop-valid": "*" @@ -5281,7 +5290,7 @@ __metadata: optional: true react-dom: optional: true - checksum: 10/67e86dd3c695362812fd86d06e82bb53173900212a78802c94adbcff947e70316141ec6e2908fb3ebf70d3686578bb7fbe7a820a359ce553cd2d79ff77fc1428 + checksum: 10/c5e683d2c67e55816587cbbd451c5600dc0602aa04108ab0bf8d4472befd490e90b3177362dbc8b9f96316ec16383924cc574eb7c9e031540f1e88e64a2704ae languageName: node linkType: hard @@ -5342,11 +5351,11 @@ __metadata: languageName: node linkType: hard -"next@npm:15.5.7": - version: 15.5.7 - resolution: "next@npm:15.5.7" +"next@npm:15.5.9": + version: 15.5.9 + resolution: "next@npm:15.5.9" dependencies: - "@next/env": "npm:15.5.7" + "@next/env": "npm:15.5.9" "@next/swc-darwin-arm64": "npm:15.5.7" "@next/swc-darwin-x64": "npm:15.5.7" "@next/swc-linux-arm64-gnu": "npm:15.5.7" @@ -5397,7 +5406,7 @@ __metadata: optional: true bin: next: dist/bin/next - checksum: 10/bfac0cbac41b36227ec91d3a0727561f73dfc35d6a78eafd0200528ef95fa2e9d2dba5a8c8922864b4f4e4321ae6a07c6cf8f5766ac3192ad03e68516c3a458a + checksum: 10/ac27b82de08c9720e8e99cd64102af5e30306a8c861630d50da347a02c288cc441273ada64875c47e7a4d5991ff69cc92b23e906ce3271f9835a7911a0f060cc languageName: node linkType: hard @@ -6473,11 +6482,11 @@ __metadata: languageName: node linkType: hard -"storybook@npm:^8.6.12": - version: 8.6.14 - resolution: "storybook@npm:8.6.14" +"storybook@npm:^8.6.15": + version: 8.6.15 + resolution: "storybook@npm:8.6.15" dependencies: - "@storybook/core": "npm:8.6.14" + "@storybook/core": "npm:8.6.15" peerDependencies: prettier: ^2 || ^3 peerDependenciesMeta: @@ -6487,7 +6496,7 @@ __metadata: getstorybook: ./bin/index.cjs sb: ./bin/index.cjs storybook: ./bin/index.cjs - checksum: 10/104932fe29ebf49bef24c90285741cec964d1c36b3f0b38da1dace31ac664be457f2a510e41ba69fe8aa0d90c20e3446fec27d1ced41e5eefb3a9ca713d99e79 + checksum: 10/15762c79ec8444a46bc14cddfadbdd54dfd379828acd38555887a246c01e7c9ebb61e4eafafe04efb3ddf6278fb47035216e7f7d9f94fc205da148870173abdf languageName: node linkType: hard diff --git a/docs/api/utility-apis.md b/docs/api/utility-apis.md index 3e60124775..8d882227ec 100644 --- a/docs/api/utility-apis.md +++ b/docs/api/utility-apis.md @@ -10,31 +10,31 @@ Backstage plugins strive to be self-contained, with as much functionality as pos Backstage provides two primary methods for plugins to communicate across their boundaries in client-side code. The first one being the -[`createPlugin`](../reference/core-plugin-api.createplugin.md) API along with the +[`createPlugin`](https://backstage.io/api/stable/functions/_backstage_core-plugin-api.index.createPlugin.html) API along with the extensions that it can provide, and the second one being Utility APIs. While the -[`createPlugin`](../reference/core-plugin-api.createplugin.md) API is focused on +[`createPlugin`](https://backstage.io/api/stable/functions/_backstage_core-plugin-api.index.createPlugin.html) API is focused on the initialization plugins and the app, the Utility APIs provide ways for plugins to communicate during their entire life cycle. ## Consuming APIs -Each Utility API is tied to an [`ApiRef`](../reference/frontend-plugin-api.apiref.md) +Each Utility API is tied to an [`ApiRef`](https://backstage.io/api/stable/types/_backstage_frontend-plugin-api.ApiRef.html) instance, which is a global singleton object without any additional state or functionality, its only purpose is to reference Utility APIs. -[`ApiRef`](../reference/frontend-plugin-api.apiref.md)s are created using -[`createApiRef`](../reference/frontend-plugin-api.createapiref.md), which is exported -by [`@backstage/core-plugin-api`](../reference/core-plugin-api.md). There are also +[`ApiRef`](https://backstage.io/api/stable/types/_backstage_frontend-plugin-api.ApiRef.html)s are created using +[`createApiRef`](https://backstage.io/api/stable/functions/_backstage_frontend-plugin-api.createApiRef.html), which is exported +by [`@backstage/core-plugin-api`](https://backstage.io/api/stable/modules/_backstage_core-plugin-api.html). There are also many predefined Utility APIs in -[`@backstage/core-plugin-api`](../reference/core-plugin-api.md), and they're all +[`@backstage/core-plugin-api`](https://backstage.io/api/stable/modules/_backstage_core-plugin-api.html), and they're all exported with a name of the pattern `*ApiRef`, for example -[`errorApiRef`](../reference/frontend-plugin-api.errorapiref.md). +[`errorApiRef`](https://backstage.io/api/stable/variables/_backstage_frontend-plugin-api.errorApiRef.html). To access one of the Utility APIs inside a React component, use the -[`useApi`](../reference/frontend-plugin-api.useapi.md) hook exported by -[`@backstage/core-plugin-api`](../reference/core-plugin-api.md), or the -[`withApis`](../reference/frontend-plugin-api.withapis.md) HOC if you prefer class +[`useApi`](https://backstage.io/api/stable/functions/_backstage_frontend-plugin-api.useApi.html) hook exported by +[`@backstage/core-plugin-api`](https://backstage.io/api/stable/modules/_backstage_core-plugin-api.html), or the +[`withApis`](https://backstage.io/api/stable/functions/_backstage_frontend-plugin-api.withApis.html) HOC if you prefer class components. For example, the -[`ErrorApi`](../reference/frontend-plugin-api.errorapi.md) can be accessed like this: +[`ErrorApi`](https://backstage.io/api/stable/types/_backstage_frontend-plugin-api.ErrorApi.html) can be accessed like this: ```tsx import { useApi, errorApiRef } from '@backstage/core-plugin-api'; @@ -52,14 +52,14 @@ export const MyComponent = () => { ``` Note that there is no explicit type given for -[`ErrorApi`](../reference/frontend-plugin-api.errorapi.md). This is because the -[`errorApiRef`](../reference/frontend-plugin-api.errorapiref.md) has the type -embedded, and [`useApi`](../reference/frontend-plugin-api.useapi.md) is able to infer +[`ErrorApi`](https://backstage.io/api/stable/types/_backstage_frontend-plugin-api.ErrorApi.html). This is because the +[`errorApiRef`](https://backstage.io/api/stable/variables/_backstage_frontend-plugin-api.errorApiRef.html) has the type +embedded, and [`useApi`](https://backstage.io/api/stable/functions/_backstage_frontend-plugin-api.useApi.html) is able to infer the type. Also note that consuming Utility APIs is not limited to plugins; it can be done from any component inside Backstage, including the ones in -[`@backstage/core-plugin-api`](../reference/core-plugin-api.md). The only +[`@backstage/core-plugin-api`](https://backstage.io/api/stable/modules/_backstage_core-plugin-api.html). The only requirement is that they are beneath the `AppProvider` in the react tree. ## Supplying APIs @@ -67,15 +67,15 @@ requirement is that they are beneath the `AppProvider` in the react tree. ### API Factories APIs are registered in the form of -[`ApiFactory`](../reference/frontend-plugin-api.apifactory.md) instances, which encapsulate +[`ApiFactory`](https://backstage.io/api/stable/types/_backstage_frontend-plugin-api.ApiFactory.html) instances, which encapsulate the process of instantiating an API. It is a collection of three things: the -[`ApiRef`](../reference/frontend-plugin-api.apiref.md) of the API to instantiate, a +[`ApiRef`](https://backstage.io/api/stable/types/_backstage_frontend-plugin-api.ApiRef.html) of the API to instantiate, a list of all required dependencies, and a factory function that returns a new API instance. For example, this is the default -[`ApiFactory`](../reference/frontend-plugin-api.apifactory.md) for the -[`ErrorApi`](../reference/frontend-plugin-api.errorapi.md): +[`ApiFactory`](https://backstage.io/api/stable/types/_backstage_frontend-plugin-api.ApiFactory.html) for the +[`ErrorApi`](https://backstage.io/api/stable/types/_backstage_frontend-plugin-api.ErrorApi.html): ```ts createApiFactory({ @@ -89,25 +89,25 @@ createApiFactory({ }); ``` -In this example, the [`errorApiRef`](../reference/frontend-plugin-api.errorapiref.md) +In this example, the [`errorApiRef`](https://backstage.io/api/stable/variables/_backstage_frontend-plugin-api.errorApiRef.html) is our API, which encapsulates the -[`ErrorApi`](../reference/frontend-plugin-api.errorapi.md) type. The -[`alertApiRef`](../reference/frontend-plugin-api.alertapiref.md) is our single +[`ErrorApi`](https://backstage.io/api/stable/types/_backstage_frontend-plugin-api.ErrorApi.html) type. The +[`alertApiRef`](https://backstage.io/api/stable/variables/_backstage_frontend-plugin-api.alertApiRef.html) is our single dependency, which we give the name `alertApi`, and is then passed on to the factory function, which returns an implementation of the -[`ErrorApi`](../reference/frontend-plugin-api.errorapi.md). +[`ErrorApi`](https://backstage.io/api/stable/types/_backstage_frontend-plugin-api.ErrorApi.html). -The [`createApiFactory`](../reference/frontend-plugin-api.createapifactory.md) +The [`createApiFactory`](https://backstage.io/api/stable/functions/_backstage_frontend-plugin-api.createApiFactory.html) function is a thin wrapper that enables TypeScript type inference. You may notice that there are no type annotations in the above example, and that is because we're able to infer all types from the -[`ApiRef`](../reference/frontend-plugin-api.apiref.md)s. TypeScript will make sure +[`ApiRef`](https://backstage.io/api/stable/types/_backstage_frontend-plugin-api.ApiRef.html)s. TypeScript will make sure that the return value of the `factory` function matches the type embedded in -`api`'s [`ApiRef`](../reference/frontend-plugin-api.apiref.md), in this case the -[`ErrorApi`](../reference/frontend-plugin-api.errorapi.md). It will also match the +`api`'s [`ApiRef`](https://backstage.io/api/stable/types/_backstage_frontend-plugin-api.ApiRef.html), in this case the +[`ErrorApi`](https://backstage.io/api/stable/types/_backstage_frontend-plugin-api.ErrorApi.html). It will also match the types between the `deps` and the parameters of the `factory` function, again using the type embedded within the -[`ApiRef`](../reference/frontend-plugin-api.apiref.md)s. +[`ApiRef`](https://backstage.io/api/stable/types/_backstage_frontend-plugin-api.ApiRef.html)s. ## Registering API Factories @@ -119,13 +119,13 @@ app, and the app itself. Starting with the Backstage core library, it provides implementations for all of the core APIs. The core APIs are the ones exported by -[`@backstage/core-plugin-api`](../reference/core-plugin-api.md), such as the -[`errorApiRef`](../reference/frontend-plugin-api.errorapiref.md) and -[`configApiRef`](../reference/frontend-plugin-api.configapiref.md). +[`@backstage/core-plugin-api`](https://backstage.io/api/stable/modules/_backstage_core-plugin-api.html), such as the +[`errorApiRef`](https://backstage.io/api/stable/variables/_backstage_frontend-plugin-api.errorApiRef.html) and +[`configApiRef`](https://backstage.io/api/stable/variables/_backstage_frontend-plugin-api.configApiRef.html). The core APIs are loaded for any app created with -[`createApp`](../reference/app-defaults.createapp.md) from -[`@backstage/core-plugin-api`](../reference/app-defaults.md), which means that +[`createApp`](https://backstage.io/api/stable/functions/_backstage_app-defaults.createApp.html) from +[`@backstage/core-plugin-api`](https://backstage.io/api/stable/modules/_backstage_core-plugin-api.html), which means that there is no step that needs to be taken to include these APIs in an app. ### Plugin APIs @@ -133,13 +133,13 @@ there is no step that needs to be taken to include these APIs in an app. In addition to the core APIs, plugins can define and export their own APIs. While doing so, they should usually also provide default implementations of their own APIs; for example, the `catalog` plugin exports `catalogApiRef` and also -supplies a default [`ApiFactory`](../reference/frontend-plugin-api.apifactory.md) of +supplies a default [`ApiFactory`](https://backstage.io/api/stable/types/_backstage_frontend-plugin-api.ApiFactory.html) of that API using the `CatalogClient`. There is one restriction to plugin-provided API Factories: plugins may not supply factories for core APIs; trying to do so will cause the app to refuse to start. Plugins supply their APIs through the `apis` option of -[`createPlugin`](../reference/core-plugin-api.createplugin.md), for example: +[`createPlugin`](https://backstage.io/api/stable/functions/_backstage_core-plugin-api.index.createPlugin.html), for example: ```ts export const techdocsPlugin = createPlugin({ @@ -164,7 +164,7 @@ Lastly, the app itself is the final point where APIs can be added, and what has the final say in what APIs will be loaded at runtime? The app may override the factories for any of the core or plugin APIs, with the exception of the config, app theme, and identity APIs. These are static APIs that are tied into the -[`createApp`](../reference/app-defaults.createapp.md) implementation and +[`createApp`](https://backstage.io/api/stable/functions/_backstage_app-defaults.createApp.html) implementation and therefore, not possible to override. Overriding APIs is useful for apps that want to switch out behavior to tailor it @@ -227,33 +227,33 @@ const app = createApp({ ``` Note that the above line will cause an error if `IgnoreErrorApi` does not fully -implement the [`ErrorApi`](../reference/frontend-plugin-api.errorapi.md), as it is +implement the [`ErrorApi`](https://backstage.io/api/stable/types/_backstage_frontend-plugin-api.ErrorApi.html), as it is checked by the type embedded in the -[`errorApiRef`](../reference/frontend-plugin-api.errorapiref.md) at compile time. +[`errorApiRef`](https://backstage.io/api/stable/variables/_backstage_frontend-plugin-api.errorApiRef.html) at compile time. ## Defining custom Utility APIs Plugins are free to define their own Utility APIs. Simply define the TypeScript interface for the API and create an -[`ApiRef`](../reference/frontend-plugin-api.apiref.md) using -[`createApiRef`](../reference/frontend-plugin-api.createapiref.md) exported from -[`@backstage/core-plugin-api`](../reference/core-plugin-api.md). Also, be sure to +[`ApiRef`](https://backstage.io/api/stable/types/_backstage_frontend-plugin-api.ApiRef.html) using +[`createApiRef`](https://backstage.io/api/stable/functions/_backstage_frontend-plugin-api.createApiRef.html) exported from +[`@backstage/core-plugin-api`](https://backstage.io/api/stable/modules/_backstage_core-plugin-api.html). Also, be sure to provide at least one implementation of the API and to declare a default factory -for the API in [`createPlugin`](../reference/core-plugin-api.createplugin.md). +for the API in [`createPlugin`](https://backstage.io/api/stable/functions/_backstage_core-plugin-api.index.createPlugin.html). Custom Utility APIs can be either public or private, which is up to the plugin to choose. Private APIs do not expose an external API surface, and it's therefore possible to make breaking changes to the API without affecting other users of the plugin. If an API is made public, however, it opens up for other plugins to make use of the API, and it also makes it possible for users for your plugin to override the API in the app. It is, however, important to maintain backward compatibility of public APIs, as you may otherwise break apps that are using your plugin. To make an API public, simply export the -[`ApiRef`](../reference/frontend-plugin-api.apiref.md) of the API, and any associated +[`ApiRef`](https://backstage.io/api/stable/types/_backstage_frontend-plugin-api.ApiRef.html) of the API, and any associated types. To make an API private, just avoid exporting the -[`ApiRef`](../reference/frontend-plugin-api.apiref.md), but still be sure to supply a -default factory to [`createPlugin`](../reference/core-plugin-api.createplugin.md). +[`ApiRef`](https://backstage.io/api/stable/types/_backstage_frontend-plugin-api.ApiRef.html), but still be sure to supply a +default factory to [`createPlugin`](https://backstage.io/api/stable/functions/_backstage_core-plugin-api.index.createPlugin.html). Private APIs are useful for plugins that want to depend on other APIs outside of React components, but not have to expose an entire API surface to maintain. When using private APIs, it is fine to use the `typeof` of an implementing class as the type parameter passed to -[`createApiRef`](../reference/frontend-plugin-api.createapiref.md), while public APIs +[`createApiRef`](https://backstage.io/api/stable/functions/_backstage_frontend-plugin-api.createApiRef.html), while public APIs should always define a separate TypeScript interface type. Plugins may depend on APIs from other plugins, both in React components and as @@ -262,13 +262,13 @@ dependencies between plugins. ## Architecture -The [`ApiRef`](../reference/frontend-plugin-api.apiref.md) instances mentioned above +The [`ApiRef`](https://backstage.io/api/stable/types/_backstage_frontend-plugin-api.ApiRef.html) instances mentioned above provide a point of indirection between consumers and producers of Utility APIs. It allows for plugins and components to depend on APIs in a type-safe way, without having a direct reference to a concrete implementation of the APIs. The Apps are also given a lot of flexibility in what implementations to provide. As long as they adhere to the contract established by an -[`ApiRef`](../reference/frontend-plugin-api.apiref.md), they are free to choose any +[`ApiRef`](https://backstage.io/api/stable/types/_backstage_frontend-plugin-api.ApiRef.html), they are free to choose any implementation they want. The figure below shows the relationship between @@ -291,16 +291,16 @@ The indirection provided by Utility APIs also makes it straightforward to test components that depend on APIs, and to provide a standard common development environment for plugins. A proper test wrapper with mocked API implementations is not yet ready, but it will be provided as a part of -[`@backstage/test-utils`](../reference/test-utils.md). It will provide mocked +[`@backstage/test-utils`](https://backstage.io/api/stable/modules/_backstage_test-utils.html). It will provide mocked variants of APIs, with additional methods for asserting a component's interaction with the API. The common development environment for plugins is included in -[`@backstage/dev-utils`](../reference/dev-utils.md), where the exported -[`createDevApp`](../reference/dev-utils.createdevapp.md) function creates an +[`@backstage/dev-utils`](https://backstage.io/api/stable/modules/_backstage_dev-utils.html), where the exported +[`createDevApp`](https://backstage.io/api/stable/functions/_backstage_dev-utils.createDevApp.html) function creates an application with implementations for all core APIs already present. Contrary to the method for wiring up Utility API implementations in an app created with -[`createApp`](../reference/app-defaults.createapp.md), -[`createDevApp`](../reference/dev-utils.createdevapp.md) uses automatic dependency +[`createApp`](https://backstage.io/api/stable/functions/_backstage_app-defaults.createApp.html), +[`createDevApp`](https://backstage.io/api/stable/functions/_backstage_dev-utils.createDevApp.html) uses automatic dependency injection. This is to make it possible to replace any API implementation, and having that be reflected in dependents of that API. diff --git a/docs/auth/index.md b/docs/auth/index.md index bff1f3df26..1d668f6961 100644 --- a/docs/auth/index.md +++ b/docs/auth/index.md @@ -340,7 +340,7 @@ The method with which frontend plugins request access to third-party services is through [Utility APIs](../api/utility-apis.md) for each service provider. These are all suffixed with `*AuthApiRef`, for example `githubAuthApiRef`. For a full list of providers, see the -[@backstage/core-plugin-api](../reference/core-plugin-api.md#variables) reference. +[@backstage/core-plugin-api](https://backstage.io/api/stable/modules/_backstage_core-plugin-api.index.html#alertapiref) reference. ## Custom Authentication Provider @@ -459,6 +459,42 @@ providerFactories: { }, ``` +In the new backend system you can leverage the `authProvidersExtensionPoint` for this: + +```ts +// your-auth-plugin-module.ts +export const gheAuth = createBackendModule({ + // This ID must be exactly "auth" because that's the plugin it targets + pluginId: 'auth', + // This ID must be unique, but can be anything + moduleId: 'ghe-auth-provider', + register(reg) { + reg.registerInit({ + deps: { + providers: authProvidersExtensionPoint, + logger: coreServices.logger, + }, + async init({ providers, logger }) { + providers.registerProvider({ + // This ID must match the actual provider config, e.g. addressing + // auth.providers.ghe means that this must be "ghe". + providerId: 'ghe', + factory: createOAuthProviderFactory({ + authenticator: githubAuthenticator, + signInResolverFactories: { + ...commonSignInResolvers, + }, + }), + }); + }, + }); + }, +}); + +// backend index.ts +backend.add(gheAuth); +``` + ## Configuring token issuers By default, the Backstage authentication backend generates and manages its own signing keys automatically for any issued diff --git a/docs/auth/oidc.md b/docs/auth/oidc.md index 7c4b09d9bf..55827ab1dc 100644 --- a/docs/auth/oidc.md +++ b/docs/auth/oidc.md @@ -241,6 +241,12 @@ These parameters have implicit default values. Don't override them unless you kn - `prompt`: Recommended to use `auto` so the browser will request sign-in to the IDP if the user has no active session. - `sessionDuration`: Lifespan of the user session. +- `startUrlSearchParams`: This is a dictionary of search (query) parameters for the OIDC + authorization start URL. Don't define it unless you want to change the identity + provider's behavior. (For example, you could set the `organization` parameter to guide + users towards a particular sign-in option that your organization prefers.) **Note:** the + start URL is controlled by the browser, so this feature is only for improving the + Backstage user experience. :::note Config Reloading Backstage does not yet support hot reloading of auth provider configuration. Any changes to this YAML file require a restart of Backstage. diff --git a/docs/backend-system/core-services/cache.md b/docs/backend-system/core-services/cache.md index ad4d04b50a..a23332409b 100644 --- a/docs/backend-system/core-services/cache.md +++ b/docs/backend-system/core-services/cache.md @@ -11,24 +11,84 @@ This service lets your plugin interact with a cache. It is bound to your plugin The cache service can be configured using the `backend.cache` section in your `app-config.yaml`: +### In-Memory (default) + ```yaml backend: cache: - store: redis # or 'valkey', 'memcache', 'memory' + store: memory +``` + +### Memcache + +```yaml +backend: + cache: + store: memcache + connection: user:pass@cache.example.com:11211 +``` + +### Redis + +```yaml +backend: + cache: + store: redis connection: redis://localhost:6379 - # Store-specific configuration (Redis/Valkey only) + # Store-specific configuration (optional) redis: client: - # Optional: Global namespace prefix for all cache keys + # Global namespace prefix for all cache keys namespace: 'my-app' - # Optional: Separator used between namespace and plugin ID (default: ':') + # Separator used between namespace and plugin ID (default: ':') keyPrefixSeparator: ':' # Other Redis-specific options... clearBatchSize: 1000 useUnlink: false ``` +### Valkey + +```yaml +backend: + cache: + store: valkey + connection: redis://localhost:6379 + + # Store-specific configuration (optional) + valkey: + # Global namespace prefix for all cache keys (including separator used between namespace and plugin ID) + keyPrefix: 'my-app:' +``` + +### Infinispan + +```yaml +backend: + cache: + store: infinispan + + # Store-specific configuration (optional) + infinispan: + servers: + # IP address or hostname of the server (default: '127.0.0.1') + - host: 127.0.0.1 + # Port number of the server (default: '11222') + port: 11222 + # Name of the cache (default: 'cache') + cacheName: cache + mediaType: application/json + authentication: + # Whether authentication is enabled (default: 'false') + enabled: true + userName: yourusername + password: yourpassword + saslMechanism: PLAIN +``` + +A full list of configuration items is available [here](https://docs.jboss.org/infinispan/hotrod-clients/javascript/1.0/apidocs/module-infinispan.html), including support for backup clusters. + ### Namespace Configuration For Redis and Valkey stores, you can configure a global namespace that will be prefixed to all cache keys: @@ -36,9 +96,10 @@ For Redis and Valkey stores, you can configure a global namespace that will be p - **Without namespace**: Cache keys use only the plugin ID (e.g., `catalog:some-key`) - **With namespace**: Cache keys use the format `namespace:pluginId:key` (e.g., `my-app:catalog:some-key`) -The `keyPrefixSeparator` controls what character is used between the namespace and plugin ID (defaults to `:`). +For **Redis**, `keyPrefixSeparator` controls what character is used between the namespace and plugin ID (defaults to `:`). +For **Valkey**, you set the full `keyPrefix` including the separator. -**Note**: Memory and Memcache stores do not support namespace configuration and will always use the plugin ID directly. +**Note**: In-memory, Memcache and Infinispan stores do not support namespace configuration and will always use the plugin ID directly. ## Using the service diff --git a/docs/conf/reading.md b/docs/conf/reading.md index a565f3a8a3..b6119b0da9 100644 --- a/docs/conf/reading.md +++ b/docs/conf/reading.md @@ -7,7 +7,7 @@ description: Documentation on Reading Backstage Configuration ## Config API There's a common configuration API for by both frontend and backend plugins. An -API reference can be found [here](../reference/config.config.md). +API reference can be found [here](https://backstage.io/api/stable/types/_backstage_config.Config.html). The configuration API is tailored towards failing fast in case of missing or bad config. That's because configuration errors can always be considered programming @@ -115,7 +115,7 @@ example `getString`. These will throw an error if there is no value available. ## Accessing ConfigApi in Frontend Plugins -The [ConfigApi](../reference/frontend-plugin-api.configapi.md) in the frontend is a +The [ConfigApi](https://backstage.io/api/stable/types/_backstage_frontend-plugin-api.ConfigApi.html) in the frontend is a [UtilityApi](../api/utility-apis.md). It's accessible as usual via the `configApiRef` exported from `@backstage/core-plugin-api`: diff --git a/docs/conf/user-interface/index.md b/docs/conf/user-interface/index.md index 81acfdf720..e0fb645d78 100644 --- a/docs/conf/user-interface/index.md +++ b/docs/conf/user-interface/index.md @@ -103,13 +103,13 @@ Backstage UI is using light by default under `:root` but you can target it more [data-theme-mode='light'] { /* Light theme specific styles */ -  --bui-bg: #f8f8f8; +  --bui-bg-surface-0: #f8f8f8; --bui-fg-primary: #000; } [data-theme-mode='dark'] { /* Dark theme specific styles */ -  --bui-bg: #333333; +  --bui-bg-surface-0: #333333; --bui-fg-primary: #fff; } ``` @@ -122,18 +122,18 @@ We recommend starting with a core set of CSS variables to quickly achieve a bran And if you’d like to go even further, you can target specific component class names for advanced customization. -| Token Name | Description | -| -------------------- | ----------------------------------------------------------------------------------- | -| `--bui-bg` | This is used to define the background color of your app. It will only be used once. | -| `--bui-bg-surface-1` | We ar using this color to sit on top of `--bui-bg` mostly for `Card`, `Dialog`, ... | -| `--bui-bg-surface-2` | This is for content inside elevated components. This colour is less common. | -| `--bui-bg-solid` | This is used for main actions like primary buttons. | -| `--bui-fg-solid` | This is for texts or icons on top of a solid backgrounds. | -| `--bui-fg-primary` | Your primary text or icon colours. | -| `--bui-fg-secondary` | Your secondary text or icon colours. | -| `--bui-fg-link` | Used for links. | -| `--bui-border` | Main borders around surfaces like `Card`, `Dialog`, ... | -| `--bui-font-regular` | The main font of your app. | +| Token Name | Description | +| -------------------- | --------------------------------------------------------------------------------------------- | +| `--bui-bg-surface-0` | This is used to define the background color of your app. It will only be used once. | +| `--bui-bg-surface-1` | We ar using this color to sit on top of `--bui-bg-surface-0` mostly for `Card`, `Dialog`, ... | +| `--bui-bg-surface-2` | This is for content inside elevated components. This colour is less common. | +| `--bui-bg-solid` | This is used for main actions like primary buttons. | +| `--bui-fg-solid` | This is for texts or icons on top of a solid backgrounds. | +| `--bui-fg-primary` | Your primary text or icon colours. | +| `--bui-fg-secondary` | Your secondary text or icon colours. | +| `--bui-fg-link` | Used for links. | +| `--bui-border` | Main borders around surfaces like `Card`, `Dialog`, ... | +| `--bui-font-regular` | The main font of your app. |
All available CSS variables @@ -157,13 +157,14 @@ These colors are used for special purposes like ring, scrollbar, ... #### Core background colors -These colors are used for the background of your application. We are mostly using for now a single elevated background for panels. `--bui-bg` should mostly use as the main background color of your app. +These colors are used for the background of your application. We are mostly using for now a single elevated background for panels. `--bui-bg-surface-0` should mostly use as the main background color of your app. | Token Name | Description | | ------------------------- | ------------------------------------------------ | -| `--bui-bg` | The background color of your Backstage instance. | +| `--bui-bg-surface-0` | The background color of your Backstage instance. | | `--bui-bg-surface-1` | Use for any panels or elevated surfaces. | | `--bui-bg-surface-2` | Use for any panels or elevated surfaces. | +| `--bui-bg-surface-3` | Use for any panels or elevated surfaces. | | `--bui-bg-solid` | Used for solid background colors. | | `--bui-bg-solid-hover` | Used for solid background colors when hovered. | | `--bui-bg-solid-pressed` | Used for solid background colors when pressed. | diff --git a/docs/deployment/scaling.md b/docs/deployment/scaling.md index 2c3b687f67..dd765d3c1a 100644 --- a/docs/deployment/scaling.md +++ b/docs/deployment/scaling.md @@ -17,7 +17,7 @@ into multiple different services, each running a different set of plugins. This is a more advanced approach and requires you to be able to route requests to the appropriate backends based on the plugin ID. Both for ingress, but also internal traffic between Backstage backends, which is done by creating a custom -implementation of the [DiscoveryService](../reference/backend-plugin-api.discoveryservice.md) interface. See the [backend system docs](../backend-system/building-backends/01-index.md#split-into-multiple-backends) for more details on how to separate your deployment into multiple backend instances. +implementation of the [DiscoveryService](https://backstage.io/api/stable/interfaces/_backstage_backend-plugin-api.index.DiscoveryService.html) interface. See the [backend system docs](../backend-system/building-backends/01-index.md#split-into-multiple-backends) for more details on how to separate your deployment into multiple backend instances. Lastly, you can also replicate the Backstage deployments across multiple regions. This is not a pattern that there is built-in support for and typically only makes diff --git a/docs/features/software-templates/ui-options-examples.md b/docs/features/software-templates/ui-options-examples.md index 1a024569a6..845da8e60b 100644 --- a/docs/features/software-templates/ui-options-examples.md +++ b/docs/features/software-templates/ui-options-examples.md @@ -468,3 +468,59 @@ repoUrl: The supported `additionalScopes` values are `gerrit`, `github`, `gitlab`, `bitbucket`, and `azure`. If you're also using the `RepoUrlPicker` field extension, you should simply duplicate this part from there. + +## RepoOwnerPicker + +The input props that can be specified under `ui:options` for the `RepoOwnerPicker` field extension. + +### `host` + +The SCM integration host that owners should be fetched from for autocompletion. + +- Fetch owners from `github.com` + +```yaml +repoUrl: + title: Repository Owner + type: string + ui:field: RepoOwnerPicker + ui:options: + host: github.com +``` + +### `excludedOwners` + +List of owners that should be excluded from autocompletion. + +- Exclude owner `owner_1` from autocompletion + +```yaml +repoUrl: + title: Repository Owner + type: string + ui:field: RepoOwnerPicker + ui:options: + excludedOwners: + - owner_1 +``` + +### `requestUserCredentials` + +If defined will request user credentials to auth against the given SCM platform. + +```yaml +repoUrl: + title: Repository Owner + type: string + ui:field: RepoOwnerPicker + ui:options: + requestUserCredentials: + secretsKey: USER_OAUTH_TOKEN + additionalScopes: + github: + - workflow:write +``` + +`secretsKey` is the key used within the template secrets context to store the credential and `additionalScopes` is any additional permission scopes to request. + +The supported `additionalScopes` values are `gerrit`, `github`, `gitlab`, `bitbucket`, and `azure`. diff --git a/docs/features/software-templates/writing-templates.md b/docs/features/software-templates/writing-templates.md index 32f17f945f..5d9fcba603 100644 --- a/docs/features/software-templates/writing-templates.md +++ b/docs/features/software-templates/writing-templates.md @@ -555,6 +555,35 @@ The `RepoBranchPicker` is a custom field that we provide part of the `plugin-scaffolder`. You can provide your own custom fields by [writing your own Custom Field Extensions](./writing-custom-field-extensions.md) +### The Repository Owner Picker + +Similar to the repository picker, there is a picker for owners to support autocompletion. A full example could look like this: + +```yaml +- title: Choose an owner + required: + - repoOwner + properties: + repoOwner: + title: Repository Owner + type: string + ui:field: RepoOwnerPicker + ui:options: + host: github.com + excludedOwners: + - backstage + requestUserCredentials: + secretsKey: USER_OAUTH_TOKEN +``` + +Passing the `requestUserCredentials` and `host` properties is required for autocompletion to work. For more information regarding the `requestUserCredentials` object, please refer to the [Using the Users `oauth` token](#using-the-users-oauth-token) section under [The Repository Picker](#the-repository-picker). + +For a list of all possible `ui:options` input props for `RepoOwnerPicker`, please visit [here](./ui-options-examples.md#repoownerpicker). + +The `RepoOwnerPicker` is a custom field that we provide part of the +`plugin-scaffolder`. You can provide your own custom fields by +[writing your own Custom Field Extensions](./writing-custom-field-extensions.md) + ### Accessing the signed-in users details Sometimes when authoring templates, you'll want to access the user that is running the template, and get details from the profile or the users `Entity` in the Catalog. diff --git a/docs/frontend-system/building-plugins/01-index.md b/docs/frontend-system/building-plugins/01-index.md index 283c162fa7..fd88478b37 100644 --- a/docs/frontend-system/building-plugins/01-index.md +++ b/docs/frontend-system/building-plugins/01-index.md @@ -220,6 +220,6 @@ export const examplePlugin = createFrontendPlugin({ }); ``` -The `ExampleEntityContent` itself is again a regular React component where you can implement any functionality you want. To access the entity that the content is being rendered for, you can use the `useEntity` hook from `@backstage/plugin-catalog-react`. You can see a full list of APIs provided by the catalog React library in [the API reference](../../reference/plugin-catalog-react.md). +The `ExampleEntityContent` itself is again a regular React component where you can implement any functionality you want. To access the entity that the content is being rendered for, you can use the `useEntity` hook from `@backstage/plugin-catalog-react`. You can see a full list of APIs provided by the catalog React library in [the API reference](https://backstage.io/api/stable/modules/_backstage_plugin-catalog-react.index.html). For a more complete list of the different kinds of extensions that you can create for your plugin, see the [extension blueprints](./03-common-extension-blueprints.md) section. diff --git a/docs/frontend-system/building-plugins/03-common-extension-blueprints.md b/docs/frontend-system/building-plugins/03-common-extension-blueprints.md index 71989e898f..abac1f03f5 100644 --- a/docs/frontend-system/building-plugins/03-common-extension-blueprints.md +++ b/docs/frontend-system/building-plugins/03-common-extension-blueprints.md @@ -11,35 +11,35 @@ This section covers many of the [extension blueprints](../architecture/23-extens These are the [extension blueprints](../architecture/23-extension-blueprints.md) provided by the Backstage frontend framework itself. -### Api - [Reference](../../reference/frontend-plugin-api.apiblueprint.md) +### Api - [Reference](https://backstage.io/api/stable/variables/_backstage_frontend-plugin-api.ApiBlueprint.html) An API extension is used to add or override [Utility API factories](../utility-apis/01-index.md) in the app. They are commonly used by plugins for both internal and shared APIs. There are also many built-in Api extensions provided by the framework that you are able to override. -### NavItem - [Reference](../../reference/frontend-plugin-api.navitemblueprint.md) +### NavItem - [Reference](https://backstage.io/api/stable/variables/_backstage_frontend-plugin-api.NavItemBlueprint.html) Navigation item extensions are used to provide menu items that link to different parts of the app. By default nav items are attached to the app nav extension, which by default is rendered as the left sidebar in the app. -### Page - [Reference](../../reference/frontend-plugin-api.pageblueprint.md) +### Page - [Reference](https://backstage.io/api/stable/variables/_backstage_frontend-plugin-api.PageBlueprint.html) Page extensions provide content for a particular route in the app. By default pages are attached to the app routes extensions, which renders the root routes. -### SignInPage - [Reference](../../reference/frontend-plugin-api.signinpageblueprint.md) +### SignInPage - [Reference](https://backstage.io/api/stable/variables/_backstage_frontend-plugin-api.SignInPageBlueprint.html) Sign-in page extension have a single purpose - to implement a custom sign-in page. They are always attached to the app root extension and are rendered before the rest of the app until the user is signed in. -### SwappableComponent - [Reference](../../reference/frontend-plugin-api.swappablecomponentblueprint.md) +### SwappableComponent - [Reference](https://backstage.io/api/stable/variables/_backstage_frontend-plugin-api.SwappableComponentBlueprint.html) Swappable Components are extensions that are used to replace the implementations of components in the app and plugins. -### Theme - [Reference](../../reference/frontend-plugin-api.themeblueprint.md) +### Theme - [Reference](https://backstage.io/api/stable/variables/_backstage_frontend-plugin-api.ThemeBlueprint.html) Theme extensions provide custom themes for the app. They are always attached to the app extension and you can have any number of themes extensions installed in an app at once, letting the user choose which theme to use. -### Icons - [Reference](../../reference/frontend-plugin-api.iconbundleblueprint.md) +### Icons - [Reference](https://backstage.io/api/stable/variables/_backstage_frontend-plugin-api.IconBundleBlueprint.html) Icon bundle extensions provide the ability to replace or provide new icons to the app. You can use the above blueprint to make new extension instances which can be installed into the app. -### Translation - [Reference](../../reference/frontend-plugin-api.translationblueprint.md) +### Translation - [Reference](https://backstage.io/api/stable/variables/_backstage_frontend-plugin-api.TranslationBlueprint.html) Translation extension provide custom translation messages for the app. They can be used both to override the default english messages to custom ones, as well as provide translations for additional languages. diff --git a/docs/integrations/bitbucketCloud/discovery.md b/docs/integrations/bitbucketCloud/discovery.md index e0fab954ac..3f5920be5d 100644 --- a/docs/integrations/bitbucketCloud/discovery.md +++ b/docs/integrations/bitbucketCloud/discovery.md @@ -54,6 +54,8 @@ You need to decide how you want to receive events from external sources like - [via HTTP endpoint](https://github.com/backstage/backstage/tree/master/plugins/events-backend/README.md) - [via an AWS SQS queue](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-aws-sqs/README.md) +- [via Google Pub/Sub](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-google-pubsub/README.md) +- [via a Kafka topic](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-kafka/README.md) Further documentation: @@ -72,6 +74,8 @@ Additionally, you need to decide how you want to receive events from external so - [via HTTP endpoint](https://github.com/backstage/backstage/tree/master/plugins/events-backend/README.md) - [via an AWS SQS queue](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-aws-sqs/README.md) +- [via Google Pub/Sub](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-google-pubsub/README.md) +- [via a Kafka topic](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-kafka/README.md) Set up your provider diff --git a/docs/integrations/bitbucketCloud/locations.md b/docs/integrations/bitbucketCloud/locations.md index 6b735171a4..807076c9e9 100644 --- a/docs/integrations/bitbucketCloud/locations.md +++ b/docs/integrations/bitbucketCloud/locations.md @@ -32,6 +32,15 @@ integrations: appPassword: my-password ``` +OAuth 2.0 client credentials flow: + +```yaml +integrations: + bitbucketCloud: + - clientId: client-id + clientSecret: client-secret +``` + :::note Note A public Bitbucket Cloud provider is added automatically at startup for @@ -41,7 +50,7 @@ convenience, so you only need to list it if you want to supply credentials. :::note Note -The credential required for this type is either an [Api token](https://support.atlassian.com/bitbucket-cloud/docs/using-api-tokens/) or an [App Password](https://support.atlassian.com/bitbucket-cloud/docs/app-passwords/). An Atlassian Account API key will not work. +The credential required for this type is either an [Api token](https://support.atlassian.com/bitbucket-cloud/docs/using-api-tokens/), an [App Password](https://support.atlassian.com/bitbucket-cloud/docs/app-passwords/) or an [OAuth 2.0 client credentials](https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/). An Atlassian Account API key will not work. ::: @@ -55,3 +64,5 @@ This one entry will have the following elements: neither a username nor token are supplied, anonymous access will be used. - `token`: The token used to authenticate requests. - `appPassword`: The app password for the Bitbucket Cloud user. +- `clientId`: The OAuth client ID for Bitbucket Cloud (used with `clientSecret` for OAuth 2.0 client credentials flow). +- `clientSecret`: The OAuth client secret for Bitbucket Cloud (used with `clientId` for OAuth 2.0 client credentials flow). diff --git a/docs/integrations/bitbucketServer/discovery.md b/docs/integrations/bitbucketServer/discovery.md index 350bc33aed..bbdd105af4 100644 --- a/docs/integrations/bitbucketServer/discovery.md +++ b/docs/integrations/bitbucketServer/discovery.md @@ -42,6 +42,8 @@ You need to decide how you want to receive events from external sources like - [via HTTP endpoint](https://github.com/backstage/backstage/tree/master/plugins/events-backend/README.md) - [via an AWS SQS queue](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-aws-sqs/README.md) +- [via Google Pub/Sub](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-google-pubsub/README.md) +- [via a Kafka topic](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-kafka/README.md) Further documentation: diff --git a/docs/integrations/github/discovery.md b/docs/integrations/github/discovery.md index f245e960ea..e17f514058 100644 --- a/docs/integrations/github/discovery.md +++ b/docs/integrations/github/discovery.md @@ -141,7 +141,7 @@ events: region: us-east-2 ``` -The [AWS SQS module `README`](https://github.com/backstage/backstage/blob/master/plugins/events-backend-module-aws-sqs/README.md#configuration) has more details on the configuration options, the example above includes on the required options. +The [AWS SQS module `README`](https://github.com/backstage/backstage/blob/master/plugins/events-backend-module-aws-sqs/README.md#configuration) has more details on the configuration options, the example above includes only the required options. ### Events Setup using Google Pub/Sub module @@ -179,7 +179,53 @@ events: targetTopic: 'github.{{ event.attributes.x-github-event }}' ``` -The [Google Pub/Sub module `README`](https://github.com/backstage/backstage/blob/master/plugins/events-backend-module-google-pubsub/README.md#configuration) has more details on the configuration options, the example above includes on the required options. +The [Google Pub/Sub module `README`](https://github.com/backstage/backstage/blob/master/plugins/events-backend-module-google-pubsub/README.md#configuration) has more details on the configuration options, the example above includes only the required options. + +### Events Setup using Kafka module + +Alternatively to using the HTTP endpoint you can use the Kafka module, here's how. + +First we need to add the package: + +```bash title="from your Backstage root directory" +yarn --cwd packages/backend add @backstage/plugin-events-backend-module-kafka +``` + +Then we need to add it to your backend: + +```ts title="in packages/backend/src/index.ts" +backend.add(import('@backstage/plugin-events-backend')); +backend.add(import('@backstage/plugin-events-backend-module-github')); +/* highlight-add-start */ +backend.add(import('@backstage/plugin-events-backend-module-kafka')); +/* highlight-add-end */ +``` + +Finally you will want to configure it: + +```yaml title="app-config.yaml +events: + modules: + kafka: + kafkaConsumingEventPublisher: + # Client ID used by Backstage to identify when connecting to the Kafka cluster. + clientId: your-client-id + # List of brokers in the Kafka cluster to connect to. + brokers: + - broker1 + - broker2 + topics: + # Replace with actual topic name as expected by subscribers + - topic: 'backstage.topic' + kafka: + # The Kafka topics to subscribe to. + topics: + - topic1 + # The GroupId to be used by the topic consumers. + groupId: your-group-id +``` + +The [Kafka module `README`](https://github.com/backstage/backstage/blob/master/plugins/events-backend-module-kafka/README.md#configuration) has more details on the configuration options, the example above includes only the required options. ## Configuration diff --git a/docs/integrations/github/org.md b/docs/integrations/github/org.md index 284451af8c..2dac8b8866 100644 --- a/docs/integrations/github/org.md +++ b/docs/integrations/github/org.md @@ -132,6 +132,8 @@ You can decide between the following options (extensible): - [via HTTP endpoint](https://github.com/backstage/backstage/tree/master/plugins/events-backend/README.md) - [via an AWS SQS queue](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-aws-sqs/README.md) +- [via Google Pub/Sub](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-google-pubsub/README.md) +- [via a Kafka topic](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-kafka/README.md) You can check the official docs to [configure your webhook](https://docs.github.com/en/developers/webhooks-and-events/webhooks/creating-webhooks) and to [secure your request](https://docs.github.com/en/developers/webhooks-and-events/webhooks/securing-your-webhooks). The webhook will need to be configured to forward `organization`,`team` and `membership` events. diff --git a/docs/integrations/gitlab/discovery.md b/docs/integrations/gitlab/discovery.md index 5e02c853fa..3d47edba6d 100644 --- a/docs/integrations/gitlab/discovery.md +++ b/docs/integrations/gitlab/discovery.md @@ -43,6 +43,8 @@ You need to decide how you want to receive events from external sources like - [via HTTP endpoint](https://github.com/backstage/backstage/blob/master/plugins/events-backend/README.md#configuration) - [via an AWS SQS queue](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-aws-sqs/README.md) +- [via Google Pub/Sub](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-google-pubsub/README.md) +- [via a Kafka topic](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-kafka/README.md) Further documentation: @@ -92,6 +94,8 @@ Additionally, you need to decide how you want to receive events from external so - [via HTTP endpoint](https://github.com/backstage/backstage/tree/master/plugins/events-backend/README.md) - [via an AWS SQS queue](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-aws-sqs/README.md) +- [via Google Pub/Sub](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-google-pubsub/README.md) +- [via a Kafka topic](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-kafka/README.md) Set up your provider diff --git a/docs/integrations/gitlab/org.md b/docs/integrations/gitlab/org.md index 8249a97c24..2908bb7c09 100644 --- a/docs/integrations/gitlab/org.md +++ b/docs/integrations/gitlab/org.md @@ -49,6 +49,8 @@ You need to decide how you want to receive events from external sources like - [via HTTP endpoint](https://github.com/backstage/backstage/blob/master/plugins/events-backend/README.md#configuration) - [via an AWS SQS queue](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-aws-sqs/README.md) +- [via Google Pub/Sub](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-google-pubsub/README.md) +- [via a Kafka topic](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-kafka/README.md) Further documentation: @@ -101,6 +103,8 @@ Additionally, you need to decide how you want to receive events from external so - [via HTTP endpoint](https://github.com/backstage/backstage/tree/master/plugins/events-backend/README.md) - [via an AWS SQS queue](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-aws-sqs/README.md) +- [via Google Pub/Sub](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-google-pubsub/README.md) +- [via a Kafka topic](https://github.com/backstage/backstage/tree/master/plugins/events-backend-module-kafka/README.md) Set up your provider diff --git a/docs/notifications/processors.md b/docs/notifications/processors.md index c25b669ed6..af0b9f8f93 100644 --- a/docs/notifications/processors.md +++ b/docs/notifications/processors.md @@ -149,11 +149,63 @@ notifications: broadcastChannels: # Optional, if you wish to support broadcast notifications. - C12345678 username: 'Backstage Bot' # Optional, defaults to the name of the Slack App. + concurrencyLimit: 20 # Optional, number of messages allowed per interval. Defaults to 10. + throttleInterval: 1m # Optional, Accepts ISO-8601 duration, ms-style ("1m", "30s"), or HumanDuration ({ minutes: 2 }). Defaults to 1 minute ``` Multiple instances can be added in the `slack` array, allowing you to have multiple configurations if you need to send messages to more than one Slack workspace. Org-Wide App installation is not currently supported. +### Broadcast Channel Routing + +For more granular control over where broadcast notifications are sent, you can use `broadcastRoutes` to route notifications to different Slack channels based on their origin and/or topic. This is useful when you want different types of notifications to go to different channels. + +```yaml +notifications: + processors: + slack: + - token: xoxb-XXXXXXXXX + # Legacy option - used as fallback when no routes match + broadcastChannels: + - general-notifications + # Route broadcasts based on origin and/or topic + broadcastRoutes: + # Most specific: matches both origin AND topic + - origin: plugin:catalog + topic: alerts + channel: catalog-alerts + # Origin only: all notifications from this origin + - origin: plugin:catalog + channel: catalog-updates + # Topic only: all notifications with this topic (any origin) + - topic: security + channel: security-team + # Multiple channels: send to several channels at once + - origin: external:monitoring + channel: + - ops-team + - on-call-alerts +``` + +#### Route Matching Precedence + +Routes are evaluated in the following order of priority: + +1. **Origin + Topic match** (most specific) - A route that specifies both `origin` and `topic` will match first +2. **Origin-only match** - A route with only `origin` specified (no `topic`) +3. **Topic-only match** - A route with only `topic` specified (no `origin`) +4. **Default fallback** - If no routes match, falls back to `broadcastChannels` + +The first matching route wins. If no routes match and no `broadcastChannels` are configured, the broadcast notification will not be sent to Slack. + +#### Configuration Options + +| Property | Type | Description | +| --------- | ---------------------- | ------------------------------------------------------------------------------------------ | +| `origin` | `string` | Optional. The notification origin to match (e.g., `plugin:catalog`, `external:my-service`) | +| `topic` | `string` | Optional. The notification topic to match (e.g., `alerts`, `updates`, `security`) | +| `channel` | `string` or `string[]` | Required. The Slack channel(s) to send to. Can be channel IDs, channel names, or user IDs | + ### Entity Requirements Entities must be annotated with the following annotation: diff --git a/docs/plugins/integrating-plugin-into-software-catalog.md b/docs/plugins/integrating-plugin-into-software-catalog.md index ed2e25c601..3542e073cb 100644 --- a/docs/plugins/integrating-plugin-into-software-catalog.md +++ b/docs/plugins/integrating-plugin-into-software-catalog.md @@ -32,7 +32,7 @@ Creating the plugin... ### Reading entities from within your plugin You can access the currently selected entity using the backstage api -[`useEntity`](../reference/plugin-catalog-react.useentity.md). For example, +[`useEntity`](https://backstage.io/api/stable/functions/_backstage_plugin-catalog-react.index.useEntity.html). For example, ```tsx import { useEntity } from '@backstage/plugin-catalog-react'; diff --git a/docs/plugins/structure-of-a-plugin.md b/docs/plugins/structure-of-a-plugin.md index 0d18942320..7cfaca4561 100644 --- a/docs/plugins/structure-of-a-plugin.md +++ b/docs/plugins/structure-of-a-plugin.md @@ -81,8 +81,8 @@ export const ExamplePage = examplePlugin.provide( ``` This is where the plugin is created and where it creates and exports extensions -that can be imported and used the app. See reference docs for -[`createPlugin`](../reference/core-plugin-api.createplugin.md) or introduction to +that can be imported and used in the app. See reference docs for +[`createPlugin`](https://backstage.io/api/stable/functions/_backstage_core-plugin-api.index.createPlugin.html) or introduction to the new [Composability System](./composability.md). ## Components diff --git a/docs/releases/v1.46.0-changelog.md b/docs/releases/v1.46.0-changelog.md new file mode 100644 index 0000000000..22e6e39dab --- /dev/null +++ b/docs/releases/v1.46.0-changelog.md @@ -0,0 +1,2369 @@ +# Release v1.46.0 + +Upgrade Helper: [https://backstage.github.io/upgrade-helper/?to=1.46.0](https://backstage.github.io/upgrade-helper/?to=1.46.0) + +## @backstage/plugin-techdocs-addons-test-utils@2.0.0 + +### Major Changes + +- 8d6709e: **BREAKING**: `TechDocsAddonTester.renderWithEffects()` no longer returns a screen; this means that you can no longer grab assertions such as `getByText` from its return value. + + Newer versions of `@testing-library` recommends using the `screen` export for assertions - and removing this from the addon tester contract allows us to more freely iterate on which underlying version of the testing library is being used. + + One notable effect of this, however, is that the `@testing-library` `screen` does NOT support assertions on the shadow DOM, which techdocs relies on. You will therefore want to add a dependency on [the `shadow-dom-testing-library` package](https://github.com/konnorrogers/shadow-dom-testing-library/) in your tests, and using its `screen` and its dedicated `*Shadow*` methods. As an example, if you keep doing `getByText` you will not get matches inside the shadow DOM - switch to `getByShadowText` instead. + + ```ts + import { screen } from 'shadow-dom-testing-library'; + + // ... render the addon ... + await TechDocsAddonTester.buildAddonsInTechDocs([]) + .withDom(TEST_CONTENT) + .renderWithEffects(); + + expect(screen.getByShadowText('TEST_CONTENT')).toBeInTheDocument(); + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.19.3 + - @backstage/plugin-techdocs@1.16.1 + - @backstage/plugin-catalog@1.32.1 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/plugin-search-react@1.10.1 + - @backstage/test-utils@1.7.14 + - @backstage/core-plugin-api@1.12.1 + - @backstage/integration-react@1.2.13 + - @backstage/plugin-techdocs-react@1.3.6 + +## @backstage/backend-app-api@1.4.0 + +### Minor Changes + +- 5a2d538: Introduced backend startup result tracking and error handling. The `Backend.start()` method now returns a `BackendStartupResult` with detailed success/failure status and timing information for all plugins and modules. When startup fails, a `BackendStartupError` is thrown that includes the complete startup results, making it easier to diagnose which plugins or modules failed. + + This also improves the default error message when backend startup fails, and of course makes it possible to craft your own custom error reporting based on the startup results. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/backend-defaults@0.14.0 + +### Minor Changes + +- fa43826: Move `better-sqlite3` from dependencies to peer dependencies +- 2bc4e02: **BREAKING** The correct configuration options for Valkey are now being used. + + These changes are **required** to `app-config.yaml`: + + ```diff + backend: + cache: + store: valkey + connection: ... + client: + - namespace: 'my-app' + - keyPrefixSeparator: ':' + + keyPrefix: 'my-app:' + - clearBatchSize: 1000 + - useUnlink: false + ``` + + In comparison to Redis, Valkey requires the full `keyPrefix` including the separator to be specified instead of separate `namespace` and `keyPrefixSeparator` options. Also, Valkey does not support the `clearBatchSize` and `useUnlink` options. + +### Patch Changes + +- 37fba1d: Added support for Bitbucket Cloud OAuth. This introduces an alternative authentication method using a workspace OAuth consumer, alongside App Passwords (deprecated) and API tokens. OAuth does not require a bot or service account and avoids token expiry issues. + + **BREAKING CHANGES** + + - **@backstage/integration** (`src/bitbucketCloud/core.ts`) + + - `getBitbucketCloudRequestOptions` now returns a `Promise` and **must** be awaited. + + - **@backstage/plugin-scaffolder-backend-module-bitbucket-cloud** (`src/actions/helpers.ts`) + - `getBitbucketClient` now returns a `Promise` and **must** be awaited. + - `getAuthorizationHeader` now returns a `Promise` and **must** be awaited. + + **OAuth usage example** + + ```yaml + integrations: + bitbucketCloud: + - clientId: client-id + clientSecret: client-secret + ``` + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 + +- aa79251: build(deps): bump `node-forge` from 1.3.1 to 1.3.2 + +- f96edff: Allow configuration of the `referrerPolicy` + +- fb029b6: Updated luxon types + +- d9759a1: **BREAKING ALPHA**: The old `instanceMetadataService` has been removed from alpha. Please switch over to using the stable `coreServices.rootInstanceMetadata` and related types instead, available from `@backstage/backend-plugin-api`. + +- 847a330: Fix for `jose` types + +- 25b560e: Internal change to support new versions of the `logform` library + +- 2a0c4b0: Adds a new experimental `RootSystemMetadataService` for tracking the collection of Backstage instances that may be deployed at any one time. It currently offers a single API, `getInstalledPlugins` that returns a list of installed plugins based on config you have set up in `discovery.endpoints` as well as the plugins installed on the instance you're calling the API with. It does not handle wildcard values or fallback values. The intention is for this plugin to provide plugin authors with a simple interface to fetch a trustworthy list of all installed plugins. + +- 3016a79: Updated dependency `@types/archiver` to `^7.0.0`. + +- 42db6a6: Don't warn when parsing `storeOptions` for `memory` cache + +- Updated dependencies + - @backstage/cli-node@0.2.16 + - @backstage/integration@1.19.0 + - @backstage/plugin-auth-node@0.6.10 + - @backstage/plugin-events-node@0.4.18 + - @backstage/plugin-permission-node@0.10.7 + - @backstage/backend-app-api@1.4.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/config-loader@1.10.7 + - @backstage/backend-dev-utils@0.1.6 + +## @backstage/backend-plugin-api@1.6.0 + +### Minor Changes + +- 2a0c4b0: Adds a new experimental `RootSystemMetadataService` for tracking the collection of Backstage instances that may be deployed at any one time. It currently offers a single API, `getInstalledPlugins` that returns a list of installed plugins based on config you have set up in `discovery.endpoints` as well as the plugins installed on the instance you're calling the API with. It does not handle wildcard values or fallback values. The intention is for this plugin to provide plugin authors with a simple interface to fetch a trustworthy list of all installed plugins. + +### Patch Changes + +- d9759a1: **BREAKING ALPHA**: The old `instanceMetadataService` has been removed from alpha. Please switch over to using the stable `coreServices.rootInstanceMetadata` and related types instead, available from `@backstage/backend-plugin-api`. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/plugin-permission-node@0.10.7 + - @backstage/cli-common@0.1.16 + +## @backstage/cli@0.35.0 + +### Minor Changes + +- f6f22a9: Provide `--no-node-snapshot` by default when running the `package start` or `package test`. You can disable this behavior by providing `NODE_OPTIONS='--node-snapshot'`. + +- f8dff94: Switched the default module resolution to `bundler` and the `module` setting to `ES2020`. + + You may need to bump some dependencies as part of this change and fix imports in code. The most common source of this is that type checking will now consider the `exports` field in `package.json` when resolving imports. This in turn can break older versions of packages that had incompatible `exports` fields. Generally these issues will have already been fixed in the upstream packages. + + You might be tempted to use `--skipLibCheck` to hide issues due to this change, but it will weaken the type safety of your project. If you run into a large number of issues and want to keep the old behavior, you can reset the `moduleResolution` and `module` settings your own `tsconfig.json` file to `node` and `ESNext` respectively. But keep in mind that the `node` option will be removed in future versions of TypeScript. + + A future version of Backstage will make these new settings mandatory, as we move to rely on the `exports` field for type resolution in packages, rather than the `typesVersions` field. + +- cd0b8a1: **BREAKING**: `jest` is now a peer dependency. If you run tests using Backstage CLI, you must add Jest and its environment dependencies as `devDependencies` in your project. + + You can choose to install either Jest 29 or Jest 30. The built-in Jest version before this change was Jest 29, however, we recommend that you switch to Jest 30. Upgrading will solve the `Could not parse CSS stylesheet` errors, allow you to use MSW v2 in web packages, and ensure that you remain compatible with future versions of the Backstage CLI. Support for Jest 29 is temporary, with the purpose of allowing you to upgrade at your own pace, but it will eventually be removed. + + - **Jest 29**: Install `jest@^29` and `jest-environment-jsdom@^29`. No migration needed, but you may see `Could not parse CSS stylesheet` warnings/errors when testing components from `@backstage/ui` or other packages using CSS `@layer` declarations. + - **Jest 30**: Install `jest@^30`, `@jest/environment-jsdom-abstract@^30`, and `jsdom@^27`. Fixes the stylesheet parsing warnings/errors, but requires migration steps. + + See the [Jest 30 migration guide](https://backstage.io/docs/tutorials/jest30-migration) for detailed migration instructions. + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 + +- e7db290: Add missing peer/dev dependencies to the frontend plugin template. + + `react-dom` was not declared as a peer dependency, causing module resolution + errors when generating plugins outside a Backstage monorepo. This adds + `react-dom` to `peerDependencies` (for consuming apps) and `devDependencies` + (for local development). `react-router-dom` is also added to `peerDependencies` (for consuming apps) and `devDependencies` + to support routing during plugin development. + + Fixes: + + - Module not found: Can't resolve 'react-dom' + - Module not found: Can't resolve 'react-router-dom' + +- 1226647: Updated dependency `esbuild` to `^0.27.0`. + +- f89a074: Updated dependency `@pmmmwh/react-refresh-webpack-plugin` to `^0.6.0`. + +- 2b81751: Updated dependency `webpack` to `~5.103.0`. + +- fafd9e1: Fixed internal usage of `yargs`. + +- c8c2329: Add proxy configuration from env-vars to create-app tasks + +- 2bae83a: Switched compilation target to ES2022 in order to match the new set of supported Node.js versions, which are 22 and 24. + + The TypeScript compilation target has been set to ES2022, because setting it to a higher target will break projects on older TypeScript versions. If you use a newer TypeScript version in your own project, you can bump `compilerOptions.target` to ES2023 or ES2024 in your own `tsconfig.json` file. + +- 7fbac5c: Updated to use new utilities from `@backstage/cli-common`. + +- 2bae83a: Bumped dev dependencies `@types/node` + +- Updated dependencies + - @backstage/cli-node@0.2.16 + - @backstage/integration@1.19.0 + - @backstage/cli-common@0.1.16 + - @backstage/config-loader@1.10.7 + +## @backstage/integration@1.19.0 + +### Minor Changes + +- 37fba1d: Added support for Bitbucket Cloud OAuth. This introduces an alternative authentication method using a workspace OAuth consumer, alongside App Passwords (deprecated) and API tokens. OAuth does not require a bot or service account and avoids token expiry issues. + + **BREAKING CHANGES** + + - **@backstage/integration** (`src/bitbucketCloud/core.ts`) + + - `getBitbucketCloudRequestOptions` now returns a `Promise` and **must** be awaited. + + - **@backstage/plugin-scaffolder-backend-module-bitbucket-cloud** (`src/actions/helpers.ts`) + - `getBitbucketClient` now returns a `Promise` and **must** be awaited. + - `getAuthorizationHeader` now returns a `Promise` and **must** be awaited. + + **OAuth usage example** + + ```yaml + integrations: + bitbucketCloud: + - clientId: client-id + clientSecret: client-secret + ``` + +### Patch Changes + +- a26a322: Added support for using a GitHub App installation to generate tokens for public repository access when the `publicAccess` option is enabled. When all other authentication methods fail (e.g., the app is not installed in that organization), the provider will now use an available installation to generate a token that can be used to access public repositories as read only. +- fb029b6: Updated luxon types +- e15fdae: Made the github urls case insensitive. + +## @backstage/ui@0.10.0 + +### Minor Changes + +- 16543fa: **Breaking change** The `Cell` component has been refactored to be a generic wrapper component that accepts `children` for custom cell content. The text-specific functionality (previously part of `Cell`) has been moved to a new `CellText` component. + + ### Migration Guide + + If you were using `Cell` with text-specific props (`title`, `description`, `leadingIcon`, `href`), you need to update your code to use `CellText` instead: + + **Before:** + + ```tsx + } + href="/path" + /> + ``` + + **After:** + + ```tsx + } + href="/path" + /> + ``` + + For custom cell content, use the new generic `Cell` component: + + ```tsx + {/* Your custom content */} + ``` + +### Patch Changes + +- 50b7927: Fixed Checkbox indicator showing checkmark color when unchecked. + + Affected components: Checkbox + +- 5bacf55: Fixed `ButtonIcon` incorrectly applying `className` to inner elements instead of only the root element. + + Affected components: ButtonIcon + +- b3ad928: Fixed Table Row component to correctly handle cases where no `href` is provided, preventing unnecessary router provider wrapping and fixing the cursor incorrectly showing as a pointer despite the element not being a link. + + Affected components: Row + +- a20d317: Added row selection support with visual state styling for hover, selected, and pressed states. Fixed checkbox rendering to only show for multi-select toggle mode. + + Affected components: Table, TableHeader, Row, Column + +- fe7c751: Fixed `useTable` hook to prioritize `providedRowCount` over data length for accurate row count in server-side pagination scenarios. + +- c145031: Fixed Table column sorting indicator to show up arrow when no sort is active, correctly indicating that clicking will sort ascending. + + Affected components: Column + +## @backstage/plugin-auth-backend-module-github-provider@0.4.0 + +### Minor Changes + +- b3286d5: Added the `github.com/user-id` annotation to store GitHub's user ID (immutable) in user entities. Also includes addition of the `userIdMatchingUserEntityAnnotation` sign-in resolver that matches users by the new ID. + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-catalog-backend@3.3.0 + +### Minor Changes + +- dce1824: Added `ActionsRegistry` actions for `register-entity` and `unregister-entity` + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- 8101ec1: Fixed default refresh service to go through the whole ancestry of the entity. +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-openapi-utils@0.6.4 + - @backstage/plugin-events-node@0.4.18 + - @backstage/plugin-permission-node@0.10.7 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## @backstage/plugin-catalog-backend-module-github@0.12.0 + +### Minor Changes + +- b3286d5: Added the `github.com/user-id` annotation to store GitHub's user ID (immutable) in user entities. Also includes addition of the `userIdMatchingUserEntityAnnotation` sign-in resolver that matches users by the new ID. + +### Patch Changes + +- ed5a7a3: Introduce new configuration option to exclude suspended users from GitHub Enterprise instances. + + When it’s set to true, suspended users won’t be returned when querying the organization users for GitHub Enterprise instances. + Note that this option should be used only against GitHub Enterprise instances, the property does not exist in the github.com GraphQL schema, setting it will cause a schema validation error and the syncing of users will fail. + +- a413977: Added configurable `pageSizes` option to `GithubOrgEntityProvider` for GitHub GraphQL API queries to prevent `RESOURCE_LIMITS_EXCEEDED` errors with organizations with large number of teams and members. This aligns the configuration options with `GithubMultiOrgEntityProvider`. + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## @backstage/plugin-events-backend-module-kafka@0.2.0 + +### Minor Changes + +- 2c74ea9: Added support for multiple named instances in `kafkaConsumingEventPublisher` configuration. The previous single configuration format is still supported for backward compatibility. +- 2c74ea9: Added `KafkaPublishingEventConsumer` to support sending Backstage events to Kafka topics. + + This addition enables Backstage to publish events to external Kafka systems, complementing the existing ability to receive events from Kafka. This allows for better integration with external systems that rely on Kafka for event streaming. + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-kubernetes-backend@0.21.0 + +### Minor Changes + +- 7f9846f: Add possibility to extends Kubernetes REST API. Add fetcher to parameters for custom objects provider + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- fb029b6: Updated luxon types +- e9589d9: Replace `@aws-sdk/signature-v4` with `@smithy/signature-v4`, + as stated in the [package documentation](https://www.npmjs.com/package/@aws-sdk/signature-v4?activeTab=readme) +- 8fa8d87: Add Kubernetes Plugin Secrets Accordion with masked secret datas +- Updated dependencies + - @backstage/plugin-permission-node@0.10.7 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-kubernetes-node@0.4.0 + - @backstage/plugin-kubernetes-common@0.9.9 + - @backstage/plugin-catalog-node@1.20.1 + +## @backstage/plugin-kubernetes-node@0.4.0 + +### Minor Changes + +- 7f9846f: Add possibility to extends Kubernetes REST API. Add fetcher to parameters for custom objects provider + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-kubernetes-common@0.9.9 + +## @backstage/plugin-notifications-backend-module-slack@0.3.0 + +### Minor Changes + +- f95a516: Enables optional routes to Slack channels for broadcast notifications based on origin and/or topics. + +### Patch Changes + +- b80857a: Slack notification handler throttling can now be configured with the `concurrencyLimit` and `throttleInterval` options. +- f8230e4: Updated dependency `@faker-js/faker` to `^10.0.0`. +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + - @backstage/plugin-notifications-node@0.2.22 + +## @backstage/plugin-scaffolder@1.35.0 + +### Minor Changes + +- dab3d3f: Added field extension `RepoOwnerPicker` for retrieving GitHub repository owners. + +### Patch Changes + +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- be21c5c: Updated dependency `@rjsf/utils` to `5.24.13`. + Updated dependency `@rjsf/core` to `5.24.13`. + Updated dependency `@rjsf/material-ui` to `5.24.13`. + Updated dependency `@rjsf/validator-ajv8` to `5.24.13`. +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/plugin-scaffolder-react@1.19.4 + - @backstage/core-components@0.18.4 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/integration-react@1.2.13 + - @backstage/plugin-permission-react@0.4.39 + - @backstage/plugin-scaffolder-common@1.7.4 + - @backstage/plugin-techdocs-react@1.3.6 + +## @backstage/plugin-scaffolder-backend@3.1.0 + +### Minor Changes + +- a4cd405: Add `defaultEnvironment` config to scaffolder to enable more flexible and custom templates. Now it's possible enable access to default parameters and secrets in templates, improving security and reducing complexity. + +### Patch Changes + +- be5972b: Fixed a bug where config was not passed to NunjucksWorkflowRunner, causing defaultEnvironment to be undefined +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- 2bae83a: Updated `isolated-vm` to `6.0.1` +- 25b560e: Internal change to support new versions of the `logform` library +- 8f4aded: Fixing OpenAPI definition +- 1226647: Updated dependency `esbuild` to `^0.27.0`. +- Updated dependencies + - @backstage/plugin-scaffolder-backend-module-gitlab@0.11.0 + - @backstage/integration@1.19.0 + - @backstage/plugin-auth-node@0.6.10 + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.3.0 + - @backstage/plugin-bitbucket-cloud-common@0.3.5 + - @backstage/backend-defaults@0.14.0 + - @backstage/backend-openapi-utils@0.6.4 + - @backstage/plugin-events-node@0.4.18 + - @backstage/plugin-permission-node@0.10.7 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-backend-module-github@0.9.3 + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.16 + - @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.17 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.15 + - @backstage/plugin-catalog-node@1.20.1 + - @backstage/plugin-scaffolder-backend-module-azure@0.2.16 + - @backstage/plugin-scaffolder-backend-module-gerrit@0.2.16 + - @backstage/plugin-scaffolder-backend-module-gitea@0.2.16 + - @backstage/plugin-scaffolder-common@1.7.4 + - @backstage/plugin-scaffolder-node@0.12.2 + +## @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.3.0 + +### Minor Changes + +- 37fba1d: Added support for Bitbucket Cloud OAuth. This introduces an alternative authentication method using a workspace OAuth consumer, alongside App Passwords (deprecated) and API tokens. OAuth does not require a bot or service account and avoids token expiry issues. + + **BREAKING CHANGES** + + - **@backstage/integration** (`src/bitbucketCloud/core.ts`) + + - `getBitbucketCloudRequestOptions` now returns a `Promise` and **must** be awaited. + + - **@backstage/plugin-scaffolder-backend-module-bitbucket-cloud** (`src/actions/helpers.ts`) + - `getBitbucketClient` now returns a `Promise` and **must** be awaited. + - `getAuthorizationHeader` now returns a `Promise` and **must** be awaited. + + **OAuth usage example** + + ```yaml + integrations: + bitbucketCloud: + - clientId: client-id + clientSecret: client-secret + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/plugin-bitbucket-cloud-common@0.3.5 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-node@0.12.2 + +## @backstage/plugin-scaffolder-backend-module-gitlab@0.11.0 + +### Minor Changes + +- f2d034b: In the `gitlabRepoPush` action, add 'auto' possibility for `commitAction` input. + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-node@0.12.2 + +## @backstage/plugin-search-backend-node@1.4.0 + +### Minor Changes + +- 4d3ddb9: Improving method that search tokenizer breaks apart entity names + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/app-defaults@1.7.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.19.3 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/theme@0.7.1 + - @backstage/plugin-permission-react@0.4.39 + +## @backstage/backend-dev-utils@0.1.6 + +### Patch Changes + +- 2bae83a: Internal update for Node.js v24 support. + +## @backstage/backend-dynamic-feature-service@0.7.7 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/cli-node@0.2.16 + - @backstage/plugin-search-backend-node@1.4.0 + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-defaults@0.14.0 + - @backstage/backend-openapi-utils@0.6.4 + - @backstage/plugin-app-node@0.1.40 + - @backstage/plugin-catalog-backend@3.3.0 + - @backstage/plugin-events-backend@0.5.9 + - @backstage/plugin-events-node@0.4.18 + - @backstage/plugin-permission-node@0.10.7 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/cli-common@0.1.16 + - @backstage/config-loader@1.10.7 + - @backstage/plugin-scaffolder-node@0.12.2 + +## @backstage/backend-openapi-utils@0.6.4 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/backend-test-utils@1.10.2 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- 8be23a4: Switched `textextensions` dependency for `text-extensions`. +- 5a737e1: Fix PostgreSQL 18 `TestDatabases` by pinning the data directory +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-defaults@0.14.0 + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-app-api@1.4.0 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/cli-common@0.1.16 + +### Patch Changes + +- 5cfb2a4: Added new `run`, `runOutput`, and `runCheck` utilities to help run child processes in a safe and portable way. +- c8c2329: Add proxy configuration from env-vars to create-app tasks +- 2bae83a: Bumped dev dependencies `@types/node` + +## @backstage/cli-node@0.2.16 + +### Patch Changes + +- 4e8c726: Updated to use new utilities from `@backstage/cli-common`. +- Updated dependencies + - @backstage/cli-common@0.1.16 + +## @backstage/codemods@0.1.53 + +### Patch Changes + +- 688f070: Updated to use new utilities from `@backstage/cli-common`. +- 2bae83a: Bumped dev dependencies `@types/node` +- Updated dependencies + - @backstage/cli-common@0.1.16 + +## @backstage/config-loader@1.10.7 + +### Patch Changes + +- 741c47a: Updated dependency `typescript-json-schema` to `^0.67.0`. +- Updated dependencies + - @backstage/cli-common@0.1.16 + +## @backstage/core-app-api@1.19.3 + +### Patch Changes + +- 75683ed: Added replay functionality to `AlertApiForwarder` to buffer and replay recent alerts to new subscribers, preventing missed alerts that were posted before subscription. +- 97cd16f: Internal update of translation imports. +- Updated dependencies + - @backstage/core-plugin-api@1.12.1 + +## @backstage/core-compat-api@0.5.5 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/core-plugin-api@1.12.1 + +## @backstage/core-components@0.18.4 + +### Patch Changes + +- 9a942a4: Fixed bug in the `LogViewer` component where shift + click always opened a new window instead of just changing the selection. + + In addition, improved the `LogViewer` component by a few usability enhancements: + + - Added support for multiple selections using cmd/ctrl + click + - Improved the generated hash that is added to the URL to also support ranges & multiple selections + - Added an hover effect & info tooltip to the "Copy to clipboard" button to indicate its functionality + - Added some color and a separator to the line numbers to improve readability + +- 207c3c8: long words like urls now breaks to new line on warning panels instead of overflowing the container + +- 4c00303: Add `tooltipClasses` prop to `OverflowTooltip` component to allow customisation of the tooltip + +- 5d52dab: Add i18n support for LogViewer search control + +- f6b49ce: added support for wrapLongLines option in CodeSnippet + +- Updated dependencies + - @backstage/core-plugin-api@1.12.1 + - @backstage/theme@0.7.1 + +## @backstage/core-plugin-api@1.12.1 + +### Patch Changes + +- 358c6f7: The `useApp` and `useRouteRef` functions are now forwards compatible with the new frontend system. Along with the previous route reference changes this means that there is no longer a need to use `compatWrapper` from `@backstage/core-compat-api` to make code based on `@backstage/core-plugin-api` compatible with `@backstage/frontend-plugin-api` APIs. +- 97cd16f: Reversed the relationship between the old `@backstage/core-plugin-api` and the new `@backstage/frontend-plugin-api`. Previously, the a lot of API definitions and utilities where defined in the old and re-exported from the old, but this change flips that around so that they now reside in the new package and are re-exported from the old. The external API of both packages remain the same, but this is a step towards being able to add further compatibility with the new frontend system built into the old. +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + +## @backstage/create-app@0.7.7 + +### Patch Changes + +- 336db00: Bumped create-app version. +- 2bae83a: Updated engines to support Node 22 or 24 +- c8c2329: Add proxy configuration from env-vars to create-app tasks +- 2bae83a: Bumped dev dependencies `@types/node` +- Updated dependencies + - @backstage/cli-common@0.1.16 + +## @backstage/dev-utils@1.1.18 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.19.3 + - @backstage/ui@0.10.0 + - @backstage/core-components@0.18.4 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/theme@0.7.1 + - @backstage/app-defaults@1.7.3 + - @backstage/integration-react@1.2.13 + +## @backstage/frontend-app-api@0.13.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.19.3 + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-plugin-api@1.12.1 + - @backstage/frontend-defaults@0.3.4 + +## @backstage/frontend-defaults@0.3.4 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-app@0.3.3 + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/frontend-app-api@0.13.3 + +## @backstage/frontend-dynamic-feature-loader@0.1.8 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + +## @backstage/frontend-plugin-api@0.13.2 + +### Patch Changes + +- 75683ed: Added a new `errorPresentation` prop to `ExtensionBoundary` to control how errors are presented to the user. The default is `'error-display'`, which is the current behavior of showing the error in the `ErrorDisplay` component. The new option is `'error-api'`, posts errors to the `ErrorApi` and does not allow retries. + + The `AppRootElementBlueprint` now wraps its element in an `ErrorBoundary` using the new `'error-api'` presentation mode. + +- 0bc1ce9: Fixed a versioning conflict that could result in a `.withContext` is not a function error. + +- f3f84f1: Made the return type of `.withOverrides` to be simplified. + +- 97cd16f: Reversed the relationship between the old `@backstage/core-plugin-api` and the new `@backstage/frontend-plugin-api`. Previously, the a lot of API definitions and utilities where defined in the old and re-exported from the old, but this change flips that around so that they now reside in the new package and are re-exported from the old. The external API of both packages remain the same, but this is a step towards being able to add further compatibility with the new frontend system built into the old. + +- 9b8bde4: Removed unnecessary dependencies on `@backstage/core-components`, `@backstage/config`, `@material-ui/core`, and `lodash`. + +## @backstage/frontend-test-utils@0.4.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-app@0.3.3 + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/test-utils@1.7.14 + - @backstage/frontend-app-api@0.13.3 + +## @backstage/integration-react@1.2.13 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/core-plugin-api@1.12.1 + +## @backstage/repo-tools@0.16.1 + +### Patch Changes + +- 688f070: Updated to use new utilities from `@backstage/cli-common`. + +- 85895f9: Updates OpenAPI generator templates to preserve original property names (like 'group-name', 'user-id') from OpenAPI specs when propertyNaming=original is specified. Previously, these were always converted to camelCase regardless of the propertyNaming setting. + + - Updates modelGeneric.mustache templates in both client and server generators + - Updates modelTaggedUnion.mustache templates in both client and server generators + - Uses {{baseName}} when available, falls back to {{name}} for backward compatibility + - Maintains backward compatibility - no changes when propertyNaming=original is not used + +- 2bae83a: Bump `@microsoft/api-documenter` and `@microsoft/api-extractor` to latest versions. + +- d1e38a7: Properly create workspace in OS temporary directory for `generate-patch` command + +- 2bae83a: Bumped dev dependencies `@types/node` + +- Updated dependencies + - @backstage/cli-node@0.2.16 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/cli-common@0.1.16 + - @backstage/config-loader@1.10.7 + +## @techdocs/cli@1.10.3 + +### Patch Changes + +- 43629b1: Updated to use new utilities from `@backstage/cli-common`. +- 2bae83a: Bumped dev dependencies `@types/node` +- Updated dependencies + - @backstage/backend-defaults@0.14.0 + - @backstage/plugin-techdocs-node@1.13.10 + - @backstage/cli-common@0.1.16 + +## @backstage/test-utils@1.7.14 + +### Patch Changes + +- 97cd16f: Internal update of translation imports. +- Updated dependencies + - @backstage/core-app-api@1.19.3 + - @backstage/core-plugin-api@1.12.1 + - @backstage/theme@0.7.1 + - @backstage/plugin-permission-react@0.4.39 + +## @backstage/theme@0.7.1 + +### Patch Changes + +- fa06f6b: Added a `themeName` prop to `UnifiedThemeProvider`, enabling Backstage UI `data-theme-name` CSS attribute to be set based on active theme. + +## @backstage/plugin-api-docs@0.13.2 + +### Patch Changes + +- f3f84f1: Minor extension type updates after frontend API bump +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- Updated dependencies + - @backstage/plugin-catalog@1.32.1 + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/plugin-permission-react@0.4.39 + +## @backstage/plugin-app@0.3.3 + +### Patch Changes + +- f3f84f1: Minor extension type updates after frontend API bump +- f7bc228: Support to set `defaultLanguage` and `availableLanguages` for the app language API in the new frontend system +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/theme@0.7.1 + - @backstage/integration-react@1.2.13 + - @backstage/plugin-permission-react@0.4.39 + +## @backstage/plugin-app-backend@0.5.9 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/plugin-app-node@0.1.40 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/config-loader@1.10.7 + +## @backstage/plugin-app-node@0.1.40 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/config-loader@1.10.7 + +## @backstage/plugin-app-visualizer@0.1.26 + +### Patch Changes + +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- Updated dependencies + - @backstage/ui@0.10.0 + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + +## @backstage/plugin-auth@0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/theme@0.7.1 + +## @backstage/plugin-auth-backend@0.25.7 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## @backstage/plugin-auth-backend-module-atlassian-provider@0.4.10 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-auth-backend-module-auth0-provider@0.2.10 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-auth-backend-module-aws-alb-provider@0.4.10 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/plugin-auth-backend@0.25.7 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-auth-backend-module-azure-easyauth-provider@0.2.15 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-auth-backend-module-bitbucket-provider@0.3.10 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-auth-backend-module-bitbucket-server-provider@0.2.10 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-auth-backend-module-cloudflare-access-provider@0.4.10 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-auth-backend-module-gcp-iap-provider@0.4.10 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-auth-backend-module-gitlab-provider@0.3.10 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-auth-backend-module-google-provider@0.3.10 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-auth-backend-module-guest-provider@0.2.15 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-auth-backend-module-microsoft-provider@0.3.10 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-auth-backend-module-oauth2-provider@0.4.10 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-auth-backend-module-oauth2-proxy-provider@0.2.15 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-auth-backend-module-oidc-provider@0.4.10 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/plugin-auth-backend@0.25.7 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-auth-backend-module-okta-provider@0.2.10 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-auth-backend-module-onelogin-provider@0.3.10 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-auth-backend-module-openshift-provider@0.1.3 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-auth-backend-module-pinniped-provider@0.3.10 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-auth-backend-module-vmware-cloud-provider@0.5.10 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-auth-node@0.6.10 + +### Patch Changes + +- 2389358: remove leading dot in auth cookie cleanup call +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- b35f8b2: Fixed chunked cookie replacing edge case in OAuthCookieManager class where some of the old chunks would not get removed if new chunked cookie would have fewer chunks. +- e9dd634: fix flawed cookie removal logic with chunked tokens +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-auth-react@0.1.22 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + +## @backstage/plugin-bitbucket-cloud-common@0.3.5 + +### Patch Changes + +- 37fba1d: Added support for Bitbucket Cloud OAuth. This introduces an alternative authentication method using a workspace OAuth consumer, alongside App Passwords (deprecated) and API tokens. OAuth does not require a bot or service account and avoids token expiry issues. + + **BREAKING CHANGES** + + - **@backstage/integration** (`src/bitbucketCloud/core.ts`) + + - `getBitbucketCloudRequestOptions` now returns a `Promise` and **must** be awaited. + + - **@backstage/plugin-scaffolder-backend-module-bitbucket-cloud** (`src/actions/helpers.ts`) + - `getBitbucketClient` now returns a `Promise` and **must** be awaited. + - `getAuthorizationHeader` now returns a `Promise` and **must** be awaited. + + **OAuth usage example** + + ```yaml + integrations: + bitbucketCloud: + - clientId: client-id + clientSecret: client-secret + ``` + +- Updated dependencies + - @backstage/integration@1.19.0 + +## @backstage/plugin-catalog@1.32.1 + +### Patch Changes + +- f3f84f1: Minor extension type updates after frontend API bump +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- 91f5ed8: Fixed `catalogAboutEntityCard` to filter icon links before calling useProps(), preventing side effects from hooks in filtered-out links +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/plugin-search-react@1.10.1 + - @backstage/core-plugin-api@1.12.1 + - @backstage/core-compat-api@0.5.5 + - @backstage/integration-react@1.2.13 + - @backstage/plugin-permission-react@0.4.39 + - @backstage/plugin-scaffolder-common@1.7.4 + - @backstage/plugin-techdocs-react@1.3.6 + +## @backstage/plugin-catalog-backend-module-aws@0.4.18 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-defaults@0.14.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-kubernetes-common@0.9.9 + - @backstage/plugin-catalog-node@1.20.1 + +## @backstage/plugin-catalog-backend-module-azure@0.3.12 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.9 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-openapi-utils@0.6.4 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.5.6 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/plugin-bitbucket-cloud-common@0.3.5 + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.5.6 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## @backstage/plugin-catalog-backend-module-gcp@0.3.15 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-kubernetes-common@0.9.9 + - @backstage/plugin-catalog-node@1.20.1 + +## @backstage/plugin-catalog-backend-module-gerrit@0.3.9 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## @backstage/plugin-catalog-backend-module-gitea@0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## @backstage/plugin-catalog-backend-module-github-org@0.3.17 + +### Patch Changes + +- ed5a7a3: Introduce new configuration option to exclude suspended users from GitHub Enterprise instances. + + When it’s set to true, suspended users won’t be returned when querying the organization users for GitHub Enterprise instances. + Note that this option should be used only against GitHub Enterprise instances, the property does not exist in the github.com GraphQL schema, setting it will cause a schema validation error and the syncing of users will fail. + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18 + - @backstage/plugin-catalog-backend-module-github@0.12.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## @backstage/plugin-catalog-backend-module-gitlab@0.7.6 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-defaults@0.14.0 + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## @backstage/plugin-catalog-backend-module-gitlab-org@0.2.16 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-backend-module-gitlab@0.7.6 + - @backstage/plugin-catalog-node@1.20.1 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.7.7 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- fb029b6: Updated luxon types +- Updated dependencies + - @backstage/backend-defaults@0.14.0 + - @backstage/plugin-catalog-backend@3.3.0 + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## @backstage/plugin-catalog-backend-module-ldap@0.12.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## @backstage/plugin-catalog-backend-module-logs@0.1.17 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@3.3.0 + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-catalog-backend-module-msgraph@0.8.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## @backstage/plugin-catalog-backend-module-openapi@0.2.17 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## @backstage/plugin-catalog-backend-module-puppetdb@0.2.17 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.15 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + - @backstage/plugin-scaffolder-common@1.7.4 + +## @backstage/plugin-catalog-backend-module-unprocessed@0.6.7 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-unprocessed-entities-common@0.0.12 + - @backstage/plugin-catalog-node@1.20.1 + +## @backstage/plugin-catalog-graph@0.5.4 + +### Patch Changes + +- a67c144: Fixed zoom out description (replace `&` with &) +- f3f84f1: Minor extension type updates after frontend API bump +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/core-plugin-api@1.12.1 + +## @backstage/plugin-catalog-import@0.13.8 + +### Patch Changes + +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/integration-react@1.2.13 + - @backstage/plugin-permission-react@0.4.39 + +## @backstage/plugin-catalog-node@1.20.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-node@0.10.7 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-catalog-react@1.21.4 + +### Patch Changes + +- 6d39141: Fixed an issue where `EntityOwnerPicker` failed to filter options when the input text contained uppercase characters. +- b3c0594: Use a versioned context for `useEntityList`, to better work with mixed `@backstage/plugin-catalog-react` versions. +- c51c901: $contains may have string value in an entity filter. Typescript type and Zod parser were not the same. +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/core-compat-api@0.5.5 + - @backstage/frontend-test-utils@0.4.2 + - @backstage/integration-react@1.2.13 + - @backstage/plugin-permission-react@0.4.39 + +## @backstage/plugin-catalog-unprocessed-entities@0.2.24 + +### Patch Changes + +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. + +- df4d646: Moved types, API and client to the common package, allowing both frontend and + backend plugins to use the `CatalogUnprocessedEntitiesClient`. + + The following types, clients and interfaces have been deprecated and should be + imported from the `@backstage/plugin-catalog-unprocessed-entities-common` instead: + `CatalogUnprocessedEntitiesApi`, `CatalogUnprocessedEntitiesApiResponse`, `UnprocessedEntity`, + `UnprocessedEntityCache`, `UnprocessedEntityError`, `CatalogUnprocessedEntitiesClient`. + + All those types, clients and interfaces are re-exported temporarily in the + `@backstage/plugin-catalog-unprocessed-entities` package until cleaned up. + +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/plugin-catalog-unprocessed-entities-common@0.0.12 + +## @backstage/plugin-catalog-unprocessed-entities-common@0.0.12 + +### Patch Changes + +- df4d646: Moved types, API and client to the common package, allowing both frontend and + backend plugins to use the `CatalogUnprocessedEntitiesClient`. + + The following types, clients and interfaces have been deprecated and should be + imported from the `@backstage/plugin-catalog-unprocessed-entities-common` instead: + `CatalogUnprocessedEntitiesApi`, `CatalogUnprocessedEntitiesApiResponse`, `UnprocessedEntity`, + `UnprocessedEntityCache`, `UnprocessedEntityError`, `CatalogUnprocessedEntitiesClient`. + + All those types, clients and interfaces are re-exported temporarily in the + `@backstage/plugin-catalog-unprocessed-entities` package until cleaned up. + +## @backstage/plugin-config-schema@0.1.75 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + +## @backstage/plugin-devtools@0.1.34 + +### Patch Changes + +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- 291bf9d: Added scheduled tasks UI feature for the DevTools plugin +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/plugin-devtools-common@0.1.20 + - @backstage/core-compat-api@0.5.5 + - @backstage/plugin-permission-react@0.4.39 + +## @backstage/plugin-devtools-backend@0.5.12 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- 291bf9d: Added scheduled tasks UI feature for the DevTools plugin +- Updated dependencies + - @backstage/backend-defaults@0.14.0 + - @backstage/plugin-permission-node@0.10.7 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/cli-common@0.1.16 + - @backstage/config-loader@1.10.7 + - @backstage/plugin-devtools-common@0.1.20 + +## @backstage/plugin-devtools-common@0.1.20 + +### Patch Changes + +- 291bf9d: Added scheduled tasks UI feature for the DevTools plugin + +## @backstage/plugin-events-backend@0.5.9 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-openapi-utils@0.6.4 + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-events-backend-module-aws-sqs@0.4.18 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-events-backend-module-azure@0.2.27 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-events-backend-module-bitbucket-cloud@0.2.27 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-events-backend-module-bitbucket-server@0.1.8 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-events-backend-module-gerrit@0.2.27 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-events-backend-module-github@0.4.7 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-events-backend-module-gitlab@0.3.8 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-events-backend-module-google-pubsub@0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-events-backend-test-utils@0.1.51 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18 + +## @backstage/plugin-events-node@0.4.18 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-gateway-backend@1.1.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- 7e860dd: Updated dependency `eventsource` to `^4.0.0`. +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-home@0.8.15 + +### Patch Changes + +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- be21c5c: Updated dependency `@rjsf/utils` to `5.24.13`. + Updated dependency `@rjsf/core` to `5.24.13`. + Updated dependency `@rjsf/material-ui` to `5.24.13`. + Updated dependency `@rjsf/validator-ajv8` to `5.24.13`. +- Updated dependencies + - @backstage/core-app-api@1.19.3 + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/plugin-home-react@0.1.33 + - @backstage/theme@0.7.1 + +## @backstage/plugin-home-react@0.1.33 + +### Patch Changes + +- be21c5c: Updated dependency `@rjsf/utils` to `5.24.13`. + Updated dependency `@rjsf/core` to `5.24.13`. + Updated dependency `@rjsf/material-ui` to `5.24.13`. + Updated dependency `@rjsf/validator-ajv8` to `5.24.13`. +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + +## @backstage/plugin-kubernetes@0.12.14 + +### Patch Changes + +- f15d5f1: add missing i18n support for kubernetes and kubernetes-react +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/plugin-kubernetes-react@0.5.14 + - @backstage/core-components@0.18.4 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/plugin-kubernetes-common@0.9.9 + - @backstage/core-plugin-api@1.12.1 + - @backstage/plugin-permission-react@0.4.39 + +## @backstage/plugin-kubernetes-cluster@0.0.32 + +### Patch Changes + +- 2bae83a: Bumped dev dependencies `@types/node` +- Updated dependencies + - @backstage/plugin-kubernetes-react@0.5.14 + - @backstage/core-components@0.18.4 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/plugin-kubernetes-common@0.9.9 + - @backstage/core-plugin-api@1.12.1 + - @backstage/plugin-permission-react@0.4.39 + +## @backstage/plugin-kubernetes-common@0.9.9 + +### Patch Changes + +- 8fa8d87: Add Kubernetes Plugin Secrets Accordion with masked secret datas + +## @backstage/plugin-kubernetes-react@0.5.14 + +### Patch Changes + +- f966a85: Enabled a pod terminal at GKE +- 8fa8d87: Add Kubernetes Plugin Secrets Accordion with masked secret datas +- f15d5f1: add missing i18n support for kubernetes and kubernetes-react +- Updated dependencies + - @backstage/core-components@0.18.4 + - @backstage/plugin-kubernetes-common@0.9.9 + - @backstage/core-plugin-api@1.12.1 + +## @backstage/plugin-mcp-actions-backend@0.1.6 + +### Patch Changes + +- e83e038: Added `@cfworker/json-schema` as a dependency to this package part of the `@modelcontextprotocol/sdk` bump as it's required in the types +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- 79ef471: Clarify error handling in readme and update handleError.ts to include all backstage/errors +- Updated dependencies + - @backstage/backend-defaults@0.14.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## @backstage/plugin-mui-to-bui@0.2.2 + +### Patch Changes + +- Updated dependencies + - @backstage/ui@0.10.0 + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-plugin-api@1.12.1 + - @backstage/theme@0.7.1 + +## @backstage/plugin-notifications@0.5.12 + +### Patch Changes + +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. + +- 53347cc: Move long notification descriptions behind `Show more/less` button. + + This improves readability of the notifications list by preventing long descriptions from taking up too much space + or rendering very small scrollable areas. + +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/theme@0.7.1 + - @backstage/plugin-signals-react@0.0.18 + +## @backstage/plugin-notifications-backend@0.6.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-signals-node@0.1.27 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + - @backstage/plugin-notifications-node@0.2.22 + +## @backstage/plugin-notifications-backend-module-email@0.3.17 + +### Patch Changes + +- a5d5b3a: SES config for the notification email processor now supports utilizing an ARN for the SES identity when sending an email after the SES SDK V2 update. + + The `sesConfig.fromArn` will set the `fromEmailAddressIdentityArn` option for the SES `SendEmailCommand`. The `sesConfig.sourceArn` field is removed since no equivalent option is available in the send email command options. Setting `sesConfig.sourceArn` will have no effect and log a warning. Example changes: + + ```diff + notifications: + processors: + email: + transportConfig: + transport: "ses" + region: "us-west-2" + sender: "sender@mycompany.com" + replyTo: "no-reply@mycompany.com" + sesConfig: + - sourceArn: "arn:aws:ses:us-west-2:123456789012:identity/example.com" + fromArn: "arn:aws:ses:us-west-2:123456789012:identity/example.com" + ``` + +- b267aea: Updated dependency `@types/nodemailer` to `^7.0.0`. + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + - @backstage/plugin-notifications-node@0.2.22 + +## @backstage/plugin-notifications-node@0.2.22 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-signals-node@0.1.27 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-org@0.6.47 + +### Patch Changes + +- f3f84f1: Minor extension type updates after frontend API bump +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/core-plugin-api@1.12.1 + +## @backstage/plugin-org-react@0.1.45 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.18.4 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/core-plugin-api@1.12.1 + +## @backstage/plugin-permission-backend@0.7.7 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/plugin-permission-node@0.10.7 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-permission-backend-module-allow-all-policy@0.2.15 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/plugin-permission-node@0.10.7 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-permission-node@0.10.7 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-permission-react@0.4.39 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.12.1 + +## @backstage/plugin-proxy-backend@0.6.9 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-proxy-node@0.1.11 + +## @backstage/plugin-proxy-node@0.1.11 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-scaffolder-backend-module-azure@0.2.16 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-node@0.12.2 + +## @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.17 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.3.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.16 + - @backstage/plugin-scaffolder-node@0.12.2 + +## @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.16 + +### Patch Changes + +- 5a6aca2: Improve error message when provided target branch is missing +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-node@0.12.2 + +## @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.3.16 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-node@0.12.2 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.3.18 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-defaults@0.14.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-node@0.12.2 + +## @backstage/plugin-scaffolder-backend-module-gcp@0.2.16 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-node@0.12.2 + +## @backstage/plugin-scaffolder-backend-module-gerrit@0.2.16 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-node@0.12.2 + +## @backstage/plugin-scaffolder-backend-module-gitea@0.2.16 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-node@0.12.2 + +## @backstage/plugin-scaffolder-backend-module-github@0.9.3 + +### Patch Changes + +- dab3d3f: Added autocompletion resource `owners` for retrieving GitHub repository owners. +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + - @backstage/plugin-scaffolder-node@0.12.2 + +## @backstage/plugin-scaffolder-backend-module-notifications@0.1.17 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-notifications-node@0.2.22 + - @backstage/plugin-scaffolder-node@0.12.2 + +## @backstage/plugin-scaffolder-backend-module-rails@0.5.16 + +### Patch Changes + +- 2bae83a: Bumped dev dependencies `@types/node` +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-node@0.12.2 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.2.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-node@0.12.2 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.4.17 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-node@0.12.2 + - @backstage/plugin-scaffolder-node-test-utils@0.3.6 + +## @backstage/plugin-scaffolder-common@1.7.4 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + +## @backstage/plugin-scaffolder-node@0.12.2 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-common@1.7.4 + +## @backstage/plugin-scaffolder-node-test-utils@0.3.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-test-utils@1.10.2 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-node@0.12.2 + +## @backstage/plugin-scaffolder-react@1.19.4 + +### Patch Changes + +- fb029b6: Updated luxon types +- 5ca461e: Fixed bug where custom `review.name` values were incorrectly formatted by `startCase`, preserving them exactly as written. +- be21c5c: Updated dependency `@rjsf/utils` to `5.24.13`. + Updated dependency `@rjsf/core` to `5.24.13`. + Updated dependency `@rjsf/material-ui` to `5.24.13`. + Updated dependency `@rjsf/validator-ajv8` to `5.24.13`. +- 9b38f22: Updated dependency `use-immer` to `^0.11.0`. +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/theme@0.7.1 + - @backstage/plugin-permission-react@0.4.39 + - @backstage/plugin-scaffolder-common@1.7.4 + +## @backstage/plugin-search@1.5.1 + +### Patch Changes + +- f3f84f1: Minor extension type updates after frontend API bump +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/plugin-search-react@1.10.1 + - @backstage/core-plugin-api@1.12.1 + +## @backstage/plugin-search-backend@2.0.9 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-search-backend-node@1.4.0 + - @backstage/backend-defaults@0.14.0 + - @backstage/backend-openapi-utils@0.6.4 + - @backstage/plugin-permission-node@0.10.7 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-search-backend-module-catalog@0.3.11 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-backend-node@1.4.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## @backstage/plugin-search-backend-module-elasticsearch@1.7.9 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-backend-node@1.4.0 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-search-backend-module-explore@0.3.10 + +### Patch Changes + +- 9b69262: Updated dependency `@backstage-community/plugin-explore-common` to `^0.9.0`. +- Updated dependencies + - @backstage/plugin-search-backend-node@1.4.0 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-search-backend-module-pg@0.5.51 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-backend-node@1.4.0 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-search-backend-module-stack-overflow-collator@0.3.16 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-backend-node@1.4.0 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-search-backend-module-techdocs@0.4.9 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-backend-node@1.4.0 + - @backstage/plugin-techdocs-node@1.13.10 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## @backstage/plugin-search-react@1.10.1 + +### Patch Changes + +- 8947a4e: Skip the very first empty search when going to the landing page +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/theme@0.7.1 + +## @backstage/plugin-signals@0.0.26 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/theme@0.7.1 + - @backstage/plugin-signals-react@0.0.18 + +## @backstage/plugin-signals-backend@0.3.11 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-events-node@0.4.18 + - @backstage/plugin-signals-node@0.1.27 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-signals-node@0.1.27 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-signals-react@0.0.18 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.12.1 + +## @backstage/plugin-techdocs@1.16.1 + +### Patch Changes + +- f3f84f1: Minor extension type updates after frontend API bump +- 5c33821: Fixed schema type for additionalAllowedURIProtocols +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- 592361e: The `techdocs` config is now marked as optional. +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/plugin-search-react@1.10.1 + - @backstage/core-plugin-api@1.12.1 + - @backstage/theme@0.7.1 + - @backstage/integration-react@1.2.13 + - @backstage/plugin-auth-react@0.1.22 + - @backstage/plugin-techdocs-react@1.3.6 + +## @backstage/plugin-techdocs-backend@2.1.3 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- 2bae83a: Corrected `ErrorCallback` type to work with Node 22 types +- 592361e: The `techdocs` config is now marked as optional. +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-defaults@0.14.0 + - @backstage/plugin-techdocs-node@1.13.10 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## @backstage/plugin-techdocs-module-addons-contrib@1.1.31 + +### Patch Changes + +- 8d6709e: Updated tests to match test-utils change +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/integration-react@1.2.13 + - @backstage/plugin-techdocs-react@1.3.6 + +## @backstage/plugin-techdocs-node@1.13.10 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- 703f8c0: There was an issue in the uploading of large size files to the AWS S3. We have modified the logic by adding retry along with multipart uploading functionality. +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-plugin-api@1.6.0 + +## @backstage/plugin-techdocs-react@1.3.6 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + +## @backstage/plugin-user-settings@0.8.30 + +### Patch Changes + +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- Updated dependencies + - @backstage/core-app-api@1.19.3 + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/theme@0.7.1 + - @backstage/plugin-signals-react@0.0.18 + +## @backstage/plugin-user-settings-backend@0.3.9 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-defaults@0.14.0 + - @backstage/plugin-signals-node@0.1.27 + - @backstage/backend-plugin-api@1.6.0 + +## example-app@0.2.116 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.19.3 + - @backstage/cli@0.35.0 + - @backstage/ui@0.10.0 + - @backstage/plugin-catalog-graph@0.5.4 + - @backstage/plugin-api-docs@0.13.2 + - @backstage/plugin-techdocs@1.16.1 + - @backstage/plugin-catalog@1.32.1 + - @backstage/plugin-search@1.5.1 + - @backstage/plugin-org@0.6.47 + - @backstage/plugin-scaffolder-react@1.19.4 + - @backstage/core-components@0.18.4 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.31 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/plugin-kubernetes@0.12.14 + - @backstage/plugin-search-react@1.10.1 + - @backstage/core-plugin-api@1.12.1 + - @backstage/plugin-catalog-unprocessed-entities@0.2.24 + - @backstage/plugin-catalog-import@0.13.8 + - @backstage/plugin-notifications@0.5.12 + - @backstage/plugin-user-settings@0.8.30 + - @backstage/plugin-scaffolder@1.35.0 + - @backstage/plugin-devtools@0.1.34 + - @backstage/plugin-home@0.8.15 + - @backstage/theme@0.7.1 + - @backstage/plugin-kubernetes-cluster@0.0.32 + - @backstage/app-defaults@1.7.3 + - @backstage/frontend-app-api@0.13.3 + - @backstage/integration-react@1.2.13 + - @backstage/plugin-auth-react@0.1.22 + - @backstage/plugin-mui-to-bui@0.2.2 + - @backstage/plugin-permission-react@0.4.39 + - @backstage/plugin-signals@0.0.26 + - @backstage/plugin-techdocs-react@1.3.6 + +## example-app-next@0.0.30 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.19.3 + - @backstage/cli@0.35.0 + - @backstage/ui@0.10.0 + - @backstage/plugin-catalog-graph@0.5.4 + - @backstage/plugin-api-docs@0.13.2 + - @backstage/plugin-techdocs@1.16.1 + - @backstage/plugin-catalog@1.32.1 + - @backstage/plugin-search@1.5.1 + - @backstage/plugin-app@0.3.3 + - @backstage/plugin-org@0.6.47 + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/plugin-scaffolder-react@1.19.4 + - @backstage/core-components@0.18.4 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.31 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/plugin-kubernetes@0.12.14 + - @backstage/plugin-search-react@1.10.1 + - @backstage/core-plugin-api@1.12.1 + - @backstage/plugin-catalog-unprocessed-entities@0.2.24 + - @backstage/plugin-app-visualizer@0.1.26 + - @backstage/plugin-catalog-import@0.13.8 + - @backstage/plugin-notifications@0.5.12 + - @backstage/plugin-user-settings@0.8.30 + - @backstage/plugin-scaffolder@1.35.0 + - @backstage/plugin-home@0.8.15 + - @backstage/theme@0.7.1 + - @backstage/plugin-kubernetes-cluster@0.0.32 + - @backstage/app-defaults@1.7.3 + - @backstage/core-compat-api@0.5.5 + - @backstage/frontend-app-api@0.13.3 + - @backstage/frontend-defaults@0.3.4 + - @backstage/integration-react@1.2.13 + - @backstage/plugin-auth@0.1.3 + - @backstage/plugin-auth-react@0.1.22 + - @backstage/plugin-permission-react@0.4.39 + - @backstage/plugin-signals@0.0.26 + - @backstage/plugin-techdocs-react@1.3.6 + +## app-next-example-plugin@0.0.30 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + +## example-backend@0.0.45 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-mcp-actions-backend@0.1.6 + - @backstage/plugin-scaffolder-backend@3.1.0 + - @backstage/plugin-search-backend-node@1.4.0 + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-defaults@0.14.0 + - @backstage/plugin-app-backend@0.5.9 + - @backstage/plugin-auth-backend-module-guest-provider@0.2.15 + - @backstage/plugin-auth-backend-module-openshift-provider@0.1.3 + - @backstage/plugin-auth-backend@0.25.7 + - @backstage/plugin-catalog-backend@3.3.0 + - @backstage/plugin-devtools-backend@0.5.12 + - @backstage/plugin-events-backend@0.5.9 + - @backstage/plugin-kubernetes-backend@0.21.0 + - @backstage/plugin-notifications-backend@0.6.1 + - @backstage/plugin-permission-backend@0.7.7 + - @backstage/plugin-permission-node@0.10.7 + - @backstage/plugin-proxy-backend@0.6.9 + - @backstage/plugin-search-backend@2.0.9 + - @backstage/plugin-signals-backend@0.3.11 + - @backstage/plugin-techdocs-backend@2.1.3 + - @backstage/plugin-auth-backend-module-github-provider@0.4.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-backend-module-github@0.9.3 + - @backstage/plugin-search-backend-module-explore@0.3.10 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.9 + - @backstage/plugin-catalog-backend-module-openapi@0.2.17 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.15 + - @backstage/plugin-catalog-backend-module-unprocessed@0.6.7 + - @backstage/plugin-events-backend-module-google-pubsub@0.1.7 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.2.15 + - @backstage/plugin-scaffolder-backend-module-notifications@0.1.17 + - @backstage/plugin-search-backend-module-catalog@0.3.11 + - @backstage/plugin-search-backend-module-elasticsearch@1.7.9 + - @backstage/plugin-search-backend-module-techdocs@0.4.9 + +## e2e-test@0.2.35 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.7.7 + - @backstage/cli-common@0.1.16 + +## @internal/frontend@0.0.16 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + +## @internal/scaffolder@0.0.16 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/plugin-scaffolder-react@1.19.4 + +## techdocs-cli-embedded-app@0.2.115 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.19.3 + - @backstage/cli@0.35.0 + - @backstage/ui@0.10.0 + - @backstage/plugin-techdocs@1.16.1 + - @backstage/plugin-catalog@1.32.1 + - @backstage/core-components@0.18.4 + - @backstage/test-utils@1.7.14 + - @backstage/core-plugin-api@1.12.1 + - @backstage/theme@0.7.1 + - @backstage/app-defaults@1.7.3 + - @backstage/integration-react@1.2.13 + - @backstage/plugin-techdocs-react@1.3.6 + +## yarn-plugin-backstage@0.0.8 + +### Patch Changes + +- Updated dependencies + - @backstage/cli-common@0.1.16 + +## @internal/plugin-todo-list@1.0.46 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + +## @internal/plugin-todo-list-backend@1.0.46 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 diff --git a/docs/releases/v1.46.0-next.2-changelog.md b/docs/releases/v1.46.0-next.2-changelog.md new file mode 100644 index 0000000000..0bb2bf687d --- /dev/null +++ b/docs/releases/v1.46.0-next.2-changelog.md @@ -0,0 +1,1897 @@ +# Release v1.46.0-next.2 + +Upgrade Helper: [https://backstage.github.io/upgrade-helper/?to=1.46.0-next.2](https://backstage.github.io/upgrade-helper/?to=1.46.0-next.2) + +## @backstage/backend-plugin-api@1.6.0-next.1 + +### Minor Changes + +- 2a0c4b0: Adds a new experimental `RootSystemMetadataService` for tracking the collection of Backstage instances that may be deployed at any one time. It currently offers a single API, `getInstalledPlugins` that returns a list of installed plugins based on config you have set up in `discovery.endpoints` as well as the plugins installed on the instance you're calling the API with. It does not handle wildcard values or fallback values. The intention is for this plugin to provide plugin authors with a simple interface to fetch a trustworthy list of all installed plugins. + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/plugin-permission-node@0.10.7-next.1 + - @backstage/cli-common@0.1.16-next.2 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-permission-common@0.9.3 + +## @backstage/cli@0.35.0-next.2 + +### Minor Changes + +- f8dff94: Switched the default module resolution to `bundler` and the `module` setting to `ES2020`. + + You may need to bump some dependencies as part of this change and fix imports in code. The most common source of this is that type checking will now consider the `exports` field in `package.json` when resolving imports. This in turn can break older versions of packages that had incompatible `exports` fields. Generally these issues will have already been fixed in the upstream packages. + + You might be tempted to use `--skipLibCheck` to hide issues due to this change, but it will weaken the type safety of your project. If you run into a large number of issues and want to keep the old behavior, you can reset the `moduleResolution` and `module` settings your own `tsconfig.json` file to `node` and `ESNext` respectively. But keep in mind that the `node` option will be removed in future versions of TypeScript. + + A future version of Backstage will make these new settings mandatory, as we move to rely on the `exports` field for type resolution in packages, rather than the `typesVersions` field. + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- 1226647: Updated dependency `esbuild` to `^0.27.0`. +- f89a074: Updated dependency `@pmmmwh/react-refresh-webpack-plugin` to `^0.6.0`. +- 2b81751: Updated dependency `webpack` to `~5.103.0`. +- fafd9e1: Fixed internal usage of `yargs`. +- 2bae83a: Switched ECMAScript version to ES2023. +- 2bae83a: Bumped dev dependencies `@types/node` +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/config-loader@1.10.7-next.1 + - @backstage/cli-common@0.1.16-next.2 + - @backstage/catalog-model@1.7.6 + - @backstage/cli-node@0.2.16-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/eslint-plugin@0.2.0 + - @backstage/release-manifests@0.0.13 + - @backstage/types@1.2.2 + +## @backstage/plugin-kubernetes-backend@0.21.0-next.2 + +### Minor Changes + +- 7f9846f: Add possibility to extends Kubernetes REST API. Add fetcher to parameters for custom objects provider + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- fb029b6: Updated luxon types +- Updated dependencies + - @backstage/plugin-permission-node@0.10.7-next.1 + - @backstage/plugin-kubernetes-node@0.4.0-next.2 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/integration-aws-node@0.1.19 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-node@1.20.1-next.1 + - @backstage/plugin-kubernetes-common@0.9.9-next.0 + - @backstage/plugin-permission-common@0.9.3 + +## @backstage/plugin-kubernetes-node@0.4.0-next.2 + +### Minor Changes + +- 7f9846f: Add possibility to extends Kubernetes REST API. Add fetcher to parameters for custom objects provider + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/types@1.2.2 + - @backstage/plugin-kubernetes-common@0.9.9-next.0 + +## @backstage/plugin-scaffolder-backend-module-gitlab@0.11.0-next.1 + +### Minor Changes + +- f2d034b: In the `gitlabRepoPush` action, add 'auto' possibility for `commitAction` input. + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + +## @backstage/backend-app-api@1.4.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + +## @backstage/backend-defaults@0.14.0-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- aa79251: build(deps): bump `node-forge` from 1.3.1 to 1.3.2 +- f96edff: Allow configuration of the `referrerPolicy` +- fb029b6: Updated luxon types +- 847a330: Fix for `jose` types +- 25b560e: Internal change to support new versions of the `logform` library +- 2a0c4b0: Adds a new experimental `RootSystemMetadataService` for tracking the collection of Backstage instances that may be deployed at any one time. It currently offers a single API, `getInstalledPlugins` that returns a list of installed plugins based on config you have set up in `discovery.endpoints` as well as the plugins installed on the instance you're calling the API with. It does not handle wildcard values or fallback values. The intention is for this plugin to provide plugin authors with a simple interface to fetch a trustworthy list of all installed plugins. +- 3016a79: Updated dependency `@types/archiver` to `^7.0.0`. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/plugin-permission-node@0.10.7-next.1 + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config-loader@1.10.7-next.1 + - @backstage/backend-dev-utils@0.1.6-next.0 + - @backstage/backend-app-api@1.4.0-next.1 + - @backstage/cli-node@0.2.16-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/integration-aws-node@0.1.19 + - @backstage/types@1.2.2 + +## @backstage/backend-dev-utils@0.1.6-next.0 + +### Patch Changes + +- 2bae83a: Internal update for Node.js v24 support. + +## @backstage/backend-dynamic-feature-service@0.7.7-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-defaults@0.14.0-next.1 + - @backstage/backend-openapi-utils@0.6.4-next.1 + - @backstage/plugin-app-node@0.1.40-next.1 + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/plugin-catalog-backend@3.2.1-next.1 + - @backstage/plugin-events-backend@0.5.9-next.1 + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/plugin-permission-node@0.10.7-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config-loader@1.10.7-next.1 + - @backstage/cli-common@0.1.16-next.2 + - @backstage/cli-node@0.2.16-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-permission-common@0.9.3 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + - @backstage/plugin-search-backend-node@1.4.0-next.1 + - @backstage/plugin-search-common@1.2.21 + +## @backstage/backend-openapi-utils@0.6.4-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + +## @backstage/backend-test-utils@1.10.2-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- 8be23a4: Switched `textextensions` dependency for `text-extensions`. +- 5a737e1: Fix PostgreSQL 18 `TestDatabases` by pinning the data directory +- Updated dependencies + - @backstage/backend-defaults@0.14.0-next.1 + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/backend-app-api@1.4.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-permission-common@0.9.3 + +## @backstage/cli-common@0.1.16-next.2 + +### Patch Changes + +- 2bae83a: Bumped dev dependencies `@types/node` +- Updated dependencies + - @backstage/errors@1.2.7 + +## @backstage/codemods@0.1.53-next.2 + +### Patch Changes + +- 2bae83a: Bumped dev dependencies `@types/node` +- Updated dependencies + - @backstage/cli-common@0.1.16-next.2 + +## @backstage/config-loader@1.10.7-next.1 + +### Patch Changes + +- 741c47a: Updated dependency `typescript-json-schema` to `^0.67.0`. +- Updated dependencies + - @backstage/cli-common@0.1.16-next.2 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + +## @backstage/core-app-api@1.19.3-next.1 + +### Patch Changes + +- 75683ed: Added replay functionality to `AlertApiForwarder` to buffer and replay recent alerts to new subscribers, preventing missed alerts that were posted before subscription. +- Updated dependencies + - @backstage/config@1.3.6 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/types@1.2.2 + - @backstage/version-bridge@1.0.11 + +## @backstage/core-components@0.18.4-next.2 + +### Patch Changes + +- 4c00303: Add `tooltipClasses` prop to `OverflowTooltip` component to allow customisation of the tooltip +- Updated dependencies + - @backstage/config@1.3.6 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/errors@1.2.7 + - @backstage/theme@0.7.1-next.0 + - @backstage/version-bridge@1.0.11 + +## @backstage/create-app@0.7.7-next.2 + +### Patch Changes + +- 2bae83a: Updated engines to support Node 22 or 24 +- 2bae83a: Bumped dev dependencies `@types/node` +- Updated dependencies + - @backstage/cli-common@0.1.16-next.2 + +## @backstage/frontend-plugin-api@0.13.2-next.1 + +### Patch Changes + +- 75683ed: Added a new `errorPresentation` prop to `ExtensionBoundary` to control how errors are presented to the user. The default is `'error-display'`, which is the current behavior of showing the error in the `ErrorDisplay` component. The new option is `'error-api'`, posts errors to the `ErrorApi` and does not allow retries. + + The `AppRootElementBlueprint` now wraps its element in an `ErrorBoundary` using the new `'error-api'` presentation mode. + +- f3f84f1: Made the return type of `.withOverrides` to be simplified. + +- Updated dependencies + - @backstage/core-components@0.18.4-next.2 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/version-bridge@1.0.11 + +## @backstage/integration@1.18.3-next.1 + +### Patch Changes + +- fb029b6: Updated luxon types +- Updated dependencies + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + +## @backstage/repo-tools@0.16.1-next.2 + +### Patch Changes + +- 2bae83a: Bump `@microsoft/api-documenter` and `@microsoft/api-extractor` to latest versions. +- 2bae83a: Bumped dev dependencies `@types/node` +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config-loader@1.10.7-next.1 + - @backstage/cli-common@0.1.16-next.2 + - @backstage/catalog-model@1.7.6 + - @backstage/cli-node@0.2.16-next.1 + - @backstage/errors@1.2.7 + +## @techdocs/cli@1.10.3-next.2 + +### Patch Changes + +- 2bae83a: Bumped dev dependencies `@types/node` +- Updated dependencies + - @backstage/backend-defaults@0.14.0-next.1 + - @backstage/plugin-techdocs-node@1.13.10-next.1 + - @backstage/cli-common@0.1.16-next.2 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + +## @backstage/plugin-api-docs@0.13.2-next.1 + +### Patch Changes + +- f3f84f1: Minor extension type updates after frontend API bump +- Updated dependencies + - @backstage/plugin-catalog@1.32.1-next.1 + - @backstage/frontend-plugin-api@0.13.2-next.1 + - @backstage/plugin-catalog-react@1.21.4-next.2 + - @backstage/core-components@0.18.4-next.2 + - @backstage/catalog-model@1.7.6 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-permission-react@0.4.39-next.0 + +## @backstage/plugin-app@0.3.3-next.1 + +### Patch Changes + +- f3f84f1: Minor extension type updates after frontend API bump +- f7bc228: Support to set `defaultLanguage` and `availableLanguages` for the app language API in the new frontend system +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2-next.1 + - @backstage/core-components@0.18.4-next.2 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/integration-react@1.2.13-next.0 + - @backstage/theme@0.7.1-next.0 + - @backstage/types@1.2.2 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-permission-react@0.4.39-next.0 + +## @backstage/plugin-app-backend@0.5.9-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-app-node@0.1.40-next.1 + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config-loader@1.10.7-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + +## @backstage/plugin-app-node@0.1.40-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config-loader@1.10.7-next.1 + +## @backstage/plugin-auth-backend@0.25.7-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-node@1.20.1-next.1 + +## @backstage/plugin-auth-backend-module-atlassian-provider@0.4.10-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + +## @backstage/plugin-auth-backend-module-auth0-provider@0.2.10-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + +## @backstage/plugin-auth-backend-module-aws-alb-provider@0.4.10-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-backend@0.25.7-next.1 + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/errors@1.2.7 + +## @backstage/plugin-auth-backend-module-azure-easyauth-provider@0.2.15-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/errors@1.2.7 + +## @backstage/plugin-auth-backend-module-bitbucket-provider@0.3.10-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + +## @backstage/plugin-auth-backend-module-bitbucket-server-provider@0.2.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + +## @backstage/plugin-auth-backend-module-cloudflare-access-provider@0.4.10-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + +## @backstage/plugin-auth-backend-module-gcp-iap-provider@0.4.10-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + +## @backstage/plugin-auth-backend-module-github-provider@0.3.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + +## @backstage/plugin-auth-backend-module-gitlab-provider@0.3.10-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + +## @backstage/plugin-auth-backend-module-google-provider@0.3.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + +## @backstage/plugin-auth-backend-module-guest-provider@0.2.15-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/errors@1.2.7 + +## @backstage/plugin-auth-backend-module-microsoft-provider@0.3.10-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + +## @backstage/plugin-auth-backend-module-oauth2-provider@0.4.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + +## @backstage/plugin-auth-backend-module-oauth2-proxy-provider@0.2.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/errors@1.2.7 + +## @backstage/plugin-auth-backend-module-oidc-provider@0.4.10-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-backend@0.25.7-next.1 + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/types@1.2.2 + +## @backstage/plugin-auth-backend-module-okta-provider@0.2.10-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + +## @backstage/plugin-auth-backend-module-onelogin-provider@0.3.10-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + +## @backstage/plugin-auth-backend-module-openshift-provider@0.1.3-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/types@1.2.2 + +## @backstage/plugin-auth-backend-module-pinniped-provider@0.3.10-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/types@1.2.2 + +## @backstage/plugin-auth-backend-module-vmware-cloud-provider@0.5.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + +## @backstage/plugin-auth-node@0.6.10-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- e9dd634: fix flawed cookie removal logic with chunked tokens +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + +## @backstage/plugin-catalog@1.32.1-next.1 + +### Patch Changes + +- f3f84f1: Minor extension type updates after frontend API bump +- 91f5ed8: Fixed `catalogAboutEntityCard` to filter icon links before calling useProps(), preventing side effects from hooks in filtered-out links +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2-next.1 + - @backstage/plugin-catalog-react@1.21.4-next.2 + - @backstage/core-components@0.18.4-next.2 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/core-compat-api@0.5.5-next.0 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/errors@1.2.7 + - @backstage/integration-react@1.2.13-next.0 + - @backstage/types@1.2.2 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-permission-react@0.4.39-next.0 + - @backstage/plugin-scaffolder-common@1.7.4-next.0 + - @backstage/plugin-search-common@1.2.21 + - @backstage/plugin-search-react@1.10.1-next.0 + - @backstage/plugin-techdocs-common@0.1.1 + - @backstage/plugin-techdocs-react@1.3.6-next.0 + +## @backstage/plugin-catalog-backend@3.2.1-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-openapi-utils@0.6.4-next.1 + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/plugin-permission-node@0.10.7-next.1 + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + - @backstage/plugin-permission-common@0.9.3 + +## @backstage/plugin-catalog-backend-module-aws@0.4.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.14.0-next.1 + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/integration-aws-node@0.1.19 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + - @backstage/plugin-kubernetes-common@0.9.9-next.0 + +## @backstage/plugin-catalog-backend-module-azure@0.3.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + +## @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-openapi-utils@0.6.4-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.5.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/plugin-bitbucket-cloud-common@0.3.5-next.0 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.5.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + +## @backstage/plugin-catalog-backend-module-gcp@0.3.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/plugin-catalog-node@1.20.1-next.1 + - @backstage/plugin-kubernetes-common@0.9.9-next.0 + +## @backstage/plugin-catalog-backend-module-gerrit@0.3.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + +## @backstage/plugin-catalog-backend-module-gitea@0.1.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + +## @backstage/plugin-catalog-backend-module-github@0.11.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + +## @backstage/plugin-catalog-backend-module-github-org@0.3.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/plugin-catalog-backend-module-github@0.11.3-next.2 + - @backstage/plugin-catalog-node@1.20.1-next.1 + +## @backstage/plugin-catalog-backend-module-gitlab@0.7.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.14.0-next.1 + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + +## @backstage/plugin-catalog-backend-module-gitlab-org@0.2.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/plugin-catalog-backend-module-gitlab@0.7.6-next.1 + - @backstage/plugin-catalog-node@1.20.1-next.1 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.7.7-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- fb029b6: Updated luxon types +- Updated dependencies + - @backstage/backend-defaults@0.14.0-next.1 + - @backstage/plugin-catalog-backend@3.2.1-next.1 + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-node@1.20.1-next.1 + - @backstage/plugin-permission-common@0.9.3 + +## @backstage/plugin-catalog-backend-module-ldap@0.12.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + +## @backstage/plugin-catalog-backend-module-logs@0.1.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@3.2.1-next.1 + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + +## @backstage/plugin-catalog-backend-module-msgraph@0.8.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + +## @backstage/plugin-catalog-backend-module-openapi@0.2.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + +## @backstage/plugin-catalog-backend-module-puppetdb@0.2.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-node@1.20.1-next.1 + +## @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + - @backstage/plugin-scaffolder-common@1.7.4-next.0 + +## @backstage/plugin-catalog-backend-module-unprocessed@0.6.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + - @backstage/plugin-catalog-unprocessed-entities-common@0.0.12-next.0 + - @backstage/plugin-permission-common@0.9.3 + +## @backstage/plugin-catalog-graph@0.5.4-next.1 + +### Patch Changes + +- f3f84f1: Minor extension type updates after frontend API bump +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2-next.1 + - @backstage/plugin-catalog-react@1.21.4-next.2 + - @backstage/core-components@0.18.4-next.2 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/types@1.2.2 + +## @backstage/plugin-catalog-node@1.20.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-node@0.10.7-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-permission-common@0.9.3 + +## @backstage/plugin-catalog-react@1.21.4-next.2 + +### Patch Changes + +- b3c0594: Use a versioned context for `useEntityList`, to better work with mixed `@backstage/plugin-catalog-react` versions. +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2-next.1 + - @backstage/core-components@0.18.4-next.2 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/core-compat-api@0.5.5-next.0 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/errors@1.2.7 + - @backstage/frontend-test-utils@0.4.2-next.0 + - @backstage/integration-react@1.2.13-next.0 + - @backstage/types@1.2.2 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-permission-common@0.9.3 + - @backstage/plugin-permission-react@0.4.39-next.0 + +## @backstage/plugin-devtools-backend@0.5.12-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-defaults@0.14.0-next.1 + - @backstage/plugin-permission-node@0.10.7-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config-loader@1.10.7-next.1 + - @backstage/cli-common@0.1.16-next.2 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-devtools-common@0.1.19 + - @backstage/plugin-permission-common@0.9.3 + +## @backstage/plugin-events-backend@0.5.9-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-openapi-utils@0.6.4-next.1 + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + +## @backstage/plugin-events-backend-module-aws-sqs@0.4.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/types@1.2.2 + +## @backstage/plugin-events-backend-module-azure@0.2.27-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + +## @backstage/plugin-events-backend-module-bitbucket-cloud@0.2.27-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + +## @backstage/plugin-events-backend-module-bitbucket-server@0.1.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + +## @backstage/plugin-events-backend-module-gerrit@0.2.27-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + +## @backstage/plugin-events-backend-module-github@0.4.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/types@1.2.2 + +## @backstage/plugin-events-backend-module-gitlab@0.3.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + +## @backstage/plugin-events-backend-module-google-pubsub@0.1.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + +## @backstage/plugin-events-backend-module-kafka@0.1.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/types@1.2.2 + +## @backstage/plugin-events-node@0.4.18-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + +## @backstage/plugin-gateway-backend@1.1.1-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + +## @backstage/plugin-home@0.8.15-next.1 + +### Patch Changes + +- be21c5c: Updated dependency `@rjsf/utils` to `5.24.13`. + Updated dependency `@rjsf/core` to `5.24.13`. + Updated dependency `@rjsf/material-ui` to `5.24.13`. + Updated dependency `@rjsf/validator-ajv8` to `5.24.13`. +- Updated dependencies + - @backstage/core-app-api@1.19.3-next.1 + - @backstage/frontend-plugin-api@0.13.2-next.1 + - @backstage/plugin-catalog-react@1.21.4-next.2 + - @backstage/core-components@0.18.4-next.2 + - @backstage/plugin-home-react@0.1.33-next.1 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/theme@0.7.1-next.0 + +## @backstage/plugin-home-react@0.1.33-next.1 + +### Patch Changes + +- be21c5c: Updated dependency `@rjsf/utils` to `5.24.13`. + Updated dependency `@rjsf/core` to `5.24.13`. + Updated dependency `@rjsf/material-ui` to `5.24.13`. + Updated dependency `@rjsf/validator-ajv8` to `5.24.13`. +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2-next.1 + - @backstage/core-components@0.18.4-next.2 + - @backstage/core-plugin-api@1.12.1-next.0 + +## @backstage/plugin-kubernetes-cluster@0.0.32-next.2 + +### Patch Changes + +- 2bae83a: Bumped dev dependencies `@types/node` +- Updated dependencies + - @backstage/plugin-catalog-react@1.21.4-next.2 + - @backstage/core-components@0.18.4-next.2 + - @backstage/catalog-model@1.7.6 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/plugin-kubernetes-common@0.9.9-next.0 + - @backstage/plugin-kubernetes-react@0.5.14-next.1 + - @backstage/plugin-permission-react@0.4.39-next.0 + +## @backstage/plugin-mcp-actions-backend@0.1.6-next.1 + +### Patch Changes + +- e83e038: Added `@cfworker/json-schema` as a dependency to this package part of the `@modelcontextprotocol/sdk` bump as it's required in the types +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-defaults@0.14.0-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-client@1.12.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-node@1.20.1-next.1 + +## @backstage/plugin-notifications-backend@0.6.1-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-signals-node@0.1.27-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-node@1.20.1-next.1 + - @backstage/plugin-notifications-common@0.2.0 + - @backstage/plugin-notifications-node@0.2.22-next.1 + +## @backstage/plugin-notifications-backend-module-email@0.3.17-next.1 + +### Patch Changes + +- b267aea: Updated dependency `@types/nodemailer` to `^7.0.0`. +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/integration-aws-node@0.1.19 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-node@1.20.1-next.1 + - @backstage/plugin-notifications-common@0.2.0 + - @backstage/plugin-notifications-node@0.2.22-next.1 + +## @backstage/plugin-notifications-backend-module-slack@0.2.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-node@1.20.1-next.1 + - @backstage/plugin-notifications-common@0.2.0 + - @backstage/plugin-notifications-node@0.2.22-next.1 + +## @backstage/plugin-notifications-node@0.2.22-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-signals-node@0.1.27-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/plugin-notifications-common@0.2.0 + +## @backstage/plugin-org@0.6.47-next.1 + +### Patch Changes + +- f3f84f1: Minor extension type updates after frontend API bump +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2-next.1 + - @backstage/plugin-catalog-react@1.21.4-next.2 + - @backstage/core-components@0.18.4-next.2 + - @backstage/catalog-model@1.7.6 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/plugin-catalog-common@1.1.7 + +## @backstage/plugin-permission-backend@0.7.7-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/plugin-permission-node@0.10.7-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-permission-common@0.9.3 + +## @backstage/plugin-permission-backend-module-allow-all-policy@0.2.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/plugin-permission-node@0.10.7-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/plugin-permission-common@0.9.3 + +## @backstage/plugin-permission-node@0.10.7-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-permission-common@0.9.3 + +## @backstage/plugin-proxy-backend@0.6.9-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/types@1.2.2 + - @backstage/plugin-proxy-node@0.1.11-next.1 + +## @backstage/plugin-proxy-node@0.1.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + +## @backstage/plugin-scaffolder@1.34.4-next.1 + +### Patch Changes + +- be21c5c: Updated dependency `@rjsf/utils` to `5.24.13`. + Updated dependency `@rjsf/core` to `5.24.13`. + Updated dependency `@rjsf/material-ui` to `5.24.13`. + Updated dependency `@rjsf/validator-ajv8` to `5.24.13`. +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2-next.1 + - @backstage/plugin-scaffolder-react@1.19.4-next.2 + - @backstage/integration@1.18.3-next.1 + - @backstage/plugin-catalog-react@1.21.4-next.2 + - @backstage/core-components@0.18.4-next.2 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/errors@1.2.7 + - @backstage/integration-react@1.2.13-next.0 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-permission-react@0.4.39-next.0 + - @backstage/plugin-scaffolder-common@1.7.4-next.0 + - @backstage/plugin-techdocs-common@0.1.1 + - @backstage/plugin-techdocs-react@1.3.6-next.0 + +## @backstage/plugin-scaffolder-backend@3.1.0-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- 2bae83a: Updated `isolated-vm` to `6.0.1` +- 25b560e: Internal change to support new versions of the `logform` library +- 1226647: Updated dependency `esbuild` to `^0.27.0`. +- Updated dependencies + - @backstage/plugin-scaffolder-backend-module-gitlab@0.11.0-next.1 + - @backstage/backend-defaults@0.14.0-next.1 + - @backstage/backend-openapi-utils@0.6.4-next.1 + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/plugin-permission-node@0.10.7-next.1 + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.16-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-bitbucket-cloud-common@0.3.5-next.0 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.15-next.1 + - @backstage/plugin-catalog-node@1.20.1-next.1 + - @backstage/plugin-permission-common@0.9.3 + - @backstage/plugin-scaffolder-backend-module-azure@0.2.16-next.1 + - @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.17-next.1 + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.16-next.1 + - @backstage/plugin-scaffolder-backend-module-gerrit@0.2.16-next.1 + - @backstage/plugin-scaffolder-backend-module-gitea@0.2.16-next.1 + - @backstage/plugin-scaffolder-backend-module-github@0.9.3-next.1 + - @backstage/plugin-scaffolder-common@1.7.4-next.0 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + +## @backstage/plugin-scaffolder-backend-module-azure@0.2.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + +## @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.16-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.16-next.1 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + +## @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-bitbucket-cloud-common@0.3.5-next.0 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + +## @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.16-next.1 + +### Patch Changes + +- 5a6aca2: Improve error message when provided target branch is missing +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + +## @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.3.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.3.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.14.0-next.1 + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + +## @backstage/plugin-scaffolder-backend-module-gcp@0.2.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + +## @backstage/plugin-scaffolder-backend-module-gerrit@0.2.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + +## @backstage/plugin-scaffolder-backend-module-gitea@0.2.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + +## @backstage/plugin-scaffolder-backend-module-github@0.9.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-node@1.20.1-next.1 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + +## @backstage/plugin-scaffolder-backend-module-notifications@0.1.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/plugin-notifications-common@0.2.0 + - @backstage/plugin-notifications-node@0.2.22-next.1 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + +## @backstage/plugin-scaffolder-backend-module-rails@0.5.16-next.1 + +### Patch Changes + +- 2bae83a: Bumped dev dependencies `@types/node` +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.2.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.4.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/types@1.2.2 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + - @backstage/plugin-scaffolder-node-test-utils@0.3.6-next.1 + +## @backstage/plugin-scaffolder-node@0.12.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-permission-common@0.9.3 + - @backstage/plugin-scaffolder-common@1.7.4-next.0 + +## @backstage/plugin-scaffolder-node-test-utils@0.3.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-test-utils@1.10.2-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/types@1.2.2 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + +## @backstage/plugin-scaffolder-react@1.19.4-next.2 + +### Patch Changes + +- fb029b6: Updated luxon types +- be21c5c: Updated dependency `@rjsf/utils` to `5.24.13`. + Updated dependency `@rjsf/core` to `5.24.13`. + Updated dependency `@rjsf/material-ui` to `5.24.13`. + Updated dependency `@rjsf/validator-ajv8` to `5.24.13`. +- 9b38f22: Updated dependency `use-immer` to `^0.11.0`. +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2-next.1 + - @backstage/plugin-catalog-react@1.21.4-next.2 + - @backstage/core-components@0.18.4-next.2 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/theme@0.7.1-next.0 + - @backstage/types@1.2.2 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-permission-react@0.4.39-next.0 + - @backstage/plugin-scaffolder-common@1.7.4-next.0 + +## @backstage/plugin-search@1.5.1-next.1 + +### Patch Changes + +- f3f84f1: Minor extension type updates after frontend API bump +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2-next.1 + - @backstage/plugin-catalog-react@1.21.4-next.2 + - @backstage/core-components@0.18.4-next.2 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-search-common@1.2.21 + - @backstage/plugin-search-react@1.10.1-next.0 + +## @backstage/plugin-search-backend@2.0.9-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-defaults@0.14.0-next.1 + - @backstage/backend-openapi-utils@0.6.4-next.1 + - @backstage/plugin-permission-node@0.10.7-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-permission-common@0.9.3 + - @backstage/plugin-search-backend-node@1.4.0-next.1 + - @backstage/plugin-search-common@1.2.21 + +## @backstage/plugin-search-backend-module-catalog@0.3.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + - @backstage/plugin-permission-common@0.9.3 + - @backstage/plugin-search-backend-node@1.4.0-next.1 + - @backstage/plugin-search-common@1.2.21 + +## @backstage/plugin-search-backend-module-elasticsearch@1.7.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/integration-aws-node@0.1.19 + - @backstage/plugin-search-backend-node@1.4.0-next.1 + - @backstage/plugin-search-common@1.2.21 + +## @backstage/plugin-search-backend-module-explore@0.3.10-next.1 + +### Patch Changes + +- 9b69262: Updated dependency `@backstage-community/plugin-explore-common` to `^0.9.0`. +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/plugin-search-backend-node@1.4.0-next.1 + - @backstage/plugin-search-common@1.2.21 + +## @backstage/plugin-search-backend-module-pg@0.5.51-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/plugin-search-backend-node@1.4.0-next.1 + - @backstage/plugin-search-common@1.2.21 + +## @backstage/plugin-search-backend-module-stack-overflow-collator@0.3.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/plugin-search-backend-node@1.4.0-next.1 + - @backstage/plugin-search-common@1.2.21 + +## @backstage/plugin-search-backend-module-techdocs@0.4.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-techdocs-node@1.13.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + - @backstage/plugin-permission-common@0.9.3 + - @backstage/plugin-search-backend-node@1.4.0-next.1 + - @backstage/plugin-search-common@1.2.21 + +## @backstage/plugin-search-backend-node@1.4.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-permission-common@0.9.3 + - @backstage/plugin-search-common@1.2.21 + +## @backstage/plugin-signals-backend@0.3.11-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/plugin-signals-node@0.1.27-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/types@1.2.2 + +## @backstage/plugin-signals-node@0.1.27-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/types@1.2.2 + +## @backstage/plugin-techdocs@1.16.1-next.2 + +### Patch Changes + +- f3f84f1: Minor extension type updates after frontend API bump +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2-next.1 + - @backstage/integration@1.18.3-next.1 + - @backstage/plugin-catalog-react@1.21.4-next.2 + - @backstage/core-components@0.18.4-next.2 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/errors@1.2.7 + - @backstage/integration-react@1.2.13-next.0 + - @backstage/theme@0.7.1-next.0 + - @backstage/plugin-auth-react@0.1.22-next.0 + - @backstage/plugin-search-common@1.2.21 + - @backstage/plugin-search-react@1.10.1-next.0 + - @backstage/plugin-techdocs-common@0.1.1 + - @backstage/plugin-techdocs-react@1.3.6-next.0 + +## @backstage/plugin-techdocs-backend@2.1.3-next.2 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- 2bae83a: Corrected `ErrorCallback` type to work with Node 22 types +- Updated dependencies + - @backstage/backend-defaults@0.14.0-next.1 + - @backstage/plugin-techdocs-node@1.13.10-next.1 + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-node@1.20.1-next.1 + +## @backstage/plugin-techdocs-node@1.13.10-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- 703f8c0: There was an issue in the uploading of large size files to the AWS S3. We have modified the logic by adding retry along with multipart uploading functionality. +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/integration-aws-node@0.1.19 + - @backstage/plugin-search-common@1.2.21 + - @backstage/plugin-techdocs-common@0.1.1 + +## @backstage/plugin-user-settings-backend@0.3.9-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-defaults@0.14.0-next.1 + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/plugin-signals-node@0.1.27-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-user-settings-common@0.0.1 + +## example-app@0.2.116-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.19.3-next.1 + - @backstage/cli@0.35.0-next.2 + - @backstage/plugin-catalog-graph@0.5.4-next.1 + - @backstage/plugin-api-docs@0.13.2-next.1 + - @backstage/plugin-techdocs@1.16.1-next.2 + - @backstage/plugin-catalog@1.32.1-next.1 + - @backstage/plugin-search@1.5.1-next.1 + - @backstage/plugin-org@0.6.47-next.1 + - @backstage/plugin-scaffolder-react@1.19.4-next.2 + - @backstage/plugin-catalog-react@1.21.4-next.2 + - @backstage/core-components@0.18.4-next.2 + - @backstage/plugin-home@0.8.15-next.1 + - @backstage/plugin-scaffolder@1.34.4-next.1 + - @backstage/plugin-kubernetes-cluster@0.0.32-next.2 + - @backstage/app-defaults@1.7.3-next.0 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/frontend-app-api@0.13.3-next.0 + - @backstage/integration-react@1.2.13-next.0 + - @backstage/theme@0.7.1-next.0 + - @backstage/ui@0.10.0-next.1 + - @backstage/plugin-auth-react@0.1.22-next.0 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-import@0.13.8-next.0 + - @backstage/plugin-catalog-unprocessed-entities@0.2.24-next.1 + - @backstage/plugin-devtools@0.1.34-next.0 + - @backstage/plugin-kubernetes@0.12.14-next.1 + - @backstage/plugin-mui-to-bui@0.2.2-next.1 + - @backstage/plugin-notifications@0.5.12-next.0 + - @backstage/plugin-permission-react@0.4.39-next.0 + - @backstage/plugin-search-common@1.2.21 + - @backstage/plugin-search-react@1.10.1-next.0 + - @backstage/plugin-signals@0.0.26-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.31-next.1 + - @backstage/plugin-techdocs-react@1.3.6-next.0 + - @backstage/plugin-user-settings@0.8.30-next.0 + +## example-app-next@0.0.30-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.19.3-next.1 + - @backstage/cli@0.35.0-next.2 + - @backstage/plugin-catalog-graph@0.5.4-next.1 + - @backstage/plugin-api-docs@0.13.2-next.1 + - @backstage/plugin-techdocs@1.16.1-next.2 + - @backstage/plugin-catalog@1.32.1-next.1 + - @backstage/plugin-search@1.5.1-next.1 + - @backstage/plugin-app@0.3.3-next.1 + - @backstage/plugin-org@0.6.47-next.1 + - @backstage/frontend-plugin-api@0.13.2-next.1 + - @backstage/plugin-scaffolder-react@1.19.4-next.2 + - @backstage/plugin-catalog-react@1.21.4-next.2 + - @backstage/core-components@0.18.4-next.2 + - @backstage/plugin-home@0.8.15-next.1 + - @backstage/plugin-scaffolder@1.34.4-next.1 + - @backstage/plugin-kubernetes-cluster@0.0.32-next.2 + - @backstage/app-defaults@1.7.3-next.0 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/core-compat-api@0.5.5-next.0 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/frontend-app-api@0.13.3-next.0 + - @backstage/frontend-defaults@0.3.4-next.0 + - @backstage/integration-react@1.2.13-next.0 + - @backstage/theme@0.7.1-next.0 + - @backstage/ui@0.10.0-next.1 + - @backstage/plugin-app-visualizer@0.1.26-next.1 + - @backstage/plugin-auth@0.1.3-next.0 + - @backstage/plugin-auth-react@0.1.22-next.0 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-import@0.13.8-next.0 + - @backstage/plugin-catalog-unprocessed-entities@0.2.24-next.1 + - @backstage/plugin-kubernetes@0.12.14-next.1 + - @backstage/plugin-notifications@0.5.12-next.0 + - @backstage/plugin-permission-react@0.4.39-next.0 + - @backstage/plugin-search-common@1.2.21 + - @backstage/plugin-search-react@1.10.1-next.0 + - @backstage/plugin-signals@0.0.26-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.31-next.1 + - @backstage/plugin-techdocs-react@1.3.6-next.0 + - @backstage/plugin-user-settings@0.8.30-next.0 + +## example-backend@0.0.45-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-mcp-actions-backend@0.1.6-next.1 + - @backstage/backend-defaults@0.14.0-next.1 + - @backstage/plugin-app-backend@0.5.9-next.1 + - @backstage/plugin-auth-backend-module-guest-provider@0.2.15-next.1 + - @backstage/plugin-auth-backend-module-openshift-provider@0.1.3-next.1 + - @backstage/plugin-auth-backend@0.25.7-next.1 + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/plugin-catalog-backend@3.2.1-next.1 + - @backstage/plugin-devtools-backend@0.5.12-next.1 + - @backstage/plugin-events-backend@0.5.9-next.1 + - @backstage/plugin-kubernetes-backend@0.21.0-next.2 + - @backstage/plugin-notifications-backend@0.6.1-next.1 + - @backstage/plugin-permission-backend@0.7.7-next.1 + - @backstage/plugin-permission-node@0.10.7-next.1 + - @backstage/plugin-proxy-backend@0.6.9-next.1 + - @backstage/plugin-scaffolder-backend@3.1.0-next.1 + - @backstage/plugin-search-backend@2.0.9-next.1 + - @backstage/plugin-signals-backend@0.3.11-next.1 + - @backstage/plugin-techdocs-backend@2.1.3-next.2 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/plugin-search-backend-module-explore@0.3.10-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/plugin-auth-backend-module-github-provider@0.3.10-next.1 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.9-next.1 + - @backstage/plugin-catalog-backend-module-openapi@0.2.17-next.1 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.15-next.1 + - @backstage/plugin-catalog-backend-module-unprocessed@0.6.7-next.2 + - @backstage/plugin-events-backend-module-google-pubsub@0.1.7-next.1 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.2.15-next.1 + - @backstage/plugin-permission-common@0.9.3 + - @backstage/plugin-scaffolder-backend-module-github@0.9.3-next.1 + - @backstage/plugin-scaffolder-backend-module-notifications@0.1.17-next.1 + - @backstage/plugin-search-backend-module-catalog@0.3.11-next.1 + - @backstage/plugin-search-backend-module-elasticsearch@1.7.9-next.1 + - @backstage/plugin-search-backend-module-techdocs@0.4.9-next.1 + - @backstage/plugin-search-backend-node@1.4.0-next.1 + +## techdocs-cli-embedded-app@0.2.115-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.19.3-next.1 + - @backstage/cli@0.35.0-next.2 + - @backstage/plugin-techdocs@1.16.1-next.2 + - @backstage/plugin-catalog@1.32.1-next.1 + - @backstage/core-components@0.18.4-next.2 + - @backstage/app-defaults@1.7.3-next.0 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/integration-react@1.2.13-next.0 + - @backstage/test-utils@1.7.14-next.0 + - @backstage/theme@0.7.1-next.0 + - @backstage/ui@0.10.0-next.1 + - @backstage/plugin-techdocs-react@1.3.6-next.0 + +## @internal/plugin-todo-list-backend@1.0.46-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/errors@1.2.7 diff --git a/docs/releases/v1.46.0.md b/docs/releases/v1.46.0.md new file mode 100644 index 0000000000..9ee4c68681 --- /dev/null +++ b/docs/releases/v1.46.0.md @@ -0,0 +1,129 @@ +--- +id: v1.46.0 +title: v1.46.0 +description: Backstage Release v1.46.0 +--- + +These are the release notes for the v1.46.0 release of [Backstage](https://backstage.io/). + +A huge thanks to the whole team of maintainers and contributors as well as the amazing Backstage Community for the hard work in getting this release developed and done. + +## Highlights + +To begin with, this release has a few important framework level updates. + +### **BREAKING:** Updated supported Node.js versions to 22 and 24 + +This release moves up the supported Node.js versions to 22 and 24, according to our [versioning policy](https://backstage.io/docs/overview/versioning-policy#nodejs-releases). As part of this change, we are also setting the compilation targets to ES2023, which lines up with the supported Node.js versions. + +The default TypeScript `target` compiler option is however left at ES2022. This is because older versions of TypeScript will error if they see an unsupported value, even if an override is set in your local `tsconfig.json`. You can still choose to set the TypeScript `target` to either `ES2023` or even `ES2024` in your own `tsconfig.json` if you prefer. + +### **BREAKING:** Switched modules to `ES2020` and resolution mode to `bundler` + +Now that the ecosystem has had some time to mature and adapt, we have finally switched over the default module resolution mode to `bundler` instead of `node`. The `module` setting was also changed to `ES2022`. + +You _may_ need to bump some dependencies as part of this change, or fix imports in code. The most common source of this is that type checking will now consider the `exports` field in `package.json` when resolving imports. This in turn can break older versions of packages that had incompatible `exports` fields. Generally these issues will have already been fixed in the upstream packages, but if you depend on old versions or unmaintained packages, you may still notice some effects of this. + +You might be tempted to use `--skipLibCheck` to hide issues due to this change, but it will weaken the type safety of your project. If you run into a large number of issues and want to keep the old behavior, you can reset the `moduleResolution` and `module` settings of your own `tsconfig.json` file to `node` and `ESNext` respectively. But keep in mind that the `node` option will be removed in future versions of TypeScript. + +A future version of Backstage will make these new settings mandatory, as we move to rely on the `exports` field for type resolution in packages, rather than the `typesVersions` field. + +### **BREAKING:** Moving toward updating `jest` and its DOM + +The `jest` test framework used to be a builtin dependency of the Backstage CLI. In this release, it has been made into a peer dependency to allow for easy upgrades to newer versions as you see fit. + +If you run tests using the Backstage CLI, you must therefore add Jest and its environment dependencies as `devDependencies` in your project root `package.json` when you upgrade. + +You can choose to install either Jest 29 or Jest 30. The built-in Jest version before this change was Jest 29, however, we recommend that you switch to Jest 30. Upgrading will solve the `Could not parse CSS stylesheet` errors, allow you to use MSW v2 in web packages, and ensure that you remain compatible with future versions of the Backstage CLI. Support for Jest 29 is temporary, with the purpose of allowing you to upgrade at your own pace, but it will eventually be removed. + +- **Jest 29**: Install `jest@^29` and `jest-environment-jsdom@^29` in your root `package.json`. No migration needed, but you may see `Could not parse CSS stylesheet` warnings/errors when testing components from `@backstage/ui` or other packages using CSS `@layer` declarations. +- **Jest 30**: Install `jest@^30`, `@types/jest@^30`, `@jest/environment-jsdom-abstract@^30`, and `jsdom@^27` in your root `package.json`. Fixes the stylesheet parsing warnings/errors, but requires migration steps. + +See the [Jest 30 migration guide](https://backstage.io/docs/tutorials/jest30-migration) for detailed migration instructions. + +### **BREAKING:** Now using correct configuration options for Valkey + +If you are using Valkey as your backend cache provider, take note. It used to piggyback on the Redis configuration format, but that was not quite correct. So its config options have been updated to better match its capabilities. + +So if you use Valkey, you need to upgrade your `app-config.yaml`: + +```diff +backend: + cache: + store: valkey + connection: ... + client: +- namespace: 'my-app' +- keyPrefixSeparator: ':' ++ keyPrefix: 'my-app:' +- clearBatchSize: 1000 +- useUnlink: false +``` + +Contributed by [@benjidotsh](https://github.com/benjidotsh) in [#31497](https://github.com/backstage/backstage/pull/31497) + +### **BREAKING:** Techdocs addon test utils removed explicit `screen` + +`TechdocsAddonTester.renderWithEffects()` used to return a `screen` that you could use for things like `getByText`. In order to support moving to newer versions of `@testing-library`, we have removed this, and you should import and use the normal `screen` from `@testing-library/react` instead. + +However: that `screen` can’t see inside the shadow DOM, which TechDocs uses. So if your tests need to look inside shadow DOM, you must install `shadow-dom-testing-library` and use its `screen` which provides special shadow-DOM queries, such as `getByShadowText` instead of `getByText. + +Example: + +```tsx +import { screen } from 'shadow-dom-testing-library'; +// ... render the addon ... +await TechDocsAddonTester.buildAddonsInTechDocs([]) + .withDom(TEST_CONTENT) + .renderWithEffects(); +expect(screen.getByShadowText('TEST_CONTENT')).toBeInTheDocument(); +``` + +### **BREAKING:** Backstage-UI advances! + +Again, Backstage-UI has a bunch of updates! One of them is breaking: If you were using the `Cell` component with text-specific props (`title` etc), you should now instead use the `CellText` component for that. Plain `Cell` is now meant to be used with generic child elements instead. + +### Simplified route compatibility + +If you are partway through a migration to the New Frontend System, you may enjoy the fact that the `useApp` and `useRouteRef` hooks now are forwards compatible with NFS. Along with the previous route reference changes this means that there is no longer a need to use `compatWrapper` from `@backstage/core-compat-api` to make code based on `@backstage/core-plugin-api` compatible with `@backstage/frontend-plugin-api` APIs. + +### Support for Bitbucket Cloud OAuth + +Support for Bitbucket Cloud OAuth has been added - which was much welcome. This introduces an alternative authentication method using a workspace OAuth consumer, alongside App Passwords (deprecated) and API tokens. OAuth does not require a bot or service account and avoids token expiry issues. + +As part of this change, some breaking changes were made to low level auth getter functions, such that they now return a promise instead of a plain value. + +Contributed by [@jksmth](https://github.com/jksmth) in [#31848](https://github.com/backstage/backstage/pull/31848) + +### New Catalog actions + +There are two new MCP-usable actions on the block for registering and unregistering entities: `catalog:register-entity` and `catalog:unregister-entity`. + +Contributed by [@gabemontero](https://github.com/gabemontero) in [#32042](https://github.com/backstage/backstage/pull/32042) + +### New `RepoOwnerPicker` for Scaffolder + +A new field extension for selecting an organization or owner for a particular repository has been shipped! Currently, this only supports GitHub autocomplete, but contributions welcome in making this available for other providers! + +Contributed by [@benjidotsh](https://github.com/benjidotsh) in [#32105](https://github.com/backstage/backstage/pull/32105) + +## Security Fixes + +This release does not contain any security fixes. + +## Upgrade path + +We recommend that you keep your Backstage project up to date with this latest release. For more guidance on how to upgrade, check out the documentation for [keeping Backstage updated](https://backstage.io/docs/getting-started/keeping-backstage-updated). + +## Links and References + +Below you can find a list of links and references to help you learn about and start using this new release. + +- [Backstage official website](https://backstage.io/), [documentation](https://backstage.io/docs/), and [getting started guide](https://backstage.io/docs/getting-started/) +- [GitHub repository](https://github.com/backstage/backstage) +- Backstage's [versioning and support policy](https://backstage.io/docs/overview/versioning-policy) +- [Community Discord](https://discord.gg/backstage-687207715902193673) for discussions and support +- [Changelog](https://github.com/backstage/backstage/tree/master/docs/releases/v1.46.0-changelog.md) +- Backstage [Demos](https://backstage.io/demos), [Blog](https://backstage.io/blog), [Roadmap](https://backstage.io/docs/overview/roadmap) and [Plugins](https://backstage.io/plugins) + +Sign up for our [newsletter](https://info.backstage.spotify.com/newsletter_subscribe) if you want to be informed about what is happening in the world of Backstage. diff --git a/docs/releases/v1.47.0-next.0-changelog.md b/docs/releases/v1.47.0-next.0-changelog.md new file mode 100644 index 0000000000..e1fd3f9ebb --- /dev/null +++ b/docs/releases/v1.47.0-next.0-changelog.md @@ -0,0 +1,578 @@ +# Release v1.47.0-next.0 + +Upgrade Helper: [https://backstage.github.io/upgrade-helper/?to=1.47.0-next.0](https://backstage.github.io/upgrade-helper/?to=1.47.0-next.0) + +## @backstage/ui@0.11.0-next.0 + +### Minor Changes + +- 4ea1d15: **BREAKING**: Renamed CSS variable `--bui-bg` to `--bui-bg-surface-0` for consistency. + +### Patch Changes + +- 1880402: Fixes app background color on dark mode. +- 9c76682: build(deps-dev): bump `storybook` from 10.1.9 to 10.1.10 +- b4a4911: Fixed SearchField `startCollapsed` prop not working correctly in Backstage UI. The field now properly starts in a collapsed state, expands when clicked and focused, and collapses back when unfocused with no input. Also fixed CSS logic to work correctly in all layout contexts (flex row, flex column, and regular containers). + + Affected components: SearchField + +## @backstage/backend-defaults@0.14.1-next.0 + +### Patch Changes + +- 7126bf2: Fixed a spelling mistake in root health service shutdown response. +- Updated dependencies + - @backstage/backend-app-api@1.4.0 + - @backstage/backend-dev-utils@0.1.6 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/cli-node@0.2.16 + - @backstage/config@1.3.6 + - @backstage/config-loader@1.10.7 + - @backstage/errors@1.2.7 + - @backstage/integration@1.19.0 + - @backstage/integration-aws-node@0.1.19 + - @backstage/types@1.2.2 + - @backstage/plugin-auth-node@0.6.10 + - @backstage/plugin-events-node@0.4.18 + - @backstage/plugin-permission-node@0.10.7 + +## @backstage/backend-dynamic-feature-service@0.7.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-openapi-utils@0.6.5-next.0 + - @backstage/backend-defaults@0.14.1-next.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/cli-common@0.1.16 + - @backstage/cli-node@0.2.16 + - @backstage/config@1.3.6 + - @backstage/config-loader@1.10.7 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-app-node@0.1.40 + - @backstage/plugin-auth-node@0.6.10 + - @backstage/plugin-catalog-backend@3.3.1-next.0 + - @backstage/plugin-events-backend@0.5.10-next.0 + - @backstage/plugin-events-node@0.4.18 + - @backstage/plugin-permission-common@0.9.3 + - @backstage/plugin-permission-node@0.10.7 + - @backstage/plugin-scaffolder-node@0.12.2 + - @backstage/plugin-search-backend-node@1.4.0 + - @backstage/plugin-search-common@1.2.21 + +## @backstage/backend-openapi-utils@0.6.5-next.0 + +### Patch Changes + +- 6678b78: Internal update to use native feature from our request validation library for handling base path determination. +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + +## @backstage/backend-test-utils@1.10.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.14.1-next.0 + - @backstage/backend-app-api@1.4.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-auth-node@0.6.10 + - @backstage/plugin-events-node@0.4.18 + - @backstage/plugin-permission-common@0.9.3 + +## @backstage/cli@0.35.2-next.0 + +### Patch Changes + +- 320c6a9: Bump `@swc/core` to support `ES2023` and `ES2024` +- 9ee5996: Bump minimum required `@swc/core` to avoid transpilation bug +- Updated dependencies + - @backstage/catalog-model@1.7.6 + - @backstage/cli-common@0.1.16 + - @backstage/cli-node@0.2.16 + - @backstage/config@1.3.6 + - @backstage/config-loader@1.10.7 + - @backstage/errors@1.2.7 + - @backstage/eslint-plugin@0.2.0 + - @backstage/integration@1.19.0 + - @backstage/release-manifests@0.0.13 + - @backstage/types@1.2.2 + +## @backstage/create-app@0.7.8-next.0 + +### Patch Changes + +- Bumped create-app version. +- Updated dependencies + - @backstage/cli-common@0.1.16 + +## @backstage/dev-utils@1.1.19-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/ui@0.11.0-next.0 + - @backstage/app-defaults@1.7.3 + - @backstage/catalog-model@1.7.6 + - @backstage/core-app-api@1.19.3 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/integration-react@1.2.13 + - @backstage/theme@0.7.1 + - @backstage/plugin-catalog-react@1.21.4 + +## @techdocs/cli@1.10.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.14.1-next.0 + - @backstage/catalog-model@1.7.6 + - @backstage/cli-common@0.1.16 + - @backstage/config@1.3.6 + - @backstage/plugin-techdocs-node@1.13.10 + +## @backstage/plugin-app-visualizer@0.1.27-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/ui@0.11.0-next.0 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/frontend-plugin-api@0.13.2 + +## @backstage/plugin-auth-backend-module-oidc-provider@0.4.11-next.0 + +### Patch Changes + +- e54fcb2: Added support for custom start URL search parameters (with the new `startUrlSearchParams` config property) +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/config@1.3.6 + - @backstage/types@1.2.2 + - @backstage/plugin-auth-backend@0.25.7 + - @backstage/plugin-auth-node@0.6.10 + +## @backstage/plugin-catalog-backend@3.3.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-openapi-utils@0.6.5-next.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/integration@1.19.0 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1 + - @backstage/plugin-events-node@0.4.18 + - @backstage/plugin-permission-common@0.9.3 + - @backstage/plugin-permission-node@0.10.7 + +## @backstage/plugin-catalog-backend-module-aws@0.4.19-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.14.1-next.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/integration@1.19.0 + - @backstage/integration-aws-node@0.1.19 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1 + - @backstage/plugin-kubernetes-common@0.9.9 + +## @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-openapi-utils@0.6.5-next.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-node@1.20.1 + +## @backstage/plugin-catalog-backend-module-gitlab@0.7.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.14.1-next.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/integration@1.19.0 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1 + - @backstage/plugin-events-node@0.4.18 + +## @backstage/plugin-catalog-backend-module-gitlab-org@0.2.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-backend-module-gitlab@0.7.7-next.0 + - @backstage/plugin-catalog-node@1.20.1 + - @backstage/plugin-events-node@0.4.18 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.7.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.14.1-next.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-backend@3.3.1-next.0 + - @backstage/plugin-catalog-node@1.20.1 + - @backstage/plugin-events-node@0.4.18 + - @backstage/plugin-permission-common@0.9.3 + +## @backstage/plugin-catalog-backend-module-logs@0.1.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-backend@3.3.1-next.0 + - @backstage/plugin-events-node@0.4.18 + +## @backstage/plugin-devtools-backend@0.5.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.14.1-next.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/cli-common@0.1.16 + - @backstage/config@1.3.6 + - @backstage/config-loader@1.10.7 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-devtools-common@0.1.20 + - @backstage/plugin-permission-common@0.9.3 + - @backstage/plugin-permission-node@0.10.7 + +## @backstage/plugin-events-backend@0.5.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-openapi-utils@0.6.5-next.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-events-node@0.4.18 + +## @backstage/plugin-mcp-actions-backend@0.1.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.14.1-next.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/catalog-client@1.12.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-node@1.20.1 + +## @backstage/plugin-mui-to-bui@0.2.3-next.0 + +### Patch Changes + +- e4a1180: Updated tokens from `--bui-bg` to `--bui-bg-surface-0` +- Updated dependencies + - @backstage/ui@0.11.0-next.0 + - @backstage/core-plugin-api@1.12.1 + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/theme@0.7.1 + +## @backstage/plugin-scaffolder-backend@3.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-openapi-utils@0.6.5-next.0 + - @backstage/backend-defaults@0.14.1-next.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/integration@1.19.0 + - @backstage/types@1.2.2 + - @backstage/plugin-auth-node@0.6.10 + - @backstage/plugin-bitbucket-cloud-common@0.3.5 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.15 + - @backstage/plugin-catalog-node@1.20.1 + - @backstage/plugin-events-node@0.4.18 + - @backstage/plugin-permission-common@0.9.3 + - @backstage/plugin-permission-node@0.10.7 + - @backstage/plugin-scaffolder-backend-module-azure@0.2.16 + - @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.17 + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.3.0 + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.16 + - @backstage/plugin-scaffolder-backend-module-gerrit@0.2.16 + - @backstage/plugin-scaffolder-backend-module-gitea@0.2.16 + - @backstage/plugin-scaffolder-backend-module-github@0.9.3 + - @backstage/plugin-scaffolder-backend-module-gitlab@0.11.0 + - @backstage/plugin-scaffolder-common@1.7.4 + - @backstage/plugin-scaffolder-node@0.12.2 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.3.19-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.14.1-next.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/integration@1.19.0 + - @backstage/types@1.2.2 + - @backstage/plugin-scaffolder-node@0.12.2 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.4.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/types@1.2.2 + - @backstage/plugin-scaffolder-node@0.12.2 + - @backstage/plugin-scaffolder-node-test-utils@0.3.7-next.0 + +## @backstage/plugin-scaffolder-node-test-utils@0.3.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/backend-test-utils@1.10.3-next.0 + - @backstage/types@1.2.2 + - @backstage/plugin-scaffolder-node@0.12.2 + +## @backstage/plugin-search-backend@2.0.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-openapi-utils@0.6.5-next.0 + - @backstage/backend-defaults@0.14.1-next.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-permission-common@0.9.3 + - @backstage/plugin-permission-node@0.10.7 + - @backstage/plugin-search-backend-node@1.4.0 + - @backstage/plugin-search-common@1.2.21 + +## @backstage/plugin-techdocs-backend@2.1.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.14.1-next.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/integration@1.19.0 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-node@1.20.1 + - @backstage/plugin-techdocs-node@1.13.10 + +## @backstage/plugin-user-settings-backend@0.3.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.14.1-next.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-auth-node@0.6.10 + - @backstage/plugin-signals-node@0.1.27 + - @backstage/plugin-user-settings-common@0.0.1 + +## example-app@0.2.117-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/ui@0.11.0-next.0 + - @backstage/cli@0.35.2-next.0 + - @backstage/plugin-mui-to-bui@0.2.3-next.0 + - @backstage/app-defaults@1.7.3 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/core-app-api@1.19.3 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/frontend-app-api@0.13.3 + - @backstage/integration-react@1.2.13 + - @backstage/theme@0.7.1 + - @backstage/plugin-api-docs@0.13.2 + - @backstage/plugin-auth-react@0.1.22 + - @backstage/plugin-catalog@1.32.1 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-graph@0.5.4 + - @backstage/plugin-catalog-import@0.13.8 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/plugin-catalog-unprocessed-entities@0.2.24 + - @backstage/plugin-devtools@0.1.34 + - @backstage/plugin-home@0.8.15 + - @backstage/plugin-kubernetes@0.12.14 + - @backstage/plugin-kubernetes-cluster@0.0.32 + - @backstage/plugin-notifications@0.5.12 + - @backstage/plugin-org@0.6.47 + - @backstage/plugin-permission-react@0.4.39 + - @backstage/plugin-scaffolder@1.35.0 + - @backstage/plugin-scaffolder-react@1.19.4 + - @backstage/plugin-search@1.5.1 + - @backstage/plugin-search-common@1.2.21 + - @backstage/plugin-search-react@1.10.1 + - @backstage/plugin-signals@0.0.26 + - @backstage/plugin-techdocs@1.16.1 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.31 + - @backstage/plugin-techdocs-react@1.3.6 + - @backstage/plugin-user-settings@0.8.30 + +## example-app-next@0.0.31-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/ui@0.11.0-next.0 + - @backstage/cli@0.35.2-next.0 + - @backstage/plugin-app-visualizer@0.1.27-next.0 + - @backstage/app-defaults@1.7.3 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/core-app-api@1.19.3 + - @backstage/core-compat-api@0.5.5 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/frontend-app-api@0.13.3 + - @backstage/frontend-defaults@0.3.4 + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/integration-react@1.2.13 + - @backstage/theme@0.7.1 + - @backstage/plugin-api-docs@0.13.2 + - @backstage/plugin-app@0.3.3 + - @backstage/plugin-auth@0.1.3 + - @backstage/plugin-auth-react@0.1.22 + - @backstage/plugin-catalog@1.32.1 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-graph@0.5.4 + - @backstage/plugin-catalog-import@0.13.8 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/plugin-catalog-unprocessed-entities@0.2.24 + - @backstage/plugin-home@0.8.15 + - @backstage/plugin-kubernetes@0.12.14 + - @backstage/plugin-kubernetes-cluster@0.0.32 + - @backstage/plugin-notifications@0.5.12 + - @backstage/plugin-org@0.6.47 + - @backstage/plugin-permission-react@0.4.39 + - @backstage/plugin-scaffolder@1.35.0 + - @backstage/plugin-scaffolder-react@1.19.4 + - @backstage/plugin-search@1.5.1 + - @backstage/plugin-search-common@1.2.21 + - @backstage/plugin-search-react@1.10.1 + - @backstage/plugin-signals@0.0.26 + - @backstage/plugin-techdocs@1.16.1 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.31 + - @backstage/plugin-techdocs-react@1.3.6 + - @backstage/plugin-user-settings@0.8.30 + +## example-backend@0.0.46-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.14.1-next.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/catalog-model@1.7.6 + - @backstage/plugin-app-backend@0.5.9 + - @backstage/plugin-auth-backend@0.25.7 + - @backstage/plugin-auth-backend-module-github-provider@0.4.0 + - @backstage/plugin-auth-backend-module-guest-provider@0.2.15 + - @backstage/plugin-auth-backend-module-openshift-provider@0.1.3 + - @backstage/plugin-auth-node@0.6.10 + - @backstage/plugin-catalog-backend@3.3.1-next.0 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.10-next.0 + - @backstage/plugin-catalog-backend-module-openapi@0.2.17 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.15 + - @backstage/plugin-catalog-backend-module-unprocessed@0.6.7 + - @backstage/plugin-devtools-backend@0.5.13-next.0 + - @backstage/plugin-events-backend@0.5.10-next.0 + - @backstage/plugin-events-backend-module-google-pubsub@0.1.7 + - @backstage/plugin-kubernetes-backend@0.21.0 + - @backstage/plugin-mcp-actions-backend@0.1.7-next.0 + - @backstage/plugin-notifications-backend@0.6.1 + - @backstage/plugin-permission-backend@0.7.7 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.2.15 + - @backstage/plugin-permission-common@0.9.3 + - @backstage/plugin-permission-node@0.10.7 + - @backstage/plugin-proxy-backend@0.6.9 + - @backstage/plugin-scaffolder-backend@3.1.1-next.0 + - @backstage/plugin-scaffolder-backend-module-github@0.9.3 + - @backstage/plugin-scaffolder-backend-module-notifications@0.1.17 + - @backstage/plugin-search-backend@2.0.10-next.0 + - @backstage/plugin-search-backend-module-catalog@0.3.11 + - @backstage/plugin-search-backend-module-elasticsearch@1.7.9 + - @backstage/plugin-search-backend-module-explore@0.3.10 + - @backstage/plugin-search-backend-module-techdocs@0.4.9 + - @backstage/plugin-search-backend-node@1.4.0 + - @backstage/plugin-signals-backend@0.3.11 + - @backstage/plugin-techdocs-backend@2.1.4-next.0 + +## e2e-test@0.2.36-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.7.8-next.0 + - @backstage/cli-common@0.1.16 + - @backstage/errors@1.2.7 + +## techdocs-cli-embedded-app@0.2.116-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/ui@0.11.0-next.0 + - @backstage/cli@0.35.2-next.0 + - @backstage/app-defaults@1.7.3 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/core-app-api@1.19.3 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/integration-react@1.2.13 + - @backstage/test-utils@1.7.14 + - @backstage/theme@0.7.1 + - @backstage/plugin-catalog@1.32.1 + - @backstage/plugin-techdocs@1.16.1 + - @backstage/plugin-techdocs-react@1.3.6 diff --git a/docs/tooling/cli/02-build-system.md b/docs/tooling/cli/02-build-system.md index c8d9034955..6f1b7fd54a 100644 --- a/docs/tooling/cli/02-build-system.md +++ b/docs/tooling/cli/02-build-system.md @@ -610,7 +610,7 @@ With that in mind, here are some IDEs configurations to run backstage components 1. Click on "Edit Configurations" on top panel 2. In the modal dialog click on link "Edit configuration templates..." located in the bottom left corner. 3. "Configuration file": leave empty (`backstage-cli` adds the config) - 4. "Node options": `--no-node-snapshot --experimental-vm-modules` + 4. "Node options": ` --experimental-vm-modules` 5. "Jest package": `~/workspace/backstage/node_modules/@backstage/cli` - the location of the backstage cli package. 6. "Working directory": `~/workspace/backstage` 7. "Jest Options": `repo test --runInBand --watch=false` @@ -621,20 +621,21 @@ With that in mind, here are some IDEs configurations to run backstage components #### VS Code +1. Install the [Jest extension](https://marketplace.visualstudio.com/items?itemName=Orta.vscode-jest) for VS Code. +2. Update `settings.json` in the `.vscode` folder with: + ```jsonc { "jest.jestCommandLine": "yarn test", // In a large repo like the Backstage main repo you likely want to disable // watch mode and the initial test run too, leaving just manual and perhaps // on-save test runs in place. - "jest.autoRun": { - "watch": false, - "onSave": "test-src-file" - } + "jest.runMode": "on-save" } ``` -A complete launch configuration for VS Code debugging may look like this: +3. Add a launch configuration for VS Code in `launch.json` in the `.vscode` folder. + A complete configuration for debugging may look like this: ```jsonc { @@ -653,11 +654,13 @@ A complete launch configuration for VS Code debugging may look like this: ], "console": "integratedTerminal", "internalConsoleOptions": "neverOpen", - "disableOptimisticBPs": true, - "program": "${workspaceFolder}/node_modules/.bin/backstage-cli" + "program": "${workspaceFolder}/node_modules/@backstage/cli/bin/backstage-cli" } ``` +4. The configuration is not for manual runs from the "Run and Debug" view. + Instead use the Jest test explorer or the [test's gutter menu](https://github.com/jest-community/vscode-jest#how-to-trigger-a-test-run). + ## Publishing Package publishing is an optional part of the Backstage build system and not diff --git a/docs/tutorials/jest30-migration.md b/docs/tutorials/jest30-migration.md new file mode 100644 index 0000000000..ea79b03009 --- /dev/null +++ b/docs/tutorials/jest30-migration.md @@ -0,0 +1,95 @@ +--- +id: jest30-migration +title: Migrating to Jest 30 +description: A guide to migrating your project to Jest 30 and JSDOM 27 +--- + +Starting with a recent version of `@backstage/cli`, `jest` is a peer dependency. If you run tests using Backstage CLI, you must add Jest and its environment dependencies as `devDependencies` in your project. + +You can choose to install either Jest 29 or Jest 30. The built-in Jest version before this change was Jest 29, however, we recommend that you switch to Jest 30. Upgrading will solve the `Could not parse CSS stylesheet` errors, allow you to use MSW v2 in web packages, and ensure that you remain compatible with future versions of the Backstage CLI. Support for Jest 29 is temporary, with the purpose of allowing you to upgrade at your own pace, but it will eventually be removed. + +- **Jest 29**: + + ```bash + # in your repository root, run: + yarn add --dev jest@^29 @types/jest@^29 jest-environment-jsdom@^29 + ``` + + Pros: No migration needed + + Cons: You may see `Could not parse CSS stylesheet` warnings/errors when testing components from `@backstage/ui` or other packages using CSS `@layer` declarations + +- **Jest 30**: + + ```bash + # in your repository root, run: + yarn add --dev jest@^30 @types/jest@^30 @jest/environment-jsdom-abstract@^30 jsdom@^27 + ``` + + Pros: Fixes the stylesheet parsing warnings/errors + + Cons: Requires migration steps (see below) in your tests + +## Migration Guide + +The examples below are issues we encountered while migrating the Backstage repository. For a complete list of breaking changes, see the official documentation: + +- [Jest 30 upgrade guide](https://jestjs.io/docs/upgrading-to-jest30) +- [JSDOM changelog](https://github.com/jsdom/jsdom/releases) + +### Jest 30 + +**Asymmetric matchers with arrays**: `expect.objectContaining()` no longer works with arrays. + +```diff +- expect(result).toEqual(expect.objectContaining([{ id: '123' }])); ++ expect(result).toEqual([{ id: '123' }]); +// or ++ expect(result).toEqual(expect.arrayContaining([{ id: '123' }])); +``` + +**Array length assertions**: `expect.objectContaining({ length: N })` no longer works. + +```diff +- expect(fn).toHaveBeenCalledWith(expect.objectContaining({ length: 2 })); ++ expect(fn).toHaveBeenCalledWith(expect.any(Array)); ++ expect(fn.mock.calls[0][0]).toHaveLength(2); +``` + +**Deprecated matcher aliases removed**: Replace with canonical names. + +```diff +- expect(fn).toBeCalled(); ++ expect(fn).toHaveBeenCalled(); +``` + +**Snapshots**: Regenerate snapshots as the header format has changed. + +```bash +yarn test --no-watch -u +``` + +### JSDOM 27 + +**window.location is non-configurable**: You can no longer mock location via `Object.defineProperty`. + +```diff +- Object.defineProperty(window, 'location', { value: { href: '' } }); ++ // Option 1: Use history API ++ history.replaceState({}, '', '/new-path'); ++ // Option 2: Spy on navigation methods ++ const spy = jest.spyOn(component, 'navigate'); +``` + +**CSS color values**: Colors may be returned as RGB instead of named colors. + +```diff +- expect(element.style.color).toBe('red'); ++ expect(element.style.color).toBe('rgb(255, 0, 0)'); +``` + +**Error format changes**: Error messages and stack traces may have different formatting. + +#### If you run into `Cannot read properties of null (reading 'constructor')` + +Certain Backstage UI-components (e.g. Button) have a combination of CSS that triggers this error in tests. The solution is to make sure you have at least v0.9.25 of `@acemir/cssom`. diff --git a/docs/tutorials/using-backstage-proxy-within-plugin.md b/docs/tutorials/using-backstage-proxy-within-plugin.md index 237a7207a1..bb416bf731 100644 --- a/docs/tutorials/using-backstage-proxy-within-plugin.md +++ b/docs/tutorials/using-backstage-proxy-within-plugin.md @@ -94,15 +94,15 @@ export const AwesomeUsersTable = () => { This section describes the steps to wrap your API client in a [Utility API](../api/utility-apis.md), which are: -- use [`createApiRef`](../reference/frontend-plugin-api.createapiref.md) to create a - new [`ApiRef`](../reference/frontend-plugin-api.apiref.md) -- register an [`ApiFactory`](../reference/frontend-plugin-api.apifactory.md) with +- use [`createApiRef`](https://backstage.io/api/stable/functions/_backstage_frontend-plugin-api.createApiRef.html) to create a + new [`ApiRef`](https://backstage.io/api/stable/types/_backstage_frontend-plugin-api.ApiRef.html) +- register an [`ApiFactory`](https://backstage.io/api/stable/types/_backstage_frontend-plugin-api.ApiFactory.html) with your plugin using - [`createApiFactory`](../reference/frontend-plugin-api.createapifactory.md). This + [`createApiFactory`](https://backstage.io/api/stable/functions/_backstage_frontend-plugin-api.createApiFactory.html). This will wrap your API implementation, associate your `ApiRef` with your implementation and tell backstage how to instantiate it - finally, you can use your API in your components by calling - [`useApi`](../reference/frontend-plugin-api.useapi.md) + [`useApi`](https://backstage.io/api/stable/functions/_backstage_frontend-plugin-api.useApi.html) ### Defining the API client interface @@ -187,8 +187,8 @@ export class MyAwesomeApiClient implements MyAwesomeApi { ``` > Check out the docs for more information on the -> [DiscoveryApi](../reference/frontend-plugin-api.discoveryapi.md) or the -> [FetchApi](../reference/frontend-plugin-api.fetchapi.md) +> [DiscoveryApi](https://backstage.io/api/stable/types/_backstage_frontend-plugin-api.DiscoveryApi.html) or the +> [FetchApi](https://backstage.io/api/stable/types/_backstage_frontend-plugin-api.FetchApi.html) ### Bundling your ApiRef with your plugin @@ -233,7 +233,7 @@ export const myCustomPlugin = createPlugin({ ### Using the API in your components Now you should be able to access your API using the backstage hook -[`useApi`](../reference/frontend-plugin-api.useapi.md) from within your plugin code. +[`useApi`](https://backstage.io/api/stable/functions/_backstage_frontend-plugin-api.useApi.html) from within your plugin code. ```ts title="plugins/my-awesome-plugin/src/components/AwesomeUsersTable.tsx" import { useApi } from '@backstage/core-plugin-api'; diff --git a/microsite/blog/2025-12-30-backstage-wrapped-2025.mdx b/microsite/blog/2025-12-30-backstage-wrapped-2025.mdx new file mode 100644 index 0000000000..0f8bdd21cf --- /dev/null +++ b/microsite/blog/2025-12-30-backstage-wrapped-2025.mdx @@ -0,0 +1,115 @@ +--- +title: 'Backstage Wrapped 2025: Celebrating a mature framework with modern foundations' +author: Vincenzo Scamporlino, Spotify +authorURL: https://github.com/vinzscam +authorImageURL: https://avatars.githubusercontent.com/u/8433119?v=8 +--- + +![Let's blast into the New Year with a quick look back at all the big hits — backend, frontend, AI, UI, and more! See how today's Backstage is ready to build the future of developer experience.](assets/2025-12-30/wrapped2025.png) + +This year was another big one for Backstage and our worldwide community of adopters, contributors, and partners. Backstage turned five, the New Frontend System became adoption-ready, and your favorite platform for developer experience gained AI superpowers with the introduction of the Actions Registry and MCP server support. Let's blast into the New Year with a quick look back, along with a peek around the corner at what's coming next. + +{/* truncate */} + +--- + +## Busy beavers here, there, and everywhere + +As in years past, we've visualized how our vibrant global community lights up the Backstage open source repo with enthusiasm, creativity, and commits. This year, we're visualizing contributions to the Community Plugins repo, too. Can you spot your name in the videos below? + + + +_All 7.7k commits to `backstage/backstage` in 2025_ + + + +_All 3.3k commits to `backstage/community-plugins` in 2025_ + +Couldn't spot your name in the videos? Here's one more chance — every contributor who helped shape Backstage in 2025, all in one picture. + +![Backstage 2025 contributors](assets/2025-12-30/contributors-wrapped-2025.png) + +## Mature for a five-year-old + +![Backstage community stats: 3.4k+ adopters, 1,8k contributors, 15k Discord members, 7k project forks, 68k total contributions, 250+ open source plugins, 31k stars](assets/2025-12-30/wrapped2025-stats.png) +_The growing Backstage ecosystem, by the numbers_ + +Earlier this year, the Backstage project [celebrated its 5th birthday][bday] on the main stage at [KubeCon + CloudNativeCon in London][kcon-eu]. + +While the framework still isn't old enough to shave, it's matured into the industry standard for internal developer portals (IDPs). According to [this DX survey][dx] released in March: + +> Backstage is dominating the IDP market, holding an impressive 89% market share compared to SaaS competitors and achieving a remarkable 67% overall market penetration. These percentages are even higher for enterprise companies. + +As you can see above in the [latest project stats][video], the Backstage ecosystem continues to expand, growing in adopters and contributors, as well as plugins and third-party service providers. + +Want to dive into more Backstage stats? Check out the project's health scores and more on the relaunched [LFX Insights][lfx] site. + +[bday]: https://www.youtube.com/watch?v=JqG1wey7-Ao&t=563s&list=PL8iP9yIjU0Q3K8LV_a9CcFmhvvNTAUzL1 +[kcon-eu]: https://backstage.io/blog/2025/04/29/backstagecon-kubecon-25-london#big-birthday-energy-on-the-big-stage +[dx]: https://newsletter.getdx.com/p/backstage-and-the-developer-portal-market +[video]: https://www.youtube.com/watch?v=Wih0a1v1Et0&list=PL8iP9yIjU0Q33vpSaBlAvIhgDb-9smXUU +[lfx]: https://insights.linuxfoundation.org/project/backstage + +## Building the future on modern foundations + +Just because Backstage has cemented its place as the standard for IDPs doesn't mean it's sitting still. From backend to frontend, from AI to UI, the technical foundations of the platform have been modernized, updated, and revamped — this is why today's Backstage is ready to build the future of developer experience. + +Top 2025 highlights: + +- Goodbye to the old backend system +- New Frontend System is adoption-ready +- Hello to the Actions Registry + MCP server support +- Introducing a new design system with Backstage UI + +With the [New Backend System][backend] released as a stable 1.0 last year and the [New Frontend System][frontend] becoming [adoption-ready][1-42] this year, Backstage is easier than ever to use, maintain, and build on — making it both more accessible and more capable for adopters, old and new. + +This year also saw the debut of the [Actions Registry][actions] and MCP server support — so now Backstage can empower both your human developers and their AI helpers. + +And [Backstage UI][ui] is coming! The alpha release of the upcoming design system made huge strides in 2025, preparing the way for a new level of usability throughout the Backstage experience. + +Catch up on a whole year's worth of improvements — and see where Backstage is heading next — in the recordings below. + +[backend]: https://backstage.io/docs/backend-system/ +[frontend]: https://backstage.io/docs/frontend-system/ +[1-42]: https://backstage.io/docs/releases/v1.42.0 +[actions]: https://backstage.io/docs/backend-system/core-services/actions-registry +[ui]: https://ui.backstage.io/ + + + +_Watch the Backstage maintainers' talk at [KubeCon in London][lon], where they demoed the New Frontend System and introduced the Actions Registry._ + + +_Watch the maintainers' talk at [KubeCon in Atlanta][atl], where they shared +work towards an AI-Native Backstage, progress on Backstage UI, and more._ + +[lon]: https://backstage.io/blog/2025/04/29/backstagecon-kubecon-25-london +[atl]: https://backstage.io/blog/2025/11/25/backstagecon-kubecon-25-atlanta + +## See you in 2026! + +Happy New Year, Backstage Community! See you in the repos! diff --git a/microsite/blog/assets/2025-12-30/contributors-wrapped-2025.png b/microsite/blog/assets/2025-12-30/contributors-wrapped-2025.png new file mode 100644 index 0000000000..7aa16f106e Binary files /dev/null and b/microsite/blog/assets/2025-12-30/contributors-wrapped-2025.png differ diff --git a/microsite/blog/assets/2025-12-30/wrapped2025-stats.png b/microsite/blog/assets/2025-12-30/wrapped2025-stats.png new file mode 100644 index 0000000000..59d31f142c Binary files /dev/null and b/microsite/blog/assets/2025-12-30/wrapped2025-stats.png differ diff --git a/microsite/blog/assets/2025-12-30/wrapped2025.png b/microsite/blog/assets/2025-12-30/wrapped2025.png new file mode 100644 index 0000000000..b99768dfda Binary files /dev/null and b/microsite/blog/assets/2025-12-30/wrapped2025.png differ diff --git a/microsite/data/plugins/sds_workspace.yaml b/microsite/data/plugins/sds_workspace.yaml new file mode 100644 index 0000000000..43d9a0f20e --- /dev/null +++ b/microsite/data/plugins/sds_workspace.yaml @@ -0,0 +1,10 @@ +--- +title: Citrix Secure Developer Spaces (SDS) +author: Citrix +authorUrl: https://github.com/strong-network +category: Development +description: Connect Backstage with Citrix Secure Developer Spaces (SDS) to view and create developer workspaces. +documentation: https://www.npmjs.com/package/@citrixcloud/backstage-sds-workspaces +iconUrl: /img/citrix_sds.png +npmPackageName: '@citrixcloud/backstage-sds-workspaces' +addedDate: '2025-10-07' diff --git a/microsite/package.json b/microsite/package.json index a3430545f4..edf07abb02 100644 --- a/microsite/package.json +++ b/microsite/package.json @@ -28,7 +28,7 @@ "@docusaurus/preset-classic": "^3.1.1", "@docusaurus/types": "^3.1.1", "@mdx-js/react": "^3.0.0", - "@swc/core": "^1.3.46", + "@swc/core": "^1.15.6", "clsx": "^2.0.0", "docusaurus-plugin-openapi-docs": "^4.3.0", "docusaurus-plugin-sass": "^0.2.3", diff --git a/microsite/sidebars.ts b/microsite/sidebars.ts index 9a4f03620f..afe5616bbf 100644 --- a/microsite/sidebars.ts +++ b/microsite/sidebars.ts @@ -18,664 +18,743 @@ const scaffolderSidebar = tryToLoadCustomSidebar( '../docs/features/software-templates/api/sidebar.ts', ); +function sidebarElementWithIndex( + element: { + description?: string; + differentiator?: string; + label: string; + docId?: string; + }, + children: Array, +) { + const { label, description, differentiator } = element; + return { + type: 'category', + label: label, + description, + link: { + type: 'generated-index', + title: label, + slug: `/${differentiator}${label + .toLowerCase() + .replace(/[^a-z0-9 _-]/gi, '-')}/generated-index`, + }, + items: children, + }; +} + export default { - docs: { - Overview: [ + docs: [ + sidebarElementWithIndex({ label: 'Overview' }, [ 'overview/what-is-backstage', 'overview/technical-overview', 'overview/architecture-overview', 'overview/roadmap', 'overview/threat-model', 'overview/versioning-policy', - ], - 'Getting Started': [ + ]), + sidebarElementWithIndex({ label: 'Getting Started' }, [ 'getting-started/index', - { - type: 'category', - label: 'Configuring Backstage', - items: [ - 'getting-started/config/database', - 'getting-started/config/authentication', - 'getting-started/configure-app-with-plugins', - 'getting-started/homepage', - ], - }, - { - type: 'category', - label: 'Deploying Backstage', - items: [ - 'deployment/index', - 'deployment/scaling', - 'deployment/docker', - 'deployment/k8s', - ], - }, - { - type: 'category', - label: 'Using Backstage', - items: [ - 'getting-started/logging-in', - 'getting-started/register-a-component', - 'getting-started/create-a-component', - ], - }, + sidebarElementWithIndex({ label: 'Configuring Backstage' }, [ + 'getting-started/config/database', + 'getting-started/config/authentication', + 'getting-started/configure-app-with-plugins', + 'getting-started/homepage', + ]), + sidebarElementWithIndex({ label: 'Deploying Backstage' }, [ + 'deployment/index', + 'deployment/scaling', + 'deployment/docker', + 'deployment/k8s', + ]), + sidebarElementWithIndex({ label: 'Using Backstage' }, [ + 'getting-started/logging-in', + 'getting-started/register-a-component', + 'getting-started/create-a-component', + ]), 'overview/support', 'getting-started/keeping-backstage-updated', - ], + ]), ...(process.env.GOLDEN_PATH - ? { - 'Golden Paths': [ + ? [ + sidebarElementWithIndex({ label: 'Golden Paths' }, [ + sidebarElementWithIndex({ label: '001 - Create an App' }, [ + 'golden-path/create-app/index', + 'golden-path/create-app/npx-create-app', + 'golden-path/create-app/local-development', + 'golden-path/create-app/installing-plugins', + 'golden-path/create-app/logging-in', + 'golden-path/create-app/custom-theme', + 'golden-path/create-app/keeping-backstage-updated', + ]), + sidebarElementWithIndex({ label: '002 - Plugins' }, [ + 'golden-path/plugins/index', + 'golden-path/plugins/why-build-plugins', + 'golden-path/plugins/sustainable-plugin-development', + sidebarElementWithIndex({ label: 'Backend Plugins' }, [ + 'golden-path/plugins/backend/001-first-steps', + 'golden-path/plugins/backend/002-poking-around', + ]), + ]), + ]), + ] + : []), + sidebarElementWithIndex( + { + label: 'Core Features', + description: 'Features powering the core of Backstage.', + }, + [ + sidebarElementWithIndex( + { + label: 'Auth and Identity', + description: 'Authentication and identity management features.', + }, + [ + 'auth/index', + sidebarElementWithIndex( + { + label: 'Included providers', + description: + 'Pre-configured authentication providers included with Backstage.', + }, + [ + 'auth/auth0/provider', + 'auth/atlassian/provider', + 'auth/aws-alb/provider', + 'auth/microsoft/provider', + 'auth/microsoft/easy-auth', + 'auth/bitbucket/provider', + 'auth/bitbucketServer/provider', + 'auth/cloudflare/provider', + 'auth/github/provider', + 'auth/gitlab/provider', + 'auth/google/provider', + 'auth/google/gcp-iap-auth', + 'auth/guest/provider', + 'auth/okta/provider', + 'auth/oauth2-proxy/provider', + 'auth/onelogin/provider', + 'auth/vmware-cloud/provider', + ], + ), + 'auth/identity-resolver', + 'auth/oauth', + 'auth/oidc', + 'auth/add-auth-provider', + 'auth/service-to-service-auth', + 'auth/autologout', + 'auth/troubleshooting', + ], + ), + sidebarElementWithIndex( + { + label: 'Kubernetes', + description: 'Use Kubernetes right from Backstage.', + }, + [ + 'features/kubernetes/overview', + 'features/kubernetes/installation', + 'features/kubernetes/configuration', + 'features/kubernetes/authentication', + 'features/kubernetes/authentication-strategies', + 'features/kubernetes/troubleshooting', + 'features/kubernetes/proxy', + ], + ), + sidebarElementWithIndex( + { + label: 'Notifications', + description: 'Know when important events happen in Backstage.', + }, + [ + 'notifications/index', + 'notifications/processors', + 'notifications/usage', + ], + ), + sidebarElementWithIndex( + { + label: 'Permissions', + description: 'Access control for your Backstage instance.', + }, + [ + 'permissions/overview', + 'permissions/concepts', + 'permissions/getting-started', + 'permissions/writing-a-policy', + 'permissions/frontend-integration', + 'permissions/custom-rules', + sidebarElementWithIndex( + { + label: 'Tutorial: using Permissions in your plugin', + description: + 'Step-by-step guide for plugin authors on using Permissions.', + }, + [ + 'permissions/plugin-authors/01-setup', + 'permissions/plugin-authors/02-adding-a-basic-permission-check', + 'permissions/plugin-authors/03-adding-a-resource-permission-check', + 'permissions/plugin-authors/04-authorizing-access-to-paginated-data', + 'permissions/plugin-authors/05-frontend-authorization', + ], + ), + ], + ), + sidebarElementWithIndex( + { label: 'Search', description: 'Using Search within Backstage.' }, + [ + 'features/search/search-overview', + 'features/search/getting-started', + 'features/search/concepts', { type: 'category', - label: '001 - create-app', - items: [ - 'golden-path/create-app/index', - 'golden-path/create-app/npx-create-app', - 'golden-path/create-app/local-development', - 'golden-path/create-app/installing-plugins', - 'golden-path/create-app/logging-in', - 'golden-path/create-app/custom-theme', - 'golden-path/create-app/keeping-backstage-updated', - ], + label: 'API', + link: + searchSidebar.length > 0 + ? { + type: 'generated-index', + title: 'Search API', + slug: '/category/search-api', + } + : { + type: 'doc', + id: 'openapi/generated-docs/404', + }, + items: searchSidebar, }, + 'features/search/architecture', + 'features/search/search-engines', + 'features/search/collators', + 'features/search/how-to-guides', + ], + ), + sidebarElementWithIndex( + { + label: 'Software Catalog', + description: 'Manage and explore your software components.', + }, + [ + 'features/software-catalog/software-catalog-overview', + 'features/software-catalog/life-of-an-entity', + 'features/software-catalog/configuration', + 'features/software-catalog/system-model', + 'features/software-catalog/descriptor-format', + 'features/software-catalog/references', + 'features/software-catalog/well-known-annotations', + 'features/software-catalog/well-known-relations', + 'features/software-catalog/well-known-statuses', + 'features/software-catalog/extending-the-model', + 'features/software-catalog/external-integrations', + 'features/software-catalog/catalog-customization', { type: 'category', - label: '002 - Plugins', - items: [ - 'golden-path/plugins/index', - 'golden-path/plugins/why-build-plugins', - 'golden-path/plugins/sustainable-plugin-development', - { - type: 'category', - label: 'Backend Plugins', - items: [ - 'golden-path/plugins/backend/001-first-steps', - 'golden-path/plugins/backend/002-poking-around', - ], - }, - ], + label: 'API', + link: + catalogSidebar.length > 0 + ? { + type: 'generated-index', + title: 'Catalog API', + slug: '/category/catalog-api', + } + : { + type: 'doc', + id: 'openapi/generated-docs/404', + }, + items: catalogSidebar, + }, + 'features/software-catalog/creating-the-catalog-graph', + 'features/software-catalog/faq', + ], + ), + sidebarElementWithIndex( + { + label: 'Software Templates', + description: 'Create and manage software templates.', + }, + [ + 'features/software-templates/software-templates-index', + 'features/software-templates/configuration', + 'features/software-templates/adding-templates', + 'features/software-templates/writing-templates', + 'features/software-templates/input-examples', + 'features/software-templates/builtin-actions', + 'features/software-templates/writing-custom-actions', + 'features/software-templates/writing-tests-for-actions', + 'features/software-templates/writing-custom-field-extensions', + 'features/software-templates/writing-custom-step-layouts', + 'features/software-templates/authorizing-scaffolder-template-details', + 'features/software-templates/migrating-to-rjsf-v5', + 'features/software-templates/migrating-from-v1beta2-to-v1beta3', + 'features/software-templates/dry-run-testing', + 'features/software-templates/experimental', + 'features/software-templates/templating-extensions', + { + type: 'category', + label: 'API', + link: + scaffolderSidebar.length > 0 + ? { + type: 'generated-index', + title: 'Scaffolder API', + slug: '/category/scaffolder-api', + } + : { + type: 'doc', + id: 'openapi/generated-docs/404', + }, + items: scaffolderSidebar, }, ], - } - : {}), - 'Core Features': [ - { - type: 'category', - label: 'Auth and Identity', - items: [ - 'auth/index', + ), + sidebarElementWithIndex( { - type: 'category', - label: 'Included providers', - items: [ - 'auth/auth0/provider', - 'auth/atlassian/provider', - 'auth/aws-alb/provider', - 'auth/microsoft/provider', - 'auth/microsoft/easy-auth', - 'auth/bitbucket/provider', - 'auth/bitbucketServer/provider', - 'auth/cloudflare/provider', - 'auth/github/provider', - 'auth/gitlab/provider', - 'auth/google/provider', - 'auth/google/gcp-iap-auth', - 'auth/guest/provider', - 'auth/okta/provider', - 'auth/oauth2-proxy/provider', - 'auth/onelogin/provider', - 'auth/vmware-cloud/provider', - ], + label: 'TechDocs', + description: 'Documentation as code for your software.', }, - 'auth/identity-resolver', - 'auth/oauth', - 'auth/oidc', - 'auth/add-auth-provider', - 'auth/service-to-service-auth', - 'auth/autologout', - 'auth/troubleshooting', - ], - }, + [ + 'features/techdocs/techdocs-overview', + 'features/techdocs/getting-started', + 'features/techdocs/concepts', + 'features/techdocs/addons', + 'features/techdocs/architecture', + 'features/techdocs/extensions', + 'features/techdocs/creating-and-publishing', + 'features/techdocs/configuration', + 'features/techdocs/using-cloud-storage', + 'features/techdocs/configuring-ci-cd', + 'features/techdocs/cli', + 'features/techdocs/how-to-guides', + 'features/techdocs/troubleshooting', + 'features/techdocs/faqs', + ], + ), + ], + ), + sidebarElementWithIndex( { - type: 'category', - label: 'Kubernetes', - items: [ - 'features/kubernetes/overview', - 'features/kubernetes/installation', - 'features/kubernetes/configuration', - 'features/kubernetes/authentication', - 'features/kubernetes/authentication-strategies', - 'features/kubernetes/troubleshooting', - 'features/kubernetes/proxy', - ], + label: 'Integrations', + description: 'Connect and integrate with external services.', }, - { - type: 'category', - label: 'Notifications', - items: [ - 'notifications/index', - 'notifications/processors', - 'notifications/usage', - ], - }, - { - type: 'category', - label: 'Permissions', - items: [ - 'permissions/overview', - 'permissions/concepts', - 'permissions/getting-started', - 'permissions/writing-a-policy', - 'permissions/frontend-integration', - 'permissions/custom-rules', - { - type: 'category', - label: 'Tutorial: using Permissions in your plugin', - items: [ - 'permissions/plugin-authors/01-setup', - 'permissions/plugin-authors/02-adding-a-basic-permission-check', - 'permissions/plugin-authors/03-adding-a-resource-permission-check', - 'permissions/plugin-authors/04-authorizing-access-to-paginated-data', - 'permissions/plugin-authors/05-frontend-authorization', - ], - }, - ], - }, - { - type: 'category', - label: 'Search', - items: [ - 'features/search/search-overview', - 'features/search/getting-started', - 'features/search/concepts', - { - type: 'category', - label: 'API', - link: - searchSidebar.length > 0 - ? { - type: 'generated-index', - title: 'Search API', - slug: '/category/search-api', - } - : { - type: 'doc', - id: 'openapi/generated-docs/404', - }, - items: searchSidebar, - }, - 'features/search/architecture', - 'features/search/search-engines', - 'features/search/collators', - 'features/search/how-to-guides', - ], - }, - { - type: 'category', - label: 'Software Catalog', - items: [ - 'features/software-catalog/software-catalog-overview', - 'features/software-catalog/life-of-an-entity', - 'features/software-catalog/configuration', - 'features/software-catalog/system-model', - 'features/software-catalog/descriptor-format', - 'features/software-catalog/references', - 'features/software-catalog/well-known-annotations', - 'features/software-catalog/well-known-relations', - 'features/software-catalog/well-known-statuses', - 'features/software-catalog/extending-the-model', - 'features/software-catalog/external-integrations', - 'features/software-catalog/catalog-customization', - { - type: 'category', - label: 'API', - link: - catalogSidebar.length > 0 - ? { - type: 'generated-index', - title: 'Catalog API', - slug: '/category/catalog-api', - } - : { - type: 'doc', - id: 'openapi/generated-docs/404', - }, - items: catalogSidebar, - }, - 'features/software-catalog/creating-the-catalog-graph', - 'features/software-catalog/faq', - ], - }, - { - type: 'category', - label: 'Software Templates', - items: [ - 'features/software-templates/software-templates-index', - 'features/software-templates/configuration', - 'features/software-templates/adding-templates', - 'features/software-templates/writing-templates', - 'features/software-templates/input-examples', - 'features/software-templates/builtin-actions', - 'features/software-templates/writing-custom-actions', - 'features/software-templates/writing-tests-for-actions', - 'features/software-templates/writing-custom-field-extensions', - 'features/software-templates/writing-custom-step-layouts', - 'features/software-templates/authorizing-scaffolder-template-details', - 'features/software-templates/migrating-to-rjsf-v5', - 'features/software-templates/migrating-from-v1beta2-to-v1beta3', - 'features/software-templates/dry-run-testing', - 'features/software-templates/experimental', - 'features/software-templates/templating-extensions', - { - type: 'category', - label: 'API', - link: - scaffolderSidebar.length > 0 - ? { - type: 'generated-index', - title: 'Scaffolder API', - slug: '/category/scaffolder-api', - } - : { - type: 'doc', - id: 'openapi/generated-docs/404', - }, - items: scaffolderSidebar, - }, - ], - }, - { - type: 'category', - label: 'TechDocs', - items: [ - 'features/techdocs/techdocs-overview', - 'features/techdocs/getting-started', - 'features/techdocs/concepts', - 'features/techdocs/addons', - 'features/techdocs/architecture', - 'features/techdocs/extensions', - 'features/techdocs/creating-and-publishing', - 'features/techdocs/configuration', - 'features/techdocs/using-cloud-storage', - 'features/techdocs/configuring-ci-cd', - 'features/techdocs/cli', - 'features/techdocs/how-to-guides', - 'features/techdocs/troubleshooting', - 'features/techdocs/faqs', - ], - }, - ], - Integrations: [ - 'integrations/index', - { - type: 'category', - label: 'AWS S3', - items: [ + [ + 'integrations/index', + sidebarElementWithIndex({ label: 'AWS S3' }, [ 'integrations/aws-s3/locations', 'integrations/aws-s3/discovery', - ], - }, - { - type: 'category', - label: 'Azure Blob Storage', - items: [ + ]), + sidebarElementWithIndex({ label: 'Azure Blob Storage' }, [ 'integrations/azure-blobStorage/locations', 'integrations/azure-blobStorage/discovery', - ], - }, - { - type: 'category', - label: 'Azure', - items: [ + ]), + sidebarElementWithIndex({ label: 'Azure' }, [ 'integrations/azure/locations', 'integrations/azure/discovery', 'integrations/azure/org', - ], - }, - { - type: 'category', - label: 'Bitbucket Cloud', - items: [ + ]), + sidebarElementWithIndex({ label: 'Bitbucket Cloud' }, [ 'integrations/bitbucketCloud/locations', 'integrations/bitbucketCloud/discovery', - ], - }, - { - type: 'category', - label: 'Bitbucket Server', - items: [ + ]), + sidebarElementWithIndex({ label: 'Bitbucket Server' }, [ 'integrations/bitbucketServer/locations', 'integrations/bitbucketServer/discovery', - ], - }, - { - type: 'category', - label: 'Datadog', - items: ['integrations/datadog-rum/installation'], - }, - { - type: 'category', - label: 'Gerrit', - items: [ + ]), + sidebarElementWithIndex({ label: 'Datadog' }, [ + 'integrations/datadog-rum/installation', + ]), + sidebarElementWithIndex({ label: 'Gerrit' }, [ 'integrations/gerrit/locations', 'integrations/gerrit/discovery', - ], - }, - { - type: 'category', - label: 'GitHub', - items: [ + ]), + sidebarElementWithIndex({ label: 'Github' }, [ 'integrations/github/locations', 'integrations/github/discovery', 'integrations/github/org', 'integrations/github/github-apps', - ], - }, - { - type: 'category', - label: 'GitLab', - items: [ + ]), + sidebarElementWithIndex({ label: 'GitLab' }, [ 'integrations/gitlab/locations', 'integrations/gitlab/discovery', 'integrations/gitlab/org', - ], - }, + ]), + sidebarElementWithIndex({ label: 'Gitea' }, [ + 'integrations/gitea/locations', + 'integrations/gitea/discovery', + ]), + sidebarElementWithIndex({ label: 'Harness' }, [ + 'integrations/harness/locations', + ]), + sidebarElementWithIndex({ label: 'Google GCS' }, [ + 'integrations/google-cloud-storage/locations', + ]), + sidebarElementWithIndex({ label: 'LDAP' }, ['integrations/ldap/org']), + ], + ), + sidebarElementWithIndex( { - type: 'category', - label: 'Gitea', - items: ['integrations/gitea/locations', 'integrations/gitea/discovery'], + label: 'Plugins', + description: 'Extend Backstage with custom functionality.', }, - { - type: 'category', - label: 'Harness', - items: ['integrations/harness/locations'], - }, - { - type: 'category', - label: 'Google GCS', - items: ['integrations/google-cloud-storage/locations'], - }, - { - type: 'category', - label: 'LDAP', - items: ['integrations/ldap/org'], - }, - ], - Plugins: [ - 'plugins/index', - 'plugins/existing-plugins', - 'plugins/create-a-plugin', - 'plugins/plugin-development', - 'plugins/structure-of-a-plugin', - 'plugins/integrating-plugin-into-software-catalog', - 'plugins/integrating-search-into-plugins', - 'plugins/composability', - 'plugins/internationalization', - 'plugins/analytics', - 'plugins/feature-flags', - { - type: 'category', - label: 'OpenAPI', - items: [ - 'openapi/01-getting-started', - 'openapi/generate-client', - 'openapi/test-case-validation', - ], - }, - { - type: 'category', - label: 'Backends and APIs', - items: [ - 'plugins/proxying', - 'plugins/backend-plugin', - 'plugins/call-existing-api', - ], - }, - { - type: 'category', - label: 'Testing', - items: ['plugins/testing'], - }, - { - type: 'category', - label: 'Publishing', - items: [ - 'plugins/publish-private', - 'plugins/add-to-directory', - 'plugins/observability', - ], - }, - ], - Configuration: [ - 'conf/index', - 'conf/reading', - 'conf/writing', - 'conf/defining', - ], - Framework: [ - { - type: 'category', - label: 'Backend System', - items: [ - 'backend-system/index', + [ + 'plugins/index', + 'plugins/existing-plugins', + 'plugins/create-a-plugin', + 'plugins/plugin-development', + 'plugins/structure-of-a-plugin', + 'plugins/integrating-plugin-into-software-catalog', + 'plugins/integrating-search-into-plugins', + 'plugins/composability', + 'plugins/internationalization', + 'plugins/analytics', + 'plugins/feature-flags', + sidebarElementWithIndex( { - type: 'category', - label: 'Architecture', - items: [ - 'backend-system/architecture/index', - 'backend-system/architecture/services', - 'backend-system/architecture/plugins', - 'backend-system/architecture/extension-points', - 'backend-system/architecture/modules', - 'backend-system/architecture/feature-loaders', - 'backend-system/architecture/naming-patterns', - ], + label: 'OpenAPI', + description: + 'Work with OpenAPI specifications and generate clients.', }, + [ + 'openapi/01-getting-started', + 'openapi/generate-client', + 'openapi/test-case-validation', + ], + ), + sidebarElementWithIndex( { - type: 'category', - label: 'Building Backends', - items: [ - 'backend-system/building-backends/index', - 'backend-system/building-backends/migrating', - ], + label: 'Backends and APIs', + description: 'Build and manage backend services and APIs.', }, - { - type: 'category', - label: 'Building Plugins & Modules', - items: [ - 'backend-system/building-plugins-and-modules/index', - 'backend-system/building-plugins-and-modules/testing', - 'backend-system/building-plugins-and-modules/migrating', - ], - }, - { - type: 'category', - label: 'Core Services', - items: [ - 'backend-system/core-services/index', - 'backend-system/core-services/auditor', - 'backend-system/core-services/auth', - 'backend-system/core-services/cache', - 'backend-system/core-services/database', - 'backend-system/core-services/discovery', - 'backend-system/core-services/http-auth', - 'backend-system/core-services/http-router', - 'backend-system/core-services/identity', - 'backend-system/core-services/lifecycle', - 'backend-system/core-services/logger', - 'backend-system/core-services/permissions', - 'backend-system/core-services/permissions-registry', - 'backend-system/core-services/plugin-metadata', - 'backend-system/core-services/root-config', - 'backend-system/core-services/root-health', - 'backend-system/core-services/root-http-router', - 'backend-system/core-services/root-lifecycle', - 'backend-system/core-services/root-logger', - 'backend-system/core-services/scheduler', - 'backend-system/core-services/token-manager', - 'backend-system/core-services/url-reader', - 'backend-system/core-services/user-info', - 'backend-system/core-services/actions-registry', - 'backend-system/core-services/actions', - ], - }, - ], - }, + [ + 'plugins/proxying', + 'plugins/backend-plugin', + 'plugins/call-existing-api', + ], + ), + sidebarElementWithIndex( + { label: 'Testing', description: 'Testing plugins and modules.' }, + ['plugins/testing'], + ), + sidebarElementWithIndex( + { label: 'Publishing', description: 'Publishing your plugins.' }, + ['plugins/publish-private', 'plugins/add-to-directory'], + ), + 'plugins/observability', + ], + ), + sidebarElementWithIndex( { - type: 'category', - label: 'New Frontend System', - items: [ - 'frontend-system/index', + label: 'Configuration', + description: 'Manage static configuration files and settings.', + }, + ['conf/index', 'conf/reading', 'conf/writing', 'conf/defining'], + ), + sidebarElementWithIndex( + { + label: 'Framework', + description: 'Core framework concepts and architecture.', + }, + [ + sidebarElementWithIndex( { - type: 'category', - label: 'Architecture', - items: [ - 'frontend-system/architecture/index', - 'frontend-system/architecture/app', - 'frontend-system/architecture/plugins', - 'frontend-system/architecture/extensions', - 'frontend-system/architecture/extension-blueprints', - 'frontend-system/architecture/extension-overrides', - 'frontend-system/architecture/references', - 'frontend-system/architecture/utility-apis', - 'frontend-system/architecture/routes', - 'frontend-system/architecture/naming-patterns', - 'frontend-system/architecture/migrations', - ], + label: 'Backend System', + description: 'Backend system components and architecture.', }, + [ + 'backend-system/index', + sidebarElementWithIndex( + { + label: 'Architecture', + description: 'Architecture of the backend system.', + }, + [ + 'backend-system/architecture/index', + 'backend-system/architecture/services', + 'backend-system/architecture/plugins', + 'backend-system/architecture/extension-points', + 'backend-system/architecture/modules', + 'backend-system/architecture/feature-loaders', + 'backend-system/architecture/naming-patterns', + ], + ), + sidebarElementWithIndex( + { + label: 'Building Backends', + description: 'Guides on building backend systems.', + }, + [ + 'backend-system/building-backends/index', + 'backend-system/building-backends/migrating', + ], + ), + sidebarElementWithIndex( + { + label: 'Building Plugins & Modules', + description: 'Guides on building plugins and modules.', + }, + [ + 'backend-system/building-plugins-and-modules/index', + 'backend-system/building-plugins-and-modules/testing', + 'backend-system/building-plugins-and-modules/migrating', + ], + ), + sidebarElementWithIndex( + { + label: 'Core Services', + description: 'Core services of the backend system.', + }, + [ + 'backend-system/core-services/index', + 'backend-system/core-services/auditor', + 'backend-system/core-services/auth', + 'backend-system/core-services/cache', + 'backend-system/core-services/database', + 'backend-system/core-services/discovery', + 'backend-system/core-services/http-auth', + 'backend-system/core-services/http-router', + 'backend-system/core-services/identity', + 'backend-system/core-services/lifecycle', + 'backend-system/core-services/logger', + 'backend-system/core-services/permissions', + 'backend-system/core-services/permissions-registry', + 'backend-system/core-services/plugin-metadata', + 'backend-system/core-services/root-config', + 'backend-system/core-services/root-health', + 'backend-system/core-services/root-http-router', + 'backend-system/core-services/root-instance-metadata', + 'backend-system/core-services/root-lifecycle', + 'backend-system/core-services/root-logger', + 'backend-system/core-services/scheduler', + 'backend-system/core-services/token-manager', + 'backend-system/core-services/url-reader', + 'backend-system/core-services/user-info', + 'backend-system/core-services/actions-registry', + 'backend-system/core-services/actions', + ], + ), + ], + ), + sidebarElementWithIndex( { - type: 'category', - label: 'Building Plugins', - items: [ - 'frontend-system/building-plugins/index', - 'frontend-system/building-plugins/testing', - 'frontend-system/building-plugins/common-extension-blueprints', - 'frontend-system/building-plugins/built-in-data-refs', - 'frontend-system/building-plugins/migrating', - ], + label: 'New Frontend System', + description: 'New frontend system components and architecture.', }, + [ + 'frontend-system/index', + sidebarElementWithIndex( + { + label: 'Architecture', + description: 'Architecture of the new frontend system.', + }, + [ + 'frontend-system/architecture/index', + 'frontend-system/architecture/app', + 'frontend-system/architecture/plugins', + 'frontend-system/architecture/extensions', + 'frontend-system/architecture/extension-blueprints', + 'frontend-system/architecture/extension-overrides', + 'frontend-system/architecture/references', + 'frontend-system/architecture/utility-apis', + 'frontend-system/architecture/routes', + 'frontend-system/architecture/naming-patterns', + 'frontend-system/architecture/migrations', + ], + ), + sidebarElementWithIndex( + { + label: 'Building Plugins', + description: 'Guides on building frontend plugins.', + }, + [ + 'frontend-system/building-plugins/index', + 'frontend-system/building-plugins/testing', + 'frontend-system/building-plugins/common-extension-blueprints', + 'frontend-system/building-plugins/built-in-data-refs', + 'frontend-system/building-plugins/migrating', + ], + ), + sidebarElementWithIndex( + { + label: 'Building Apps', + description: 'Guides on building frontend applications.', + }, + [ + 'frontend-system/building-apps/index', + 'frontend-system/building-apps/configuring-extensions', + 'frontend-system/building-apps/built-in-extensions', + 'frontend-system/building-apps/plugin-conversion', + 'frontend-system/building-apps/migrating', + ], + ), + sidebarElementWithIndex( + { + label: 'Utility APIs', + description: 'Utility APIs for the frontend system.', + }, + [ + 'frontend-system/utility-apis/index', + 'frontend-system/utility-apis/creating', + 'frontend-system/utility-apis/consuming', + 'frontend-system/utility-apis/configuring', + ], + ), + ], + ), + sidebarElementWithIndex( { - type: 'category', - label: 'Building Apps', - items: [ - 'frontend-system/building-apps/index', - 'frontend-system/building-apps/configuring-extensions', - 'frontend-system/building-apps/built-in-extensions', - 'frontend-system/building-apps/plugin-conversion', - 'frontend-system/building-apps/migrating', - ], + label: 'Backstage CLI', + description: 'Command-line interface for Backstage.', }, + [ + 'tooling/cli/overview', + 'tooling/cli/build-system', + 'tooling/cli/commands', + 'tooling/cli/templates', + sidebarElementWithIndex( + { + label: 'Local Development', + description: + 'Guides for local development using Backstage CLI.', + }, + [ + 'tooling/local-dev/linking-local-packages', + 'tooling/local-dev/debugging', + 'tooling/local-dev/profiling', + ], + ), + 'tooling/package-metadata', + ], + ), + sidebarElementWithIndex( { - type: 'category', - label: 'Utility APIs', - items: [ - 'frontend-system/utility-apis/index', - 'frontend-system/utility-apis/creating', - 'frontend-system/utility-apis/consuming', - 'frontend-system/utility-apis/configuring', - ], + label: 'User Interface', + description: 'User interface customization and configuration.', }, - ], - }, + [ + 'conf/user-interface/index', + 'conf/user-interface/logo', + 'conf/user-interface/icons', + 'conf/user-interface/sidebar', + ], + ), + ], + ), + sidebarElementWithIndex( { - 'Backstage CLI': [ - 'tooling/cli/overview', - 'tooling/cli/build-system', - 'tooling/cli/commands', - 'tooling/cli/templates', + label: 'Tutorials', + description: + 'Step-by-step tutorials for various Backstage features and use cases.', + }, + [ + sidebarElementWithIndex( { - type: 'category', - label: 'Local Development', - items: [ - 'tooling/local-dev/linking-local-packages', - 'tooling/local-dev/debugging', - 'tooling/local-dev/profiling', - ], + label: 'Non-technical', + description: 'Non-technical tutorials and guides.', }, - 'tooling/package-metadata', - ], - }, + ['overview/adopting'], + ), + sidebarElementWithIndex( + { + label: 'Technical', + description: 'Technical tutorials and guides.', + }, + [ + 'tutorials/quickstart-app-plugin', + 'tutorials/configuring-plugin-databases', + 'tutorials/manual-knex-rollback', + 'tutorials/switching-sqlite-postgres', + 'tutorials/using-backstage-proxy-within-plugin', + 'tutorials/enable-public-entry', + 'tutorials/setup-opentelemetry', + 'tutorials/integrating-event-driven-updates-with-entity-providers', + 'accessibility/index', + ], + ), + sidebarElementWithIndex( + { + label: 'Migrations', + description: + 'Guides for migrating between different versions and systems.', + }, + [ + 'tutorials/jest30-migration', + 'tutorials/react-router-stable-migration', + 'tutorials/react18-migration', + 'tutorials/package-role-migration', + 'tutorials/migrating-away-from-core', + 'tutorials/yarn-migration', + 'tutorials/migrate-to-mui5', + 'tutorials/auth-service-migration', + 'tutorials/jsx-transform-migration', + ], + ), + ], + ), + sidebarElementWithIndex( + { label: 'FAQ', description: 'Frequently asked questions and answers.' }, + ['faq/index', 'faq/product', 'faq/technical'], + ), + sidebarElementWithIndex( { - type: 'category', - label: 'User Interface', - items: [ - 'conf/user-interface/index', - 'conf/user-interface/logo', - 'conf/user-interface/icons', - 'conf/user-interface/sidebar', - ], + label: 'Contribute', + description: 'Information on contributing to Backstage.', }, - ], - Tutorials: [ - { 'Non-technical': ['overview/adopting'] }, + [ + 'contribute/index', + 'contribute/getting-involved', + 'contribute/project-structure', + ], + ), + sidebarElementWithIndex( { - Technical: [ - 'tutorials/quickstart-app-plugin', - 'tutorials/configuring-plugin-databases', - 'tutorials/manual-knex-rollback', - 'tutorials/switching-sqlite-postgres', - 'tutorials/using-backstage-proxy-within-plugin', - 'tutorials/enable-public-entry', - 'tutorials/setup-opentelemetry', - 'tutorials/integrating-event-driven-updates-with-entity-providers', - 'accessibility/index', - ], + label: 'References', + description: 'Reference materials and documentation.', }, - { - Migrations: [ - 'tutorials/react-router-stable-migration', - 'tutorials/react18-migration', - 'tutorials/package-role-migration', - 'tutorials/migrating-away-from-core', - 'tutorials/yarn-migration', - 'tutorials/migrate-to-mui5', - 'tutorials/auth-service-migration', - 'tutorials/jsx-transform-migration', - ], - }, - ], - FAQ: ['faq/index', 'faq/product', 'faq/technical'], - Contribute: [ - 'contribute/index', - 'contribute/getting-involved', - 'contribute/project-structure', - ], - References: [ - { - 'Designing for Backstage': [ - 'dls/design', - 'dls/component-design-guidelines', - 'dls/contributing-to-storybook', - 'dls/figma', - ], - }, - { - type: 'category', - label: 'Architecture Decision Records (ADRs)', - items: [ - 'architecture-decisions/adrs-overview', - 'architecture-decisions/adrs-adr001', - 'architecture-decisions/adrs-adr002', - 'architecture-decisions/adrs-adr003', - 'architecture-decisions/adrs-adr004', - 'architecture-decisions/adrs-adr005', - 'architecture-decisions/adrs-adr006', - 'architecture-decisions/adrs-adr007', - 'architecture-decisions/adrs-adr008', - 'architecture-decisions/adrs-adr009', - 'architecture-decisions/adrs-adr010', - 'architecture-decisions/adrs-adr011', - 'architecture-decisions/adrs-adr012', - 'architecture-decisions/adrs-adr013', - 'architecture-decisions/adrs-adr014', - ], - }, - 'api/deprecations', - 'references/glossary', - 'api/utility-apis', - 'reference/index', - ], - }, + [ + sidebarElementWithIndex( + { + label: 'Designing for Backstage', + description: + 'Guidelines and resources for designing Backstage components.', + }, + [ + 'dls/design', + 'dls/component-design-guidelines', + 'dls/contributing-to-storybook', + 'dls/figma', + ], + ), + sidebarElementWithIndex( + { + label: 'Architecture Decision Records (ADRs)', + description: + 'Documentation of architectural decisions made in Backstage.', + }, + [ + 'architecture-decisions/adrs-overview', + 'architecture-decisions/adrs-adr001', + 'architecture-decisions/adrs-adr002', + 'architecture-decisions/adrs-adr003', + 'architecture-decisions/adrs-adr004', + 'architecture-decisions/adrs-adr005', + 'architecture-decisions/adrs-adr006', + 'architecture-decisions/adrs-adr007', + 'architecture-decisions/adrs-adr008', + 'architecture-decisions/adrs-adr009', + 'architecture-decisions/adrs-adr010', + 'architecture-decisions/adrs-adr011', + 'architecture-decisions/adrs-adr012', + 'architecture-decisions/adrs-adr013', + 'architecture-decisions/adrs-adr014', + 'architecture-decisions/adrs-adr015', + ], + ), + 'api/deprecations', + 'references/glossary', + 'api/utility-apis', + 'reference/index', + ], + ), + ], releases: { 'Release Notes': releases.map(release => `releases/${release}`), }, diff --git a/microsite/static/img/citrix_sds.png b/microsite/static/img/citrix_sds.png new file mode 100644 index 0000000000..fac58411a1 Binary files /dev/null and b/microsite/static/img/citrix_sds.png differ diff --git a/microsite/yarn.lock b/microsite/yarn.lock index 2f6e723889..acceac04e2 100644 --- a/microsite/yarn.lock +++ b/microsite/yarn.lock @@ -2961,90 +2961,90 @@ __metadata: languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.15.3": - version: 1.15.3 - resolution: "@swc/core-darwin-arm64@npm:1.15.3" +"@swc/core-darwin-arm64@npm:1.15.6": + version: 1.15.6 + resolution: "@swc/core-darwin-arm64@npm:1.15.6" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.15.3": - version: 1.15.3 - resolution: "@swc/core-darwin-x64@npm:1.15.3" +"@swc/core-darwin-x64@npm:1.15.6": + version: 1.15.6 + resolution: "@swc/core-darwin-x64@npm:1.15.6" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.15.3": - version: 1.15.3 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.15.3" +"@swc/core-linux-arm-gnueabihf@npm:1.15.6": + version: 1.15.6 + resolution: "@swc/core-linux-arm-gnueabihf@npm:1.15.6" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@swc/core-linux-arm64-gnu@npm:1.15.3": - version: 1.15.3 - resolution: "@swc/core-linux-arm64-gnu@npm:1.15.3" +"@swc/core-linux-arm64-gnu@npm:1.15.6": + version: 1.15.6 + resolution: "@swc/core-linux-arm64-gnu@npm:1.15.6" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.15.3": - version: 1.15.3 - resolution: "@swc/core-linux-arm64-musl@npm:1.15.3" +"@swc/core-linux-arm64-musl@npm:1.15.6": + version: 1.15.6 + resolution: "@swc/core-linux-arm64-musl@npm:1.15.6" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.15.3": - version: 1.15.3 - resolution: "@swc/core-linux-x64-gnu@npm:1.15.3" +"@swc/core-linux-x64-gnu@npm:1.15.6": + version: 1.15.6 + resolution: "@swc/core-linux-x64-gnu@npm:1.15.6" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.15.3": - version: 1.15.3 - resolution: "@swc/core-linux-x64-musl@npm:1.15.3" +"@swc/core-linux-x64-musl@npm:1.15.6": + version: 1.15.6 + resolution: "@swc/core-linux-x64-musl@npm:1.15.6" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.15.3": - version: 1.15.3 - resolution: "@swc/core-win32-arm64-msvc@npm:1.15.3" +"@swc/core-win32-arm64-msvc@npm:1.15.6": + version: 1.15.6 + resolution: "@swc/core-win32-arm64-msvc@npm:1.15.6" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.15.3": - version: 1.15.3 - resolution: "@swc/core-win32-ia32-msvc@npm:1.15.3" +"@swc/core-win32-ia32-msvc@npm:1.15.6": + version: 1.15.6 + resolution: "@swc/core-win32-ia32-msvc@npm:1.15.6" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.15.3": - version: 1.15.3 - resolution: "@swc/core-win32-x64-msvc@npm:1.15.3" +"@swc/core-win32-x64-msvc@npm:1.15.6": + version: 1.15.6 + resolution: "@swc/core-win32-x64-msvc@npm:1.15.6" conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"@swc/core@npm:^1.3.46": - version: 1.15.3 - resolution: "@swc/core@npm:1.15.3" +"@swc/core@npm:^1.15.6": + version: 1.15.6 + resolution: "@swc/core@npm:1.15.6" dependencies: - "@swc/core-darwin-arm64": "npm:1.15.3" - "@swc/core-darwin-x64": "npm:1.15.3" - "@swc/core-linux-arm-gnueabihf": "npm:1.15.3" - "@swc/core-linux-arm64-gnu": "npm:1.15.3" - "@swc/core-linux-arm64-musl": "npm:1.15.3" - "@swc/core-linux-x64-gnu": "npm:1.15.3" - "@swc/core-linux-x64-musl": "npm:1.15.3" - "@swc/core-win32-arm64-msvc": "npm:1.15.3" - "@swc/core-win32-ia32-msvc": "npm:1.15.3" - "@swc/core-win32-x64-msvc": "npm:1.15.3" + "@swc/core-darwin-arm64": "npm:1.15.6" + "@swc/core-darwin-x64": "npm:1.15.6" + "@swc/core-linux-arm-gnueabihf": "npm:1.15.6" + "@swc/core-linux-arm64-gnu": "npm:1.15.6" + "@swc/core-linux-arm64-musl": "npm:1.15.6" + "@swc/core-linux-x64-gnu": "npm:1.15.6" + "@swc/core-linux-x64-musl": "npm:1.15.6" + "@swc/core-win32-arm64-msvc": "npm:1.15.6" + "@swc/core-win32-ia32-msvc": "npm:1.15.6" + "@swc/core-win32-x64-msvc": "npm:1.15.6" "@swc/counter": "npm:^0.1.3" "@swc/types": "npm:^0.1.25" peerDependencies: @@ -3073,7 +3073,7 @@ __metadata: peerDependenciesMeta: "@swc/helpers": optional: true - checksum: 10/280330d82328818138ed64fdcf9ea9abde6b6f16eca65a9d4db27dde06a8dfffd2649f3447d2243387277513c7430fa4142cafcfd64e943d682ce6a713cb8c2d + checksum: 10/d17d1b5e6e81f8c262b668f237b863dd612eaa19fc35e74067b2a27ba3998c0c511ec7f49cd91c02f61fa77dd1b5d7e65d293736f65ec45d6c13989904b1c7eb languageName: node linkType: hard @@ -4274,7 +4274,7 @@ __metadata: "@docusaurus/tsconfig": "npm:^3.1.1" "@docusaurus/types": "npm:^3.1.1" "@mdx-js/react": "npm:^3.0.0" - "@swc/core": "npm:^1.3.46" + "@swc/core": "npm:^1.15.6" "@types/webpack-env": "npm:^1.18.0" clsx: "npm:^2.0.0" docusaurus-plugin-openapi-docs: "npm:^4.3.0" @@ -4721,9 +4721,9 @@ __metadata: linkType: hard "caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001646, caniuse-lite@npm:^1.0.30001688": - version: 1.0.30001695 - resolution: "caniuse-lite@npm:1.0.30001695" - checksum: 10/8107c5e89b86c7a2fd506b93c658ff945c98c6518260c3b28af9f02bd83bf83939696241f0b413545c5b9895c86bcae64c9370388576440e74e9b848f04170d3 + version: 1.0.30001760 + resolution: "caniuse-lite@npm:1.0.30001760" + checksum: 10/ac5c13d00b946c3ace331d25379ed9d85743b1028aba79ae80402cb128b4b491122585144898fefb836d4d9879c13c717a081ae241a00420cbbc7e1b934ec685 languageName: node linkType: hard diff --git a/package.json b/package.json index 4a67751584..879899cae1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "root", - "version": "1.46.0-next.1", + "version": "1.47.0-next.0", "backstage": { "cli": { "new": { @@ -117,7 +117,6 @@ "csstype@npm:^3.0.2": "3.0.9", "csstype@npm:^3.1.2": "3.0.9", "csstype@npm:^3.1.3": "3.0.9", - "jest-haste-map@^29.7.0": "patch:jest-haste-map@npm%3A29.7.0#./.yarn/patches/jest-haste-map-npm-29.7.0-e3be419eff.patch", "recast@npm:0.23.9>ast-types": "patch:ast-types@npm%3A0.16.1#./.yarn/patches/ast-types-npm-0.16.1-43c4ac4b0d.patch" }, "dependencies": { @@ -138,11 +137,12 @@ "@octokit/rest": "^19.0.3", "@playwright/test": "^1.32.3", "@spotify/eslint-plugin": "^15.0.0", - "@storybook/addon-a11y": "^9.1.7", - "@storybook/addon-docs": "^9.1.7", - "@storybook/addon-links": "^9.1.7", - "@storybook/addon-themes": "^9.1.7", - "@storybook/react-vite": "^9.1.7", + "@storybook/addon-a11y": "^10.1.9", + "@storybook/addon-docs": "^10.1.9", + "@storybook/addon-links": "^10.1.9", + "@storybook/addon-themes": "^10.1.9", + "@storybook/addon-vitest": "^10.1.9", + "@storybook/react-vite": "^10.1.9", "@techdocs/cli": "workspace:*", "@types/cacheable-request": "^8.3.6", "@types/memjs": "^1.3.3", @@ -168,7 +168,7 @@ "shx": "^0.4.0", "sloc": "^0.3.1", "sort-package-json": "^2.8.0", - "storybook": "^9.1.7", + "storybook": "^10.1.10", "ts-morph": "^24.0.0", "typedoc": "^0.28.0", "typescript": "~5.7.0", diff --git a/packages/app-defaults/CHANGELOG.md b/packages/app-defaults/CHANGELOG.md index ee64c2209e..cca956654d 100644 --- a/packages/app-defaults/CHANGELOG.md +++ b/packages/app-defaults/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/app-defaults +## 1.7.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.19.3 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/theme@0.7.1 + - @backstage/plugin-permission-react@0.4.39 + ## 1.7.3-next.0 ### Patch Changes diff --git a/packages/app-defaults/package.json b/packages/app-defaults/package.json index ec08c04929..878e5b505b 100644 --- a/packages/app-defaults/package.json +++ b/packages/app-defaults/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/app-defaults", - "version": "1.7.3-next.0", + "version": "1.7.3", "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 da46f90c56..ee1e797be4 100644 --- a/packages/app-next-example-plugin/CHANGELOG.md +++ b/packages/app-next-example-plugin/CHANGELOG.md @@ -1,5 +1,13 @@ # app-next-example-plugin +## 0.0.30 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + ## 0.0.30-next.0 ### Patch Changes diff --git a/packages/app-next-example-plugin/package.json b/packages/app-next-example-plugin/package.json index f7d113827d..f632f00de8 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.30-next.0", + "version": "0.0.30", "description": "Backstage internal example plugin", "backstage": { "role": "frontend-plugin", diff --git a/packages/app-next/CHANGELOG.md b/packages/app-next/CHANGELOG.md index 9e29cd2b2e..d0789288e3 100644 --- a/packages/app-next/CHANGELOG.md +++ b/packages/app-next/CHANGELOG.md @@ -1,5 +1,142 @@ # example-app-next +## 0.0.31-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/ui@0.11.0-next.0 + - @backstage/cli@0.35.2-next.0 + - @backstage/plugin-app-visualizer@0.1.27-next.0 + - @backstage/app-defaults@1.7.3 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/core-app-api@1.19.3 + - @backstage/core-compat-api@0.5.5 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/frontend-app-api@0.13.3 + - @backstage/frontend-defaults@0.3.4 + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/integration-react@1.2.13 + - @backstage/theme@0.7.1 + - @backstage/plugin-api-docs@0.13.2 + - @backstage/plugin-app@0.3.3 + - @backstage/plugin-auth@0.1.3 + - @backstage/plugin-auth-react@0.1.22 + - @backstage/plugin-catalog@1.32.1 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-graph@0.5.4 + - @backstage/plugin-catalog-import@0.13.8 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/plugin-catalog-unprocessed-entities@0.2.24 + - @backstage/plugin-home@0.8.15 + - @backstage/plugin-kubernetes@0.12.14 + - @backstage/plugin-kubernetes-cluster@0.0.32 + - @backstage/plugin-notifications@0.5.12 + - @backstage/plugin-org@0.6.47 + - @backstage/plugin-permission-react@0.4.39 + - @backstage/plugin-scaffolder@1.35.0 + - @backstage/plugin-scaffolder-react@1.19.4 + - @backstage/plugin-search@1.5.1 + - @backstage/plugin-search-common@1.2.21 + - @backstage/plugin-search-react@1.10.1 + - @backstage/plugin-signals@0.0.26 + - @backstage/plugin-techdocs@1.16.1 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.31 + - @backstage/plugin-techdocs-react@1.3.6 + - @backstage/plugin-user-settings@0.8.30 + +## 0.0.30 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.19.3 + - @backstage/cli@0.35.0 + - @backstage/ui@0.10.0 + - @backstage/plugin-catalog-graph@0.5.4 + - @backstage/plugin-api-docs@0.13.2 + - @backstage/plugin-techdocs@1.16.1 + - @backstage/plugin-catalog@1.32.1 + - @backstage/plugin-search@1.5.1 + - @backstage/plugin-app@0.3.3 + - @backstage/plugin-org@0.6.47 + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/plugin-scaffolder-react@1.19.4 + - @backstage/core-components@0.18.4 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.31 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/plugin-kubernetes@0.12.14 + - @backstage/plugin-search-react@1.10.1 + - @backstage/core-plugin-api@1.12.1 + - @backstage/plugin-catalog-unprocessed-entities@0.2.24 + - @backstage/plugin-app-visualizer@0.1.26 + - @backstage/plugin-catalog-import@0.13.8 + - @backstage/plugin-notifications@0.5.12 + - @backstage/plugin-user-settings@0.8.30 + - @backstage/plugin-scaffolder@1.35.0 + - @backstage/plugin-home@0.8.15 + - @backstage/theme@0.7.1 + - @backstage/plugin-kubernetes-cluster@0.0.32 + - @backstage/app-defaults@1.7.3 + - @backstage/core-compat-api@0.5.5 + - @backstage/frontend-app-api@0.13.3 + - @backstage/frontend-defaults@0.3.4 + - @backstage/integration-react@1.2.13 + - @backstage/plugin-auth@0.1.3 + - @backstage/plugin-auth-react@0.1.22 + - @backstage/plugin-permission-react@0.4.39 + - @backstage/plugin-signals@0.0.26 + - @backstage/plugin-techdocs-react@1.3.6 + +## 0.0.30-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.19.3-next.1 + - @backstage/cli@0.35.0-next.2 + - @backstage/plugin-catalog-graph@0.5.4-next.1 + - @backstage/plugin-api-docs@0.13.2-next.1 + - @backstage/plugin-techdocs@1.16.1-next.2 + - @backstage/plugin-catalog@1.32.1-next.1 + - @backstage/plugin-search@1.5.1-next.1 + - @backstage/plugin-app@0.3.3-next.1 + - @backstage/plugin-org@0.6.47-next.1 + - @backstage/frontend-plugin-api@0.13.2-next.1 + - @backstage/plugin-scaffolder-react@1.19.4-next.2 + - @backstage/plugin-catalog-react@1.21.4-next.2 + - @backstage/core-components@0.18.4-next.2 + - @backstage/plugin-home@0.8.15-next.1 + - @backstage/plugin-scaffolder@1.34.4-next.1 + - @backstage/plugin-kubernetes-cluster@0.0.32-next.2 + - @backstage/app-defaults@1.7.3-next.0 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/core-compat-api@0.5.5-next.0 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/frontend-app-api@0.13.3-next.0 + - @backstage/frontend-defaults@0.3.4-next.0 + - @backstage/integration-react@1.2.13-next.0 + - @backstage/theme@0.7.1-next.0 + - @backstage/ui@0.10.0-next.1 + - @backstage/plugin-app-visualizer@0.1.26-next.1 + - @backstage/plugin-auth@0.1.3-next.0 + - @backstage/plugin-auth-react@0.1.22-next.0 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-import@0.13.8-next.0 + - @backstage/plugin-catalog-unprocessed-entities@0.2.24-next.1 + - @backstage/plugin-kubernetes@0.12.14-next.1 + - @backstage/plugin-notifications@0.5.12-next.0 + - @backstage/plugin-permission-react@0.4.39-next.0 + - @backstage/plugin-search-common@1.2.21 + - @backstage/plugin-search-react@1.10.1-next.0 + - @backstage/plugin-signals@0.0.26-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.31-next.1 + - @backstage/plugin-techdocs-react@1.3.6-next.0 + - @backstage/plugin-user-settings@0.8.30-next.0 + ## 0.0.30-next.1 ### Patch Changes diff --git a/packages/app-next/package.json b/packages/app-next/package.json index 2a3b5dbf8a..e1709b4c8f 100644 --- a/packages/app-next/package.json +++ b/packages/app-next/package.json @@ -1,6 +1,6 @@ { "name": "example-app-next", - "version": "0.0.30-next.1", + "version": "0.0.31-next.0", "backstage": { "role": "frontend" }, diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index 82e800c5ef..cc51e2878c 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,130 @@ # example-app +## 0.2.117-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/ui@0.11.0-next.0 + - @backstage/cli@0.35.2-next.0 + - @backstage/plugin-mui-to-bui@0.2.3-next.0 + - @backstage/app-defaults@1.7.3 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/core-app-api@1.19.3 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/frontend-app-api@0.13.3 + - @backstage/integration-react@1.2.13 + - @backstage/theme@0.7.1 + - @backstage/plugin-api-docs@0.13.2 + - @backstage/plugin-auth-react@0.1.22 + - @backstage/plugin-catalog@1.32.1 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-graph@0.5.4 + - @backstage/plugin-catalog-import@0.13.8 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/plugin-catalog-unprocessed-entities@0.2.24 + - @backstage/plugin-devtools@0.1.34 + - @backstage/plugin-home@0.8.15 + - @backstage/plugin-kubernetes@0.12.14 + - @backstage/plugin-kubernetes-cluster@0.0.32 + - @backstage/plugin-notifications@0.5.12 + - @backstage/plugin-org@0.6.47 + - @backstage/plugin-permission-react@0.4.39 + - @backstage/plugin-scaffolder@1.35.0 + - @backstage/plugin-scaffolder-react@1.19.4 + - @backstage/plugin-search@1.5.1 + - @backstage/plugin-search-common@1.2.21 + - @backstage/plugin-search-react@1.10.1 + - @backstage/plugin-signals@0.0.26 + - @backstage/plugin-techdocs@1.16.1 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.31 + - @backstage/plugin-techdocs-react@1.3.6 + - @backstage/plugin-user-settings@0.8.30 + +## 0.2.116 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.19.3 + - @backstage/cli@0.35.0 + - @backstage/ui@0.10.0 + - @backstage/plugin-catalog-graph@0.5.4 + - @backstage/plugin-api-docs@0.13.2 + - @backstage/plugin-techdocs@1.16.1 + - @backstage/plugin-catalog@1.32.1 + - @backstage/plugin-search@1.5.1 + - @backstage/plugin-org@0.6.47 + - @backstage/plugin-scaffolder-react@1.19.4 + - @backstage/core-components@0.18.4 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.31 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/plugin-kubernetes@0.12.14 + - @backstage/plugin-search-react@1.10.1 + - @backstage/core-plugin-api@1.12.1 + - @backstage/plugin-catalog-unprocessed-entities@0.2.24 + - @backstage/plugin-catalog-import@0.13.8 + - @backstage/plugin-notifications@0.5.12 + - @backstage/plugin-user-settings@0.8.30 + - @backstage/plugin-scaffolder@1.35.0 + - @backstage/plugin-devtools@0.1.34 + - @backstage/plugin-home@0.8.15 + - @backstage/theme@0.7.1 + - @backstage/plugin-kubernetes-cluster@0.0.32 + - @backstage/app-defaults@1.7.3 + - @backstage/frontend-app-api@0.13.3 + - @backstage/integration-react@1.2.13 + - @backstage/plugin-auth-react@0.1.22 + - @backstage/plugin-mui-to-bui@0.2.2 + - @backstage/plugin-permission-react@0.4.39 + - @backstage/plugin-signals@0.0.26 + - @backstage/plugin-techdocs-react@1.3.6 + +## 0.2.116-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.19.3-next.1 + - @backstage/cli@0.35.0-next.2 + - @backstage/plugin-catalog-graph@0.5.4-next.1 + - @backstage/plugin-api-docs@0.13.2-next.1 + - @backstage/plugin-techdocs@1.16.1-next.2 + - @backstage/plugin-catalog@1.32.1-next.1 + - @backstage/plugin-search@1.5.1-next.1 + - @backstage/plugin-org@0.6.47-next.1 + - @backstage/plugin-scaffolder-react@1.19.4-next.2 + - @backstage/plugin-catalog-react@1.21.4-next.2 + - @backstage/core-components@0.18.4-next.2 + - @backstage/plugin-home@0.8.15-next.1 + - @backstage/plugin-scaffolder@1.34.4-next.1 + - @backstage/plugin-kubernetes-cluster@0.0.32-next.2 + - @backstage/app-defaults@1.7.3-next.0 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/frontend-app-api@0.13.3-next.0 + - @backstage/integration-react@1.2.13-next.0 + - @backstage/theme@0.7.1-next.0 + - @backstage/ui@0.10.0-next.1 + - @backstage/plugin-auth-react@0.1.22-next.0 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-import@0.13.8-next.0 + - @backstage/plugin-catalog-unprocessed-entities@0.2.24-next.1 + - @backstage/plugin-devtools@0.1.34-next.0 + - @backstage/plugin-kubernetes@0.12.14-next.1 + - @backstage/plugin-mui-to-bui@0.2.2-next.1 + - @backstage/plugin-notifications@0.5.12-next.0 + - @backstage/plugin-permission-react@0.4.39-next.0 + - @backstage/plugin-search-common@1.2.21 + - @backstage/plugin-search-react@1.10.1-next.0 + - @backstage/plugin-signals@0.0.26-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.31-next.1 + - @backstage/plugin-techdocs-react@1.3.6-next.0 + - @backstage/plugin-user-settings@0.8.30-next.0 + ## 0.2.116-next.1 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index 5515e2a9c7..b2464821c0 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "example-app", - "version": "0.2.116-next.1", + "version": "0.2.117-next.0", "backstage": { "role": "frontend" }, diff --git a/packages/app/src/components/devtools/CustomDevToolsPage.tsx b/packages/app/src/components/devtools/CustomDevToolsPage.tsx index d1c68d9884..0fe17b14c3 100644 --- a/packages/app/src/components/devtools/CustomDevToolsPage.tsx +++ b/packages/app/src/components/devtools/CustomDevToolsPage.tsx @@ -18,6 +18,7 @@ import { ConfigContent, ExternalDependenciesContent, InfoContent, + ScheduledTasksContent, } from '@backstage/plugin-devtools'; import { DevToolsLayout } from '@backstage/plugin-devtools'; import { UnprocessedEntitiesContent } from '@backstage/plugin-catalog-unprocessed-entities'; @@ -31,6 +32,9 @@ const DevToolsPage = () => { + + + { it('correctly applies namespace configuration to redis and valkey stores', () => { const testCases = [ - { store: 'redis', namespace: 'test1', separator: ':' }, - { store: 'valkey', namespace: 'test2', separator: '!' }, + { + store: 'redis', + client: { + namespace: 'my-app', + keyPrefixSeparator: ':', + }, + }, + { store: 'valkey', client: { keyPrefix: 'my-app:' } }, ]; - testCases.forEach(({ store, namespace, separator }) => { + testCases.forEach(({ store, client }) => { const manager = CacheManager.fromConfig( mockServices.rootConfig({ data: { @@ -349,10 +355,7 @@ describe('CacheManager store options', () => { store, connection: 'redis://localhost:6379', [store]: { - client: { - namespace, - keyPrefixSeparator: separator, - }, + client, }, }, }, @@ -364,16 +367,16 @@ describe('CacheManager store options', () => { if (store === 'redis') { // eslint-disable-next-line jest/no-conditional-expect - expect(KeyvRedis).toHaveBeenCalledWith('redis://localhost:6379', { - namespace, - keyPrefixSeparator: separator, - }); + expect(KeyvRedis).toHaveBeenCalledWith( + 'redis://localhost:6379', + client, + ); } else if (store === 'valkey') { // eslint-disable-next-line jest/no-conditional-expect - expect(KeyvValkey).toHaveBeenCalledWith('redis://localhost:6379', { - namespace, - keyPrefixSeparator: separator, - }); + expect(KeyvValkey).toHaveBeenCalledWith( + 'redis://localhost:6379', + client, + ); } }); }); @@ -408,21 +411,31 @@ describe('CacheManager store options', () => { expect(result).toBe('testPlugin'); }); - it('returns pluginId when store options have no namespace', () => { - const storeOptions = { - client: { - keyPrefixSeparator: ':', - }, - }; - const result = (CacheManager as any).constructNamespace( - 'testPlugin', - storeOptions, - ); - expect(result).toBe('testPlugin'); - }); + it.each([ + { + type: 'redis', + field: 'namespace', + client: { keyPrefixSeparator: ':' }, + }, + { type: 'valkey', field: 'keyPrefix', client: {} }, + ])( + 'returns pluginId when store options have no $field for $type', + ({ type, client }) => { + const storeOptions = { + type, + client, + }; + const result = (CacheManager as any).constructNamespace( + 'testPlugin', + storeOptions, + ); + expect(result).toBe('testPlugin'); + }, + ); - it('combines namespace and pluginId with default separator', () => { + it('combines namespace and pluginId with default separator for redis', () => { const storeOptions = { + type: 'redis', client: { namespace: 'my-app', keyPrefixSeparator: ':', @@ -435,8 +448,9 @@ describe('CacheManager store options', () => { expect(result).toBe('my-app:testPlugin'); }); - it('combines namespace and pluginId with custom separator', () => { + it('combines namespace and pluginId with custom separator for redis', () => { const storeOptions = { + type: 'redis', client: { namespace: 'my-app', keyPrefixSeparator: '-', @@ -449,8 +463,9 @@ describe('CacheManager store options', () => { expect(result).toBe('my-app-testPlugin'); }); - it('uses default separator when keyPrefixSeparator is not provided', () => { + it('uses default separator when keyPrefixSeparator is not provided for redis', () => { const storeOptions = { + type: 'redis', client: { namespace: 'my-app', }, @@ -462,6 +477,20 @@ describe('CacheManager store options', () => { expect(result).toBe('my-app:testPlugin'); }); + it('uses keyPrefix for valkey', () => { + const storeOptions = { + type: 'valkey', + client: { + keyPrefix: 'my-app:', + }, + }; + const result = (CacheManager as any).constructNamespace( + 'testPlugin', + storeOptions, + ); + expect(result).toBe('my-app:testPlugin'); + }); + it('handles empty namespace by falling back to pluginId', () => { const storeOptions = { client: { diff --git a/packages/backend-defaults/src/entrypoints/cache/CacheManager.ts b/packages/backend-defaults/src/entrypoints/cache/CacheManager.ts index 06b2b0c57b..38c0c761ed 100644 --- a/packages/backend-defaults/src/entrypoints/cache/CacheManager.ts +++ b/packages/backend-defaults/src/entrypoints/cache/CacheManager.ts @@ -29,6 +29,7 @@ import { RedisCacheStoreOptions, InfinispanClientBehaviorOptions, InfinispanServerConfig, + ValkeyCacheStoreOptions, } from './types'; import { InfinispanOptionsMapper } from './providers/infinispan/InfinispanOptionsMapper'; import { durationToMilliseconds } from '@backstage/types'; @@ -134,43 +135,38 @@ export class CacheManager { ): CacheStoreOptions | undefined { const storeConfigPath = `backend.cache.${store}`; - if (!config.has(storeConfigPath)) { + if (store !== 'memory' && !config.has(storeConfigPath)) { logger?.warn( `No configuration found for cache store '${store}' at '${storeConfigPath}'.`, ); } - if (store === 'redis' || store === 'valkey') { - return CacheManager.parseRedisOptions( - store, - storeConfigPath, - config, - logger, - ); + switch (store) { + case 'redis': + return CacheManager.parseRedisOptions(storeConfigPath, config, logger); + case 'valkey': + return CacheManager.parseValkeyOptions(storeConfigPath, config, logger); + case 'infinispan': + return InfinispanOptionsMapper.parseInfinispanOptions( + storeConfigPath, + config, + logger, + ); + default: + return undefined; } - - if (store === 'infinispan') { - return InfinispanOptionsMapper.parseInfinispanOptions( - storeConfigPath, - config, - logger, - ); - } - - return undefined; } /** * Parse Redis-specific options from configuration. */ private static parseRedisOptions( - store: string, storeConfigPath: string, config: RootConfigService, logger?: LoggerService, ): RedisCacheStoreOptions { const redisOptions: RedisCacheStoreOptions = { - type: store as 'redis' | 'valkey', + type: 'redis', }; const redisConfig = @@ -213,6 +209,51 @@ export class CacheManager { return redisOptions; } + /** + * Parse Valkey-specific options from configuration. + */ + private static parseValkeyOptions( + storeConfigPath: string, + config: RootConfigService, + logger?: LoggerService, + ): ValkeyCacheStoreOptions { + const valkeyOptions: ValkeyCacheStoreOptions = { + type: 'valkey', + }; + + const valkeyConfig = + config.getOptionalConfig(storeConfigPath) ?? new ConfigReader({}); + + valkeyOptions.client = { + keyPrefix: valkeyConfig.getOptionalString('client.keyPrefix'), + }; + + if (valkeyConfig.has('cluster')) { + const clusterConfig = valkeyConfig.getConfig('cluster'); + + if (!clusterConfig.has('rootNodes')) { + logger?.warn( + `Valkey cluster config has no 'rootNodes' key, defaulting to non-clustered mode`, + ); + return valkeyOptions; + } + + valkeyOptions.cluster = { + rootNodes: clusterConfig.get('rootNodes'), + defaults: clusterConfig.getOptional('defaults'), + minimizeConnections: clusterConfig.getOptionalBoolean( + 'minimizeConnections', + ), + useReplicas: clusterConfig.getOptionalBoolean('useReplicas'), + maxCommandRedirections: clusterConfig.getOptionalNumber( + 'maxCommandRedirections', + ), + }; + } + + return valkeyOptions; + } + /** * Construct the full namespace based on the options and pluginId. * @@ -222,13 +263,23 @@ export class CacheManager { */ private static constructNamespace( pluginId: string, - storeOptions: RedisCacheStoreOptions | undefined, + storeOptions: RedisCacheStoreOptions | ValkeyCacheStoreOptions | undefined, ): string { - const prefix = storeOptions?.client?.namespace - ? `${storeOptions.client.namespace}${ - storeOptions.client.keyPrefixSeparator ?? ':' - }` - : ''; + let prefix: string; + switch (storeOptions?.type) { + case 'redis': + prefix = storeOptions?.client?.namespace + ? `${storeOptions.client.namespace}${ + storeOptions.client.keyPrefixSeparator ?? ':' + }` + : ''; + break; + case 'valkey': + prefix = storeOptions.client?.keyPrefix ?? ''; + break; + default: + prefix = ''; + } return `${prefix}${pluginId}`; } @@ -317,7 +368,9 @@ export class CacheManager { private createValkeyStoreFactory(): StoreFactory { const KeyvValkey = require('@keyv/valkey').default; - const { createCluster } = require('@keyv/valkey'); + // `@keyv/valkey` doesn't export a `createCluster` function, but is compatible with the one from `@keyv/redis` + // See https://keyv.org/docs/storage-adapters/valkey + const { createCluster } = require('@keyv/redis'); const stores: Record = {}; return (pluginId, defaultTtl) => { @@ -327,9 +380,7 @@ export class CacheManager { ); } if (!stores[pluginId]) { - const valkeyOptions = this.storeOptions?.client || { - keyPrefixSeparator: ':', - }; + const valkeyOptions = this.storeOptions?.client; if (this.storeOptions?.cluster) { // Create a Valkey cluster (Redis cluster under the hood) const cluster = createCluster(this.storeOptions?.cluster); diff --git a/packages/backend-defaults/src/entrypoints/cache/types.ts b/packages/backend-defaults/src/entrypoints/cache/types.ts index 522ab2ac3e..60e32e8618 100644 --- a/packages/backend-defaults/src/entrypoints/cache/types.ts +++ b/packages/backend-defaults/src/entrypoints/cache/types.ts @@ -17,6 +17,7 @@ import { LoggerService } from '@backstage/backend-plugin-api'; import { HumanDuration, durationToMilliseconds } from '@backstage/types'; import { RedisClusterOptions, KeyvRedisOptions } from '@keyv/redis'; +import { KeyvValkeyOptions } from '@keyv/valkey'; /** * Options for Redis cache store. @@ -24,11 +25,22 @@ import { RedisClusterOptions, KeyvRedisOptions } from '@keyv/redis'; * @public */ export type RedisCacheStoreOptions = { - type: 'redis' | 'valkey'; + type: 'redis'; client?: KeyvRedisOptions; cluster?: RedisClusterOptions; }; +/** + * Options for Valkey cache store. + * + * @public + */ +export type ValkeyCacheStoreOptions = { + type: 'valkey'; + client?: KeyvValkeyOptions; + cluster?: RedisClusterOptions; +}; + /** * Union type of all cache store options. * @@ -36,6 +48,7 @@ export type RedisCacheStoreOptions = { */ export type CacheStoreOptions = | RedisCacheStoreOptions + | ValkeyCacheStoreOptions | InfinispanCacheStoreOptions; /** diff --git a/packages/backend-defaults/src/entrypoints/rootHealth/rootHealthServiceFactory.test.ts b/packages/backend-defaults/src/entrypoints/rootHealth/rootHealthServiceFactory.test.ts index ca9085273c..4a5db18f6f 100644 --- a/packages/backend-defaults/src/entrypoints/rootHealth/rootHealthServiceFactory.test.ts +++ b/packages/backend-defaults/src/entrypoints/rootHealth/rootHealthServiceFactory.test.ts @@ -69,7 +69,7 @@ describe('DefaultRootHealthService', () => { await expect(service.getReadiness()).resolves.toEqual({ status: 503, payload: { - message: 'Backend is shuttting down', + message: 'Backend is shutting down', status: 'error', }, }); diff --git a/packages/backend-defaults/src/entrypoints/rootHealth/rootHealthServiceFactory.ts b/packages/backend-defaults/src/entrypoints/rootHealth/rootHealthServiceFactory.ts index e7255610bc..52812fc6b1 100644 --- a/packages/backend-defaults/src/entrypoints/rootHealth/rootHealthServiceFactory.ts +++ b/packages/backend-defaults/src/entrypoints/rootHealth/rootHealthServiceFactory.ts @@ -50,7 +50,7 @@ export class DefaultRootHealthService implements RootHealthService { if (this.#state === 'down') { return { status: 503, - payload: { message: 'Backend is shuttting down', status: 'error' }, + payload: { message: 'Backend is shutting down', status: 'error' }, }; } diff --git a/packages/backend-defaults/src/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.test.ts b/packages/backend-defaults/src/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.test.ts index 8f8d1b7656..e9982bc589 100644 --- a/packages/backend-defaults/src/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.test.ts +++ b/packages/backend-defaults/src/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.test.ts @@ -285,7 +285,7 @@ describe('rootHttpRouterServiceFactory', () => { // Immediately start failing the readiness health check await request(app).get('/.backstage/health/v1/readiness').expect(503, { - message: 'Backend is shuttting down', + message: 'Backend is shutting down', status: 'error', }); @@ -301,7 +301,7 @@ describe('rootHttpRouterServiceFactory', () => { .expect(200, { status: 'ok' }); await request(app).get('/.backstage/health/v1/readiness').expect(503, { - message: 'Backend is shuttting down', + message: 'Backend is shutting down', status: 'error', }); @@ -312,7 +312,7 @@ describe('rootHttpRouterServiceFactory', () => { .expect(200, { status: 'ok' }); await request(app).get('/.backstage/health/v1/readiness').expect(503, { - message: 'Backend is shuttting down', + message: 'Backend is shutting down', status: 'error', }); diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketCloudUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketCloudUrlReader.ts index ff6ec3bb27..73302d37e5 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketCloudUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketCloudUrlReader.ts @@ -68,7 +68,15 @@ export class BitbucketCloudUrlReader implements UrlReaderService { ) { this.integration = integration; this.deps = deps; - const { host, username, appPassword, token } = integration.config; + const { host, username, appPassword, token, clientId, clientSecret } = + integration.config; + + // Validate: OAuth requires both clientId and clientSecret + if ((clientId && !clientSecret) || (clientSecret && !clientId)) { + throw new Error( + `Bitbucket Cloud integration has incomplete OAuth configuration. Both clientId and clientSecret are required.`, + ); + } if (username && !token && !appPassword) { throw new Error( @@ -91,7 +99,7 @@ export class BitbucketCloudUrlReader implements UrlReaderService { url, this.integration.config, ); - const requestOptions = getBitbucketCloudRequestOptions( + const requestOptions = await getBitbucketCloudRequestOptions( this.integration.config, ); @@ -149,7 +157,7 @@ export class BitbucketCloudUrlReader implements UrlReaderService { ); const archiveResponse = await fetch( downloadUrl, - getBitbucketCloudRequestOptions(this.integration.config), + await getBitbucketCloudRequestOptions(this.integration.config), ); if (!archiveResponse.ok) { const message = `Failed to read tree from ${url}, ${archiveResponse.status} ${archiveResponse.statusText}`; @@ -250,7 +258,7 @@ export class BitbucketCloudUrlReader implements UrlReaderService { const commitsResponse = await fetch( commitsApiUrl, - getBitbucketCloudRequestOptions(this.integration.config), + await getBitbucketCloudRequestOptions(this.integration.config), ); if (!commitsResponse.ok) { const message = `Failed to retrieve commits from ${commitsApiUrl}, ${commitsResponse.status} ${commitsResponse.statusText}`; diff --git a/packages/backend-dev-utils/CHANGELOG.md b/packages/backend-dev-utils/CHANGELOG.md index 81686fb493..d5884588fb 100644 --- a/packages/backend-dev-utils/CHANGELOG.md +++ b/packages/backend-dev-utils/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/backend-dev-utils +## 0.1.6 + +### Patch Changes + +- 2bae83a: Internal update for Node.js v24 support. + +## 0.1.6-next.0 + +### Patch Changes + +- 2bae83a: Internal update for Node.js v24 support. + ## 0.1.5 ### Patch Changes diff --git a/packages/backend-dev-utils/package.json b/packages/backend-dev-utils/package.json index 4d22c5010f..ba46f4b36e 100644 --- a/packages/backend-dev-utils/package.json +++ b/packages/backend-dev-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/backend-dev-utils", - "version": "0.1.5", + "version": "0.1.6", "backstage": { "role": "node-library" }, diff --git a/packages/backend-dynamic-feature-service/CHANGELOG.md b/packages/backend-dynamic-feature-service/CHANGELOG.md index 25ae340cbf..36d55fd8c2 100644 --- a/packages/backend-dynamic-feature-service/CHANGELOG.md +++ b/packages/backend-dynamic-feature-service/CHANGELOG.md @@ -1,5 +1,77 @@ # @backstage/backend-dynamic-feature-service +## 0.7.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-openapi-utils@0.6.5-next.0 + - @backstage/backend-defaults@0.14.1-next.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/cli-common@0.1.16 + - @backstage/cli-node@0.2.16 + - @backstage/config@1.3.6 + - @backstage/config-loader@1.10.7 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-app-node@0.1.40 + - @backstage/plugin-auth-node@0.6.10 + - @backstage/plugin-catalog-backend@3.3.1-next.0 + - @backstage/plugin-events-backend@0.5.10-next.0 + - @backstage/plugin-events-node@0.4.18 + - @backstage/plugin-permission-common@0.9.3 + - @backstage/plugin-permission-node@0.10.7 + - @backstage/plugin-scaffolder-node@0.12.2 + - @backstage/plugin-search-backend-node@1.4.0 + - @backstage/plugin-search-common@1.2.21 + +## 0.7.7 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/cli-node@0.2.16 + - @backstage/plugin-search-backend-node@1.4.0 + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-defaults@0.14.0 + - @backstage/backend-openapi-utils@0.6.4 + - @backstage/plugin-app-node@0.1.40 + - @backstage/plugin-catalog-backend@3.3.0 + - @backstage/plugin-events-backend@0.5.9 + - @backstage/plugin-events-node@0.4.18 + - @backstage/plugin-permission-node@0.10.7 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/cli-common@0.1.16 + - @backstage/config-loader@1.10.7 + - @backstage/plugin-scaffolder-node@0.12.2 + +## 0.7.7-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-defaults@0.14.0-next.1 + - @backstage/backend-openapi-utils@0.6.4-next.1 + - @backstage/plugin-app-node@0.1.40-next.1 + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/plugin-catalog-backend@3.2.1-next.1 + - @backstage/plugin-events-backend@0.5.9-next.1 + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/plugin-permission-node@0.10.7-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config-loader@1.10.7-next.1 + - @backstage/cli-common@0.1.16-next.2 + - @backstage/cli-node@0.2.16-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-permission-common@0.9.3 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + - @backstage/plugin-search-backend-node@1.4.0-next.1 + - @backstage/plugin-search-common@1.2.21 + ## 0.7.7-next.0 ### Patch Changes diff --git a/packages/backend-dynamic-feature-service/package.json b/packages/backend-dynamic-feature-service/package.json index b2f2a5902f..e558403e0e 100644 --- a/packages/backend-dynamic-feature-service/package.json +++ b/packages/backend-dynamic-feature-service/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/backend-dynamic-feature-service", - "version": "0.7.7-next.0", + "version": "0.7.8-next.0", "description": "Backstage dynamic feature service", "backstage": { "role": "node-library" diff --git a/packages/backend-openapi-utils/CHANGELOG.md b/packages/backend-openapi-utils/CHANGELOG.md index 7f3a9328ae..f90fecb9cc 100644 --- a/packages/backend-openapi-utils/CHANGELOG.md +++ b/packages/backend-openapi-utils/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/backend-openapi-utils +## 0.6.5-next.0 + +### Patch Changes + +- 6678b78: Internal update to use native feature from our request validation library for handling base path determination. +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + +## 0.6.4 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + +## 0.6.4-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + ## 0.6.4-next.0 ### Patch Changes diff --git a/packages/backend-openapi-utils/package.json b/packages/backend-openapi-utils/package.json index 3c4908de61..5efffd1c55 100644 --- a/packages/backend-openapi-utils/package.json +++ b/packages/backend-openapi-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/backend-openapi-utils", - "version": "0.6.4-next.0", + "version": "0.6.5-next.0", "description": "OpenAPI typescript support.", "backstage": { "role": "node-library" diff --git a/packages/backend-openapi-utils/src/stub.ts b/packages/backend-openapi-utils/src/stub.ts index 8ab00c4df4..717e2ae19b 100644 --- a/packages/backend-openapi-utils/src/stub.ts +++ b/packages/backend-openapi-utils/src/stub.ts @@ -31,13 +31,6 @@ import { middleware as OpenApiValidator } from 'express-openapi-validator'; import { OPENAPI_SPEC_ROUTE } from './constants'; import { isErrorResult, merge } from 'openapi-merge'; -type PropertyOverrideRequest = Request & { - [key: symbol]: string; -}; - -const baseUrlSymbol = Symbol(); -const originalUrlSymbol = Symbol(); - function validatorErrorTransformer(): ErrorRequestHandler { return (error: Error, _: Request, _2: Response, next: NextFunction) => { next(new InputError(error.message)); @@ -75,30 +68,6 @@ function createRouterWithValidation( const router = PromiseRouter(); router.use(options?.middleware || getDefaultRouterMiddleware()); - /** - * Middleware to setup the routing for OpenApiValidator. OpenApiValidator expects `req.originalUrl` - * and `req.baseUrl` to be the full path. We adjust them here to basically be nothing and then - * revive the old values in the last function in this method. We could instead update `req.path` - * but that might affect the routing and I'd rather not. - * - * TODO: I opened https://github.com/cdimascio/express-openapi-validator/issues/843 - * to track this on the middleware side, but there was a similar ticket, https://github.com/cdimascio/express-openapi-validator/issues/113 - * that has had minimal activity. If that changes, update this to use a new option on their side. - */ - router.use((req: Request, _, next) => { - /** - * Express typings are weird. They don't recognize PropertyOverrideRequest as a valid - * Request child and try to overload as PathParams. Just cast it here, since we know - * what we're doing. - */ - const customRequest = req as PropertyOverrideRequest; - customRequest[baseUrlSymbol] = customRequest.baseUrl; - customRequest.baseUrl = ''; - customRequest[originalUrlSymbol] = customRequest.originalUrl; - customRequest.originalUrl = customRequest.url; - next(); - }); - // TODO: Handle errors by converting from OpenApiValidator errors to known @backstage/errors errors. router.use( OpenApiValidator({ @@ -106,6 +75,7 @@ function createRouterWithValidation( coerceTypes: false, allowUnknownQueryParameters: false, }, + useRequestUrl: true, ignoreUndocumented: true, validateResponses: false, ...options?.validatorOptions, @@ -113,19 +83,6 @@ function createRouterWithValidation( }), ); - /** - * Revert `req.baseUrl` and `req.originalUrl` changes. This ensures that any further usage - * of these variables will be unchanged. - */ - router.use((req: Request, _, next) => { - const customRequest = req as PropertyOverrideRequest; - customRequest.baseUrl = customRequest[baseUrlSymbol]; - customRequest.originalUrl = customRequest[originalUrlSymbol]; - delete customRequest[baseUrlSymbol]; - delete customRequest[originalUrlSymbol]; - next(); - }); - // Any errors from the middleware get through here. router.use(validatorErrorTransformer()); diff --git a/packages/backend-plugin-api/CHANGELOG.md b/packages/backend-plugin-api/CHANGELOG.md index 617012d22b..83d63fa97a 100644 --- a/packages/backend-plugin-api/CHANGELOG.md +++ b/packages/backend-plugin-api/CHANGELOG.md @@ -1,5 +1,36 @@ # @backstage/backend-plugin-api +## 1.6.0 + +### Minor Changes + +- 2a0c4b0: Adds a new experimental `RootSystemMetadataService` for tracking the collection of Backstage instances that may be deployed at any one time. It currently offers a single API, `getInstalledPlugins` that returns a list of installed plugins based on config you have set up in `discovery.endpoints` as well as the plugins installed on the instance you're calling the API with. It does not handle wildcard values or fallback values. The intention is for this plugin to provide plugin authors with a simple interface to fetch a trustworthy list of all installed plugins. + +### Patch Changes + +- d9759a1: **BREAKING ALPHA**: The old `instanceMetadataService` has been removed from alpha. Please switch over to using the stable `coreServices.rootInstanceMetadata` and related types instead, available from `@backstage/backend-plugin-api`. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/plugin-permission-node@0.10.7 + - @backstage/cli-common@0.1.16 + +## 1.6.0-next.1 + +### Minor Changes + +- 2a0c4b0: Adds a new experimental `RootSystemMetadataService` for tracking the collection of Backstage instances that may be deployed at any one time. It currently offers a single API, `getInstalledPlugins` that returns a list of installed plugins based on config you have set up in `discovery.endpoints` as well as the plugins installed on the instance you're calling the API with. It does not handle wildcard values or fallback values. The intention is for this plugin to provide plugin authors with a simple interface to fetch a trustworthy list of all installed plugins. + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/plugin-permission-node@0.10.7-next.1 + - @backstage/cli-common@0.1.16-next.2 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-permission-common@0.9.3 + ## 1.5.1-next.0 ### Patch Changes diff --git a/packages/backend-plugin-api/package.json b/packages/backend-plugin-api/package.json index be377d1d12..4867fcd0a4 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": "1.5.1-next.0", + "version": "1.6.0", "description": "Core API used by Backstage backend plugins", "backstage": { "role": "node-library" diff --git a/packages/backend-test-utils/CHANGELOG.md b/packages/backend-test-utils/CHANGELOG.md index d8ee338822..ca456b8491 100644 --- a/packages/backend-test-utils/CHANGELOG.md +++ b/packages/backend-test-utils/CHANGELOG.md @@ -1,5 +1,52 @@ # @backstage/backend-test-utils +## 1.10.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.14.1-next.0 + - @backstage/backend-app-api@1.4.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-auth-node@0.6.10 + - @backstage/plugin-events-node@0.4.18 + - @backstage/plugin-permission-common@0.9.3 + +## 1.10.2 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- 8be23a4: Switched `textextensions` dependency for `text-extensions`. +- 5a737e1: Fix PostgreSQL 18 `TestDatabases` by pinning the data directory +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-defaults@0.14.0 + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-app-api@1.4.0 + - @backstage/backend-plugin-api@1.6.0 + +## 1.10.2-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- 8be23a4: Switched `textextensions` dependency for `text-extensions`. +- 5a737e1: Fix PostgreSQL 18 `TestDatabases` by pinning the data directory +- Updated dependencies + - @backstage/backend-defaults@0.14.0-next.1 + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/backend-app-api@1.4.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-permission-common@0.9.3 + ## 1.10.1-next.0 ### Patch Changes diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index cd4f68ead0..1f6df8457d 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": "1.10.1-next.0", + "version": "1.10.3-next.0", "description": "Test helpers library for Backstage backends", "backstage": { "role": "node-library" diff --git a/packages/backend/CHANGELOG.md b/packages/backend/CHANGELOG.md index 622c2329b2..6f44aa4093 100644 --- a/packages/backend/CHANGELOG.md +++ b/packages/backend/CHANGELOG.md @@ -1,5 +1,129 @@ # example-backend +## 0.0.46-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.14.1-next.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/catalog-model@1.7.6 + - @backstage/plugin-app-backend@0.5.9 + - @backstage/plugin-auth-backend@0.25.7 + - @backstage/plugin-auth-backend-module-github-provider@0.4.0 + - @backstage/plugin-auth-backend-module-guest-provider@0.2.15 + - @backstage/plugin-auth-backend-module-openshift-provider@0.1.3 + - @backstage/plugin-auth-node@0.6.10 + - @backstage/plugin-catalog-backend@3.3.1-next.0 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.10-next.0 + - @backstage/plugin-catalog-backend-module-openapi@0.2.17 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.15 + - @backstage/plugin-catalog-backend-module-unprocessed@0.6.7 + - @backstage/plugin-devtools-backend@0.5.13-next.0 + - @backstage/plugin-events-backend@0.5.10-next.0 + - @backstage/plugin-events-backend-module-google-pubsub@0.1.7 + - @backstage/plugin-kubernetes-backend@0.21.0 + - @backstage/plugin-mcp-actions-backend@0.1.7-next.0 + - @backstage/plugin-notifications-backend@0.6.1 + - @backstage/plugin-permission-backend@0.7.7 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.2.15 + - @backstage/plugin-permission-common@0.9.3 + - @backstage/plugin-permission-node@0.10.7 + - @backstage/plugin-proxy-backend@0.6.9 + - @backstage/plugin-scaffolder-backend@3.1.1-next.0 + - @backstage/plugin-scaffolder-backend-module-github@0.9.3 + - @backstage/plugin-scaffolder-backend-module-notifications@0.1.17 + - @backstage/plugin-search-backend@2.0.10-next.0 + - @backstage/plugin-search-backend-module-catalog@0.3.11 + - @backstage/plugin-search-backend-module-elasticsearch@1.7.9 + - @backstage/plugin-search-backend-module-explore@0.3.10 + - @backstage/plugin-search-backend-module-techdocs@0.4.9 + - @backstage/plugin-search-backend-node@1.4.0 + - @backstage/plugin-signals-backend@0.3.11 + - @backstage/plugin-techdocs-backend@2.1.4-next.0 + +## 0.0.45 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-mcp-actions-backend@0.1.6 + - @backstage/plugin-scaffolder-backend@3.1.0 + - @backstage/plugin-search-backend-node@1.4.0 + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-defaults@0.14.0 + - @backstage/plugin-app-backend@0.5.9 + - @backstage/plugin-auth-backend-module-guest-provider@0.2.15 + - @backstage/plugin-auth-backend-module-openshift-provider@0.1.3 + - @backstage/plugin-auth-backend@0.25.7 + - @backstage/plugin-catalog-backend@3.3.0 + - @backstage/plugin-devtools-backend@0.5.12 + - @backstage/plugin-events-backend@0.5.9 + - @backstage/plugin-kubernetes-backend@0.21.0 + - @backstage/plugin-notifications-backend@0.6.1 + - @backstage/plugin-permission-backend@0.7.7 + - @backstage/plugin-permission-node@0.10.7 + - @backstage/plugin-proxy-backend@0.6.9 + - @backstage/plugin-search-backend@2.0.9 + - @backstage/plugin-signals-backend@0.3.11 + - @backstage/plugin-techdocs-backend@2.1.3 + - @backstage/plugin-auth-backend-module-github-provider@0.4.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-backend-module-github@0.9.3 + - @backstage/plugin-search-backend-module-explore@0.3.10 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.9 + - @backstage/plugin-catalog-backend-module-openapi@0.2.17 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.15 + - @backstage/plugin-catalog-backend-module-unprocessed@0.6.7 + - @backstage/plugin-events-backend-module-google-pubsub@0.1.7 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.2.15 + - @backstage/plugin-scaffolder-backend-module-notifications@0.1.17 + - @backstage/plugin-search-backend-module-catalog@0.3.11 + - @backstage/plugin-search-backend-module-elasticsearch@1.7.9 + - @backstage/plugin-search-backend-module-techdocs@0.4.9 + +## 0.0.45-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-mcp-actions-backend@0.1.6-next.1 + - @backstage/backend-defaults@0.14.0-next.1 + - @backstage/plugin-app-backend@0.5.9-next.1 + - @backstage/plugin-auth-backend-module-guest-provider@0.2.15-next.1 + - @backstage/plugin-auth-backend-module-openshift-provider@0.1.3-next.1 + - @backstage/plugin-auth-backend@0.25.7-next.1 + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/plugin-catalog-backend@3.2.1-next.1 + - @backstage/plugin-devtools-backend@0.5.12-next.1 + - @backstage/plugin-events-backend@0.5.9-next.1 + - @backstage/plugin-kubernetes-backend@0.21.0-next.2 + - @backstage/plugin-notifications-backend@0.6.1-next.1 + - @backstage/plugin-permission-backend@0.7.7-next.1 + - @backstage/plugin-permission-node@0.10.7-next.1 + - @backstage/plugin-proxy-backend@0.6.9-next.1 + - @backstage/plugin-scaffolder-backend@3.1.0-next.1 + - @backstage/plugin-search-backend@2.0.9-next.1 + - @backstage/plugin-signals-backend@0.3.11-next.1 + - @backstage/plugin-techdocs-backend@2.1.3-next.2 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/plugin-search-backend-module-explore@0.3.10-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/plugin-auth-backend-module-github-provider@0.3.10-next.1 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.9-next.1 + - @backstage/plugin-catalog-backend-module-openapi@0.2.17-next.1 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.15-next.1 + - @backstage/plugin-catalog-backend-module-unprocessed@0.6.7-next.2 + - @backstage/plugin-events-backend-module-google-pubsub@0.1.7-next.1 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.2.15-next.1 + - @backstage/plugin-permission-common@0.9.3 + - @backstage/plugin-scaffolder-backend-module-github@0.9.3-next.1 + - @backstage/plugin-scaffolder-backend-module-notifications@0.1.17-next.1 + - @backstage/plugin-search-backend-module-catalog@0.3.11-next.1 + - @backstage/plugin-search-backend-module-elasticsearch@1.7.9-next.1 + - @backstage/plugin-search-backend-module-techdocs@0.4.9-next.1 + - @backstage/plugin-search-backend-node@1.4.0-next.1 + ## 0.0.45-next.0 ### Patch Changes diff --git a/packages/backend/package.json b/packages/backend/package.json index 1d0040389c..762019d2f4 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,6 @@ { "name": "example-backend", - "version": "0.0.45-next.0", + "version": "0.0.46-next.0", "backstage": { "role": "backend" }, diff --git a/packages/cli-common/CHANGELOG.md b/packages/cli-common/CHANGELOG.md index d40c0629f4..a8e4872744 100644 --- a/packages/cli-common/CHANGELOG.md +++ b/packages/cli-common/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/cli-common +## 0.1.16 + +### Patch Changes + +- 5cfb2a4: Added new `run`, `runOutput`, and `runCheck` utilities to help run child processes in a safe and portable way. +- c8c2329: Add proxy configuration from env-vars to create-app tasks +- 2bae83a: Bumped dev dependencies `@types/node` + +## 0.1.16-next.2 + +### Patch Changes + +- 2bae83a: Bumped dev dependencies `@types/node` +- Updated dependencies + - @backstage/errors@1.2.7 + ## 0.1.16-next.1 ### Patch Changes diff --git a/packages/cli-common/package.json b/packages/cli-common/package.json index ea26ee09e6..0ab0a9f1fd 100644 --- a/packages/cli-common/package.json +++ b/packages/cli-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/cli-common", - "version": "0.1.16-next.1", + "version": "0.1.16", "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 4c4005c0c9..bdacd69297 100644 --- a/packages/cli-node/CHANGELOG.md +++ b/packages/cli-node/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/cli-node +## 0.2.16 + +### Patch Changes + +- 4e8c726: Updated to use new utilities from `@backstage/cli-common`. +- Updated dependencies + - @backstage/cli-common@0.1.16 + ## 0.2.16-next.1 ### Patch Changes diff --git a/packages/cli-node/package.json b/packages/cli-node/package.json index dcedc6b76c..52242bdd48 100644 --- a/packages/cli-node/package.json +++ b/packages/cli-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/cli-node", - "version": "0.2.16-next.1", + "version": "0.2.16", "description": "Node.js library for Backstage CLIs", "backstage": { "role": "node-library" diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 9cee8632cd..28bf3b98ad 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,111 @@ # @backstage/cli +## 0.35.2-next.0 + +### Patch Changes + +- 320c6a9: Bump `@swc/core` to support `ES2023` and `ES2024` +- 9ee5996: Bump minimum required `@swc/core` to avoid transpilation bug +- Updated dependencies + - @backstage/catalog-model@1.7.6 + - @backstage/cli-common@0.1.16 + - @backstage/cli-node@0.2.16 + - @backstage/config@1.3.6 + - @backstage/config-loader@1.10.7 + - @backstage/errors@1.2.7 + - @backstage/eslint-plugin@0.2.0 + - @backstage/integration@1.19.0 + - @backstage/release-manifests@0.0.13 + - @backstage/types@1.2.2 + +## 0.35.0 + +### Minor Changes + +- f6f22a9: Provide `--no-node-snapshot` by default when running the `package start` or `package test`. You can disable this behavior by providing `NODE_OPTIONS='--node-snapshot'`. +- f8dff94: Switched the default module resolution to `bundler` and the `module` setting to `ES2020`. + + You may need to bump some dependencies as part of this change and fix imports in code. The most common source of this is that type checking will now consider the `exports` field in `package.json` when resolving imports. This in turn can break older versions of packages that had incompatible `exports` fields. Generally these issues will have already been fixed in the upstream packages. + + You might be tempted to use `--skipLibCheck` to hide issues due to this change, but it will weaken the type safety of your project. If you run into a large number of issues and want to keep the old behavior, you can reset the `moduleResolution` and `module` settings your own `tsconfig.json` file to `node` and `ESNext` respectively. But keep in mind that the `node` option will be removed in future versions of TypeScript. + + A future version of Backstage will make these new settings mandatory, as we move to rely on the `exports` field for type resolution in packages, rather than the `typesVersions` field. + +- cd0b8a1: **BREAKING**: `jest` is now a peer dependency. If you run tests using Backstage CLI, you must add Jest and its environment dependencies as `devDependencies` in your project. + + You can choose to install either Jest 29 or Jest 30. The built-in Jest version before this change was Jest 29, however, we recommend that you switch to Jest 30. Upgrading will solve the `Could not parse CSS stylesheet` errors, allow you to use MSW v2 in web packages, and ensure that you remain compatible with future versions of the Backstage CLI. Support for Jest 29 is temporary, with the purpose of allowing you to upgrade at your own pace, but it will eventually be removed. + + - **Jest 29**: Install `jest@^29` and `jest-environment-jsdom@^29`. No migration needed, but you may see `Could not parse CSS stylesheet` warnings/errors when testing components from `@backstage/ui` or other packages using CSS `@layer` declarations. + - **Jest 30**: Install `jest@^30`, `@jest/environment-jsdom-abstract@^30`, and `jsdom@^27`. Fixes the stylesheet parsing warnings/errors, but requires migration steps. + + See the [Jest 30 migration guide](https://backstage.io/docs/tutorials/jest30-migration) for detailed migration instructions. + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- e7db290: Add missing peer/dev dependencies to the frontend plugin template. + + `react-dom` was not declared as a peer dependency, causing module resolution + errors when generating plugins outside a Backstage monorepo. This adds + `react-dom` to `peerDependencies` (for consuming apps) and `devDependencies` + (for local development). `react-router-dom` is also added to `peerDependencies` (for consuming apps) and `devDependencies` + to support routing during plugin development. + + Fixes: + + - Module not found: Can't resolve 'react-dom' + - Module not found: Can't resolve 'react-router-dom' + +- 1226647: Updated dependency `esbuild` to `^0.27.0`. +- f89a074: Updated dependency `@pmmmwh/react-refresh-webpack-plugin` to `^0.6.0`. +- 2b81751: Updated dependency `webpack` to `~5.103.0`. +- fafd9e1: Fixed internal usage of `yargs`. +- c8c2329: Add proxy configuration from env-vars to create-app tasks +- 2bae83a: Switched compilation target to ES2022 in order to match the new set of supported Node.js versions, which are 22 and 24. + + The TypeScript compilation target has been set to ES2022, because setting it to a higher target will break projects on older TypeScript versions. If you use a newer TypeScript version in your own project, you can bump `compilerOptions.target` to ES2023 or ES2024 in your own `tsconfig.json` file. + +- 7fbac5c: Updated to use new utilities from `@backstage/cli-common`. +- 2bae83a: Bumped dev dependencies `@types/node` +- Updated dependencies + - @backstage/cli-node@0.2.16 + - @backstage/integration@1.19.0 + - @backstage/cli-common@0.1.16 + - @backstage/config-loader@1.10.7 + +## 0.35.0-next.2 + +### Minor Changes + +- f8dff94: Switched the default module resolution to `bundler` and the `module` setting to `ES2020`. + + You may need to bump some dependencies as part of this change and fix imports in code. The most common source of this is that type checking will now consider the `exports` field in `package.json` when resolving imports. This in turn can break older versions of packages that had incompatible `exports` fields. Generally these issues will have already been fixed in the upstream packages. + + You might be tempted to use `--skipLibCheck` to hide issues due to this change, but it will weaken the type safety of your project. If you run into a large number of issues and want to keep the old behavior, you can reset the `moduleResolution` and `module` settings your own `tsconfig.json` file to `node` and `ESNext` respectively. But keep in mind that the `node` option will be removed in future versions of TypeScript. + + A future version of Backstage will make these new settings mandatory, as we move to rely on the `exports` field for type resolution in packages, rather than the `typesVersions` field. + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- 1226647: Updated dependency `esbuild` to `^0.27.0`. +- f89a074: Updated dependency `@pmmmwh/react-refresh-webpack-plugin` to `^0.6.0`. +- 2b81751: Updated dependency `webpack` to `~5.103.0`. +- fafd9e1: Fixed internal usage of `yargs`. +- 2bae83a: Switched ECMAScript version to ES2023. +- 2bae83a: Bumped dev dependencies `@types/node` +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/config-loader@1.10.7-next.1 + - @backstage/cli-common@0.1.16-next.2 + - @backstage/catalog-model@1.7.6 + - @backstage/cli-node@0.2.16-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/eslint-plugin@0.2.0 + - @backstage/release-manifests@0.0.13 + - @backstage/types@1.2.2 + ## 0.34.6-next.1 ### Patch Changes diff --git a/packages/cli/cli-report.md b/packages/cli/cli-report.md index a8df5242ad..26bd89e909 100644 --- a/packages/cli/cli-report.md +++ b/packages/cli/cli-report.md @@ -324,7 +324,7 @@ Options: ### `backstage-cli package test` ``` -Usage: backstage-cli [--config=] [TestPathPattern] +Usage: backstage-cli [--config=] [TestPathPatterns] Options: --all @@ -349,7 +349,6 @@ Options: --debug --detectLeaks --detectOpenHandles - --env --errorOnDeprecated --filter --findRelatedTests @@ -359,7 +358,6 @@ Options: --globals --haste --ignoreProjects - --init --injectGlobals --json --lastCommit @@ -400,13 +398,13 @@ Options: --silent --skipFilter --snapshotSerializers - --testEnvironment + --testEnvironment, --env --testEnvironmentOptions --testFailureExitCode --testLocationInResults --testMatch --testPathIgnorePatterns - --testPathPattern + --testPathPatterns --testRegex --testResultsProcessor --testRunner @@ -418,6 +416,7 @@ Options: --useStderr --verbose --version + --waitForUnhandledRejections --watch --watchAll --watchPathIgnorePatterns diff --git a/packages/cli/config/getJestEnvironment.js b/packages/cli/config/getJestEnvironment.js new file mode 100644 index 0000000000..aac2f79021 --- /dev/null +++ b/packages/cli/config/getJestEnvironment.js @@ -0,0 +1,49 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function getJestMajorVersion() { + const jestVersion = require('jest/package.json').version; + const majorVersion = parseInt(jestVersion.split('.')[0], 10); + return majorVersion; +} + +function getJestEnvironment() { + const majorVersion = getJestMajorVersion(); + + if (majorVersion >= 30) { + try { + require.resolve('@jest/environment-jsdom-abstract'); + require.resolve('jsdom'); + } catch { + throw new Error( + 'Jest 30+ requires @jest/environment-jsdom-abstract and jsdom. ' + + 'Please install them as dev dependencies.', + ); + } + return require.resolve('./jest-environment-jsdom'); + } + try { + require.resolve('jest-environment-jsdom'); + } catch { + throw new Error( + 'Jest 29 requires jest-environment-jsdom. ' + + 'Please install it as a dev dependency.', + ); + } + return require.resolve('jest-environment-jsdom'); +} + +module.exports = { getJestMajorVersion, getJestEnvironment }; diff --git a/packages/cli/config/jest-environment-jsdom/index.js b/packages/cli/config/jest-environment-jsdom/index.js new file mode 100644 index 0000000000..9d8b76eaf5 --- /dev/null +++ b/packages/cli/config/jest-environment-jsdom/index.js @@ -0,0 +1,61 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const JSDOMEnvironment = require('@jest/environment-jsdom-abstract').default; +const jsdom = require('jsdom'); + +/** + * A custom JSDOM environment that extends the abstract base and applies + * fixes for Web API globals that are missing or incorrectly implemented + * in JSDOM. + * + * Based on https://github.com/mswjs/jest-fixed-jsdom + */ +class FixedJSDOMEnvironment extends JSDOMEnvironment { + constructor(config, context) { + super(config, context, jsdom); + + // Fix Web API globals that JSDOM doesn't properly expose + this.global.TextDecoder = TextDecoder; + this.global.TextEncoder = TextEncoder; + this.global.TextDecoderStream = TextDecoderStream; + this.global.TextEncoderStream = TextEncoderStream; + this.global.ReadableStream = ReadableStream; + + this.global.Blob = Blob; + this.global.Headers = Headers; + this.global.FormData = FormData; + this.global.Request = Request; + this.global.Response = Response; + this.global.fetch = fetch; + this.global.AbortController = AbortController; + this.global.AbortSignal = AbortSignal; + this.global.structuredClone = structuredClone; + this.global.URL = URL; + this.global.URLSearchParams = URLSearchParams; + + this.global.BroadcastChannel = BroadcastChannel; + this.global.TransformStream = TransformStream; + this.global.WritableStream = WritableStream; + + // Needed to ensure `e instanceof Error` works as expected with errors thrown from + // any of the native APIs above. Without this, the JSDOM `Error` is what the test + // code will use for comparison with `e`, which fails the instanceof check. + this.global.Error = Error; + } +} + +module.exports = FixedJSDOMEnvironment; diff --git a/packages/cli/config/jest.js b/packages/cli/config/jest.js index f011d14b19..94e5b9c4a8 100644 --- a/packages/cli/config/jest.js +++ b/packages/cli/config/jest.js @@ -20,6 +20,10 @@ const crypto = require('crypto'); const glob = require('util').promisify(require('glob')); const { version } = require('../package.json'); const paths = require('@backstage/cli-common').findPaths(process.cwd()); +const { + getJestEnvironment, + getJestMajorVersion, +} = require('./getJestEnvironment'); const SRC_EXTS = ['ts', 'js', 'tsx', 'jsx', 'mts', 'cts', 'mjs', 'cjs']; @@ -211,7 +215,7 @@ function getRoleConfig(role, pkgJson) { }; if (FRONTEND_ROLES.includes(role)) { return { - testEnvironment: require.resolve('jest-environment-jsdom'), + testEnvironment: getJestEnvironment(), // The caching module loader is only used to speed up frontend tests, // as it breaks real dynamic imports of ESM modules. runtime: envOptions.oldTests @@ -279,7 +283,10 @@ async function getProjectConfig(targetPath, extraConfig, extraOptions) { ); } - if (options.testEnvironment === require.resolve('jest-environment-jsdom')) { + if ( + options.testEnvironment === getJestEnvironment() && + getJestMajorVersion() < 30 // Only needed when not running the custom env for Jest 30+ + ) { // FIXME https://github.com/jsdom/jsdom/issues/1724 options.setupFilesAfterEnv.unshift(require.resolve('cross-fetch/polyfill')); } diff --git a/packages/cli/config/jestCachingModuleLoader.js b/packages/cli/config/jestCachingModuleLoader.js index a3fdf106e9..5652ff67e7 100644 --- a/packages/cli/config/jestCachingModuleLoader.js +++ b/packages/cli/config/jestCachingModuleLoader.js @@ -14,6 +14,8 @@ * limitations under the License. */ +// 'jest-runtime' is included with jest and should be kept in sync with the installed jest version +// eslint-disable-next-line @backstage/no-undeclared-imports const { default: JestRuntime } = require('jest-runtime'); module.exports = class CachingJestRuntime extends JestRuntime { diff --git a/packages/cli/config/jestRejectNetworkRequests.js b/packages/cli/config/jestRejectNetworkRequests.js index de6b486809..ef577b3a22 100644 --- a/packages/cli/config/jestRejectNetworkRequests.js +++ b/packages/cli/config/jestRejectNetworkRequests.js @@ -22,7 +22,7 @@ const errorMessage = 'Network requests are not allowed in tests'; const origHttpAgent = http.globalAgent; const origHttpsAgent = https.globalAgent; const origFetch = global.fetch; -const origXMLHttpRequest = global.fetch; +const origXMLHttpRequest = global.XMLHttpRequest; http.globalAgent = new http.Agent({ lookup() { @@ -36,10 +36,21 @@ https.globalAgent = new https.Agent({ }, }); +const BLOCKING_FETCH_SYMBOL = Symbol.for( + 'backstage.jestRejectNetworkRequests.blockingFetch', +); + if (global.fetch) { - global.fetch = async () => { - throw new Error(errorMessage); + const blockingFetch = async (input, init) => { + // If global.fetch still has our marker, block the request + if (global.fetch[BLOCKING_FETCH_SYMBOL]) { + throw new Error(errorMessage); + } + // MSW (or something else) wrapped us - pass through + return origFetch(input, init); }; + blockingFetch[BLOCKING_FETCH_SYMBOL] = true; + global.fetch = blockingFetch; } if (global.XMLHttpRequest) { diff --git a/packages/cli/config/tsconfig.json b/packages/cli/config/tsconfig.json index 7648e0238a..40a572da4d 100644 --- a/packages/cli/config/tsconfig.json +++ b/packages/cli/config/tsconfig.json @@ -33,7 +33,7 @@ "strictNullChecks": true, "strictPropertyInitialization": true, "stripInternal": true, - "target": "ES2023", + "target": "ES2022", "types": ["node", "jest", "webpack-env"], "useDefineForClassFields": true } diff --git a/packages/cli/package.json b/packages/cli/package.json index be94e4e817..7f340d3000 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/cli", - "version": "0.34.6-next.1", + "version": "0.35.2-next.0", "description": "CLI for developing Backstage plugins and apps", "backstage": { "role": "cli" @@ -70,10 +70,9 @@ "@spotify/eslint-config-base": "^15.0.0", "@spotify/eslint-config-react": "^15.0.0", "@spotify/eslint-config-typescript": "^15.0.0", - "@swc/core": "^1.3.46", - "@swc/helpers": "^0.5.0", - "@swc/jest": "^0.2.22", - "@types/jest": "^29.5.11", + "@swc/core": "^1.15.6", + "@swc/helpers": "^0.5.17", + "@swc/jest": "^0.2.39", "@types/webpack-env": "^1.15.2", "@typescript-eslint/eslint-plugin": "^8.17.0", "@typescript-eslint/parser": "^8.16.0", @@ -109,11 +108,7 @@ "handlebars": "^4.7.3", "html-webpack-plugin": "^5.6.3", "inquirer": "^8.2.0", - "jest": "^29.7.0", - "jest-cli": "^29.7.0", "jest-css-modules": "^2.1.0", - "jest-environment-jsdom": "^29.0.2", - "jest-runtime": "^29.0.2", "json-schema": "^0.4.0", "lodash": "^4.17.21", "minimatch": "^9.0.0", @@ -167,6 +162,7 @@ "@backstage/plugin-scaffolder-node-test-utils": "workspace:^", "@backstage/test-utils": "workspace:^", "@backstage/theme": "workspace:^", + "@jest/environment-jsdom-abstract": "^30.0.0", "@pmmmwh/react-refresh-webpack-plugin": "^0.6.0", "@types/cross-spawn": "^6.0.2", "@types/ejs": "^3.1.3", @@ -174,6 +170,7 @@ "@types/fs-extra": "^11.0.0", "@types/http-proxy": "^1.17.4", "@types/inquirer": "^8.1.3", + "@types/jest": "^30.0.0", "@types/node": "^22.13.14", "@types/npm-packlist": "^3.0.0", "@types/recursive-readdir": "^2.2.0", @@ -188,6 +185,8 @@ "esbuild-loader": "^4.0.0", "eslint-webpack-plugin": "^4.2.0", "fork-ts-checker-webpack-plugin": "^9.0.0", + "jest": "^30.2.0", + "jsdom": "^27.1.0", "mini-css-extract-plugin": "^2.4.2", "msw": "^1.0.0", "nodemon": "^3.0.1", @@ -196,17 +195,24 @@ "webpack-dev-server": "^5.0.0" }, "peerDependencies": { + "@jest/environment-jsdom-abstract": "^30.0.0", "@module-federation/enhanced": "^0.9.0", "@pmmmwh/react-refresh-webpack-plugin": "^0.6.0", "esbuild-loader": "^4.0.0", "eslint-webpack-plugin": "^4.2.0", "fork-ts-checker-webpack-plugin": "^9.0.0", + "jest": "^29.0.0 || ^30.0.0", + "jest-environment-jsdom": "*", + "jsdom": "^27.1.0", "mini-css-extract-plugin": "^2.4.2", "terser-webpack-plugin": "^5.1.3", "webpack": "~5.103.0", "webpack-dev-server": "^5.0.0" }, "peerDependenciesMeta": { + "@jest/environment-jsdom-abstract": { + "optional": true + }, "@module-federation/enhanced": { "optional": true }, @@ -222,6 +228,12 @@ "fork-ts-checker-webpack-plugin": { "optional": true }, + "jest-environment-jsdom": { + "optional": true + }, + "jsdom": { + "optional": true + }, "mini-css-extract-plugin": { "optional": true }, diff --git a/packages/cli/src/modules/build/lib/runner/runBackend.test.ts b/packages/cli/src/modules/build/lib/runner/runBackend.test.ts new file mode 100644 index 0000000000..2b97ae352c --- /dev/null +++ b/packages/cli/src/modules/build/lib/runner/runBackend.test.ts @@ -0,0 +1,178 @@ +/* + * 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 { runBackend } from './runBackend'; +import spawn from 'cross-spawn'; + +// Mock external dependencies +jest.mock('chokidar', () => ({ + watch: jest.fn(() => ({ + on: jest.fn().mockReturnThis(), + add: jest.fn(), + })), +})); + +jest.mock('cross-spawn', () => + jest.fn(() => ({ + on: jest.fn().mockReturnThis(), + once: jest.fn().mockReturnThis(), + kill: jest.fn(), + killed: false, + exitCode: null, + pid: 12345, + })), +); + +jest.mock('../ipc', () => ({ + IpcServer: jest.fn().mockImplementation(() => ({ + addChild: jest.fn(), + })), + ServerDataStore: { + bind: jest.fn(), + }, +})); + +jest.mock('ctrlc-windows', () => ({ + ctrlc: jest.fn(), +})); + +describe('runBackend', () => { + let originalEnv: NodeJS.ProcessEnv; + let originalPlatform: string; + const mockSpawn = spawn as jest.MockedFunction; + + beforeEach(() => { + // Use fake timers to control debounce + jest.useFakeTimers(); + + // Save original environment + originalEnv = { ...process.env }; + process.env = { NODE_ENV: 'test' }; + originalPlatform = process.platform; + + // Mock process.stdin.on to prevent actual stdin reading + jest.spyOn(process.stdin, 'on').mockReturnValue(process.stdin); + + // Mock process.once to prevent actual signal handling + jest.spyOn(process, 'once').mockReturnValue(process); + }); + + afterEach(() => { + // Restore original environment + process.env = originalEnv; + Object.defineProperty(process, 'platform', { + value: originalPlatform, + }); + + jest.clearAllMocks(); + jest.useRealTimers(); + }); + + describe('--no-node-snapshot argument handling', () => { + it('should pass --no-node-snapshot when NODE_OPTIONS is not set', () => { + delete process.env.NODE_OPTIONS; + + runBackend({ + entry: 'src/index', + }); + + // Fast-forward past the debounce delay (100ms) + jest.advanceTimersByTime(100); + + expect(mockSpawn).toHaveBeenCalled(); + const spawnArgs = mockSpawn.mock.calls[0][1] as string[]; + expect(spawnArgs).toContain('--no-node-snapshot'); + }); + + it('should pass --no-node-snapshot when NODE_OPTIONS exists without --node-snapshot', () => { + process.env.NODE_OPTIONS = '--max-old-space-size=4096'; + + runBackend({ + entry: 'src/index', + }); + + // Fast-forward past the debounce delay (100ms) + jest.advanceTimersByTime(100); + + expect(mockSpawn).toHaveBeenCalled(); + const spawnArgs = mockSpawn.mock.calls[0][1] as string[]; + expect(spawnArgs).toContain('--no-node-snapshot'); + }); + + it('should not pass --no-node-snapshot when --node-snapshot already exists in NODE_OPTIONS', () => { + process.env.NODE_OPTIONS = '--node-snapshot --max-old-space-size=4096'; + + runBackend({ + entry: 'src/index', + }); + + // Fast-forward past the debounce delay (100ms) + jest.advanceTimersByTime(100); + + expect(mockSpawn).toHaveBeenCalled(); + const spawnArgs = mockSpawn.mock.calls[0][1] as string[]; + expect(spawnArgs).not.toContain('--no-node-snapshot'); + }); + + it('should not pass --no-node-snapshot when --node-snapshot exists in the middle of NODE_OPTIONS', () => { + process.env.NODE_OPTIONS = + '--max-old-space-size=4096 --node-snapshot --inspect'; + + runBackend({ + entry: 'src/index', + }); + + // Fast-forward past the debounce delay (100ms) + jest.advanceTimersByTime(100); + + expect(mockSpawn).toHaveBeenCalled(); + const spawnArgs = mockSpawn.mock.calls[0][1] as string[]; + expect(spawnArgs).not.toContain('--no-node-snapshot'); + }); + + it('should pass --no-node-snapshot even with trailing spaces in NODE_OPTIONS', () => { + process.env.NODE_OPTIONS = '--max-old-space-size=4096 '; + + runBackend({ + entry: 'src/index', + }); + + // Fast-forward past the debounce delay (100ms) + jest.advanceTimersByTime(100); + + expect(mockSpawn).toHaveBeenCalled(); + const spawnArgs = mockSpawn.mock.calls[0][1] as string[]; + expect(spawnArgs).toContain('--no-node-snapshot'); + }); + + it('should pass --no-node-snapshot alongside other option args like --inspect', () => { + delete process.env.NODE_OPTIONS; + + runBackend({ + entry: 'src/index', + inspectEnabled: true, + }); + + // Fast-forward past the debounce delay (100ms) + jest.advanceTimersByTime(100); + + expect(mockSpawn).toHaveBeenCalled(); + const spawnArgs = mockSpawn.mock.calls[0][1] as string[]; + expect(spawnArgs).toContain('--no-node-snapshot'); + expect(spawnArgs).toContain('--inspect'); + }); + }); +}); diff --git a/packages/cli/src/modules/build/lib/runner/runBackend.ts b/packages/cli/src/modules/build/lib/runner/runBackend.ts index 49dccf804f..0550ff2563 100644 --- a/packages/cli/src/modules/build/lib/runner/runBackend.ts +++ b/packages/cli/src/modules/build/lib/runner/runBackend.ts @@ -47,7 +47,7 @@ export type RunBackendOptions = { }; export async function runBackend(options: RunBackendOptions) { - const envEnv = process.env as { NODE_ENV: string }; + const envEnv = process.env as { NODE_ENV: string; NODE_OPTIONS?: string }; if (!envEnv.NODE_ENV) { envEnv.NODE_ENV = 'development'; } @@ -115,6 +115,12 @@ export async function runBackend(options: RunBackendOptions) { } } + // Unless the user explicitly toggles node-snapshot, default to provide --no-node-snapshot to reduce number of steps to run scaffolder + // on Node LTS. + if (!envEnv.NODE_OPTIONS?.includes('--node-snapshot')) { + optionArgs.push('--no-node-snapshot'); + } + const userArgs = process.argv .slice(['node', 'backstage-cli', 'package', 'start'].length) .filter(arg => !optionArgs.includes(arg)); diff --git a/packages/cli/src/modules/test/commands/package/test.ts b/packages/cli/src/modules/test/commands/package/test.ts index 1ecf5b395e..992697d19c 100644 --- a/packages/cli/src/modules/test/commands/package/test.ts +++ b/packages/cli/src/modules/test/commands/package/test.ts @@ -78,10 +78,36 @@ export default async (_opts: OptionValues, cmd: Command) => { process.env.TZ = 'UTC'; } + // Unless the user explicitly toggles node-snapshot, default to provide --no-node-snapshot to reduce number of steps to run scaffolder + // on Node LTS. + if (!process.env.NODE_OPTIONS?.includes('--node-snapshot')) { + process.env.NODE_OPTIONS = `${ + process.env.NODE_OPTIONS ? `${process.env.NODE_OPTIONS} ` : '' + }--no-node-snapshot`; + } + // This ensures that the process doesn't exit too early before stdout is flushed if (args.includes('--help')) { (process.stdout as any)._handle.setBlocking(true); } + // Because of the ongoing migration to v30 of jest, jest is no longer hard-depended to allow + // opt-in migration. Users instead need to add jest as a devDependency themselves and specify + // the version they want. This prints a helpful error message if jest is not found, i.e. they + // forgot/didn't know they had to add jest themselves. + try { + require.resolve('jest'); + } catch { + console.error( + [ + 'No Jest installation found in this project.', + '', + 'To support opt-in migration to Jest v30, the Backstage CLI now expects Jest to be installed as a devDependency.', + 'See the migration guide in the changelog for version options and their consequences.', + ].join('\n'), + ); + process.exit(1); + } + await require('jest').run(args); }; diff --git a/packages/cli/src/modules/test/commands/repo/test.ts b/packages/cli/src/modules/test/commands/repo/test.ts index fd18ba09fe..2288d13476 100644 --- a/packages/cli/src/modules/test/commands/repo/test.ts +++ b/packages/cli/src/modules/test/commands/repo/test.ts @@ -17,6 +17,8 @@ import os from 'os'; import crypto from 'node:crypto'; import yargs from 'yargs'; +// 'jest-cli' is included with jest and should be kept in sync with the installed jest version +// eslint-disable-next-line @backstage/no-undeclared-imports import { run as runJest, yargsOptions as jestYargsOptions } from 'jest-cli'; import { relative as relativePath } from 'path'; import { Command, OptionValues } from 'commander'; @@ -289,6 +291,14 @@ export async function command(opts: OptionValues, cmd: Command): Promise { process.env.TZ = 'UTC'; } + // Unless the user explicitly toggles node-snapshot, default to provide --no-node-snapshot to reduce number of steps to run scaffolder + // on Node LTS. + if (!process.env.NODE_OPTIONS?.includes('--node-snapshot')) { + process.env.NODE_OPTIONS = `${ + process.env.NODE_OPTIONS ? `${process.env.NODE_OPTIONS} ` : '' + }--no-node-snapshot`; + } + // This ensures that the process doesn't exit too early before stdout is flushed if (args.includes('--jest-help')) { removeOptionArg(args, '--jest-help'); diff --git a/packages/cli/templates/frontend-plugin/package.json.hbs b/packages/cli/templates/frontend-plugin/package.json.hbs index 1ee8231228..9499d11b18 100644 --- a/packages/cli/templates/frontend-plugin/package.json.hbs +++ b/packages/cli/templates/frontend-plugin/package.json.hbs @@ -31,7 +31,9 @@ "react-use": "{{versionQuery 'react-use' '17.2.4'}}" }, "peerDependencies": { - "react": "{{versionQuery 'react' '^16.13.1 || ^17.0.0 || ^18.0.0'}}" + "react": "{{versionQuery 'react' '^16.13.1 || ^17.0.0 || ^18.0.0'}}", + "react-dom": "{{versionQuery 'react-dom' '^16.13.1 || ^17.0.0 || ^18.0.0'}}", + "react-router-dom": "{{versionQuery 'react-router-dom' '^6.0.0'}}" }, "devDependencies": { "@backstage/cli": "{{versionQuery '@backstage/cli'}}", @@ -42,7 +44,9 @@ "@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'}}", - "react": "{{versionQuery 'react' '^16.13.1 || ^17.0.0 || ^18.0.0'}}" + "react": "{{versionQuery 'react' '^16.13.1 || ^17.0.0 || ^18.0.0'}}", + "react-dom": "{{versionQuery 'react-dom' '^16.13.1 || ^17.0.0 || ^18.0.0'}}", + "react-router-dom": "{{versionQuery 'react-router-dom' '^6.0.0'}}" }, "files": [ "dist" diff --git a/packages/codemods/CHANGELOG.md b/packages/codemods/CHANGELOG.md index 13e6bfe7f6..22dd2a5df7 100644 --- a/packages/codemods/CHANGELOG.md +++ b/packages/codemods/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/codemods +## 0.1.53 + +### Patch Changes + +- 688f070: Updated to use new utilities from `@backstage/cli-common`. +- 2bae83a: Bumped dev dependencies `@types/node` +- Updated dependencies + - @backstage/cli-common@0.1.16 + +## 0.1.53-next.2 + +### Patch Changes + +- 2bae83a: Bumped dev dependencies `@types/node` +- Updated dependencies + - @backstage/cli-common@0.1.16-next.2 + ## 0.1.53-next.1 ### Patch Changes diff --git a/packages/codemods/package.json b/packages/codemods/package.json index f78579f714..01f5ae9168 100644 --- a/packages/codemods/package.json +++ b/packages/codemods/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/codemods", - "version": "0.1.53-next.1", + "version": "0.1.53", "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 00980c43bd..84ad0e04a1 100644 --- a/packages/config-loader/CHANGELOG.md +++ b/packages/config-loader/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/config-loader +## 1.10.7 + +### Patch Changes + +- 741c47a: Updated dependency `typescript-json-schema` to `^0.67.0`. +- Updated dependencies + - @backstage/cli-common@0.1.16 + +## 1.10.7-next.1 + +### Patch Changes + +- 741c47a: Updated dependency `typescript-json-schema` to `^0.67.0`. +- Updated dependencies + - @backstage/cli-common@0.1.16-next.2 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + ## 1.10.7-next.0 ### Patch Changes diff --git a/packages/config-loader/package.json b/packages/config-loader/package.json index 24b71ce824..e48723e5f7 100644 --- a/packages/config-loader/package.json +++ b/packages/config-loader/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/config-loader", - "version": "1.10.7-next.0", + "version": "1.10.7", "description": "Config loading functionality used by Backstage backend, and CLI", "backstage": { "role": "node-library" @@ -57,7 +57,7 @@ "@backstage/cli": "workspace:^", "@types/json-schema-merge-allof": "^0.6.0", "@types/minimist": "^1.2.5", - "msw": "^1.0.0", + "msw": "^2.0.0", "zen-observable": "^0.10.0" } } diff --git a/packages/config-loader/src/loader.test.ts b/packages/config-loader/src/loader.test.ts index 8908b4268b..ea226aa557 100644 --- a/packages/config-loader/src/loader.test.ts +++ b/packages/config-loader/src/loader.test.ts @@ -17,7 +17,7 @@ import { AppConfig } from '@backstage/config'; import { loadConfig } from './loader'; import fs from 'fs-extra'; -import { rest } from 'msw'; +import { http, HttpResponse } from 'msw'; import { setupServer } from 'msw/node'; import { createMockDirectory } from '@backstage/backend-test-utils'; import { createDeferred } from '@backstage/types'; @@ -74,32 +74,28 @@ describe('loadConfig', () => { }); const server = setupServer(); - const initialLoaderHandler = rest.get( + const initialLoaderHandler = http.get( `https://some.domain.io/app-config.yaml`, - (_req, res, ctx) => { - return res( - ctx.body( - `app: + () => { + return new HttpResponse( + `app: title: Remote Example App sessionKey: 'abc123' escaped: \$\${Escaped} `, - ), ); }, ); - const reloadHandler = rest.get( + const reloadHandler = http.get( `https://some.domain.io/app-config.yaml`, - (_req, res, ctx) => { - return res( - ctx.body( - `app: + () => { + return new HttpResponse( + `app: title: NEW ReMOTe ExaMPLe App sessionKey: 'abc123' escaped: \$\${Escaped} `, - ), ); }, ); diff --git a/packages/config-loader/src/schema/collect.test.ts b/packages/config-loader/src/schema/collect.test.ts index d48c98fbe4..a732d982d3 100644 --- a/packages/config-loader/src/schema/collect.test.ts +++ b/packages/config-loader/src/schema/collect.test.ts @@ -15,14 +15,9 @@ */ import { createMockDirectory } from '@backstage/backend-test-utils'; -import { collectConfigSchemas } from './collect'; +import { collectConfigSchemas, internal } from './collect'; import path from 'path'; - -// cwd must be restored -const origDir = process.cwd(); -afterAll(() => { - process.chdir(origDir); -}); +import { execSync } from 'child_process'; const mockSchema = { type: 'object', @@ -37,6 +32,36 @@ const mockSchema = { describe('collectConfigSchemas', () => { const mockDir = createMockDirectory(); + // Jest 30's module resolver doesn't find nested node_modules in mock directories. + // Use a child process for native Node.js resolution instead. + const originalResolvePackagePath = internal.resolvePackagePath; + beforeAll(() => { + internal.resolvePackagePath = (name, options) => { + const basePath = (options && options.paths?.[0]) ?? process.cwd(); + const baseDir = basePath.endsWith('.json') + ? path.dirname(basePath) + : basePath; + + try { + return execSync('node', { + input: `console.log(require.resolve(${JSON.stringify( + name, + )}, { paths: [${JSON.stringify(baseDir)}] }))`, + encoding: 'utf8', + stdio: ['pipe', 'pipe', 'pipe'], + }).trim(); + } catch { + const error = new Error(`Cannot find module '${name}'`); + (error as NodeJS.ErrnoException).code = 'MODULE_NOT_FOUND'; + throw error; + } + }; + }); + + afterAll(() => { + internal.resolvePackagePath = originalResolvePackagePath; + }); + afterEach(() => { mockDir.clear(); }); diff --git a/packages/config-loader/src/schema/collect.ts b/packages/config-loader/src/schema/collect.ts index 16bd654946..5f4e54387d 100644 --- a/packages/config-loader/src/schema/collect.ts +++ b/packages/config-loader/src/schema/collect.ts @@ -37,6 +37,17 @@ const req = ? require : __non_webpack_require__; +/** + * Exported for test mocking. Jest 30's module resolver has issues with + * nested node_modules, requiring tests to use an alternative resolution strategy. + * @internal + */ +export const internal = { + resolvePackagePath(name: string, options?: { paths: string[] }): string { + return req.resolve(name, options); + }, +}; + /** * This collects all known config schemas across all dependencies of the app. */ @@ -62,11 +73,9 @@ export async function collectConfigSchemas( const { name, parentPath } = item; try { - pkgPath = req.resolve( + pkgPath = internal.resolvePackagePath( `${name}/package.json`, - parentPath && { - paths: [parentPath], - }, + parentPath ? { paths: [parentPath] } : undefined, ); } catch { // We can somewhat safely ignore packages that don't export package.json, diff --git a/packages/config-loader/src/sources/RemoteConfigSource.test.ts b/packages/config-loader/src/sources/RemoteConfigSource.test.ts index 372dc91823..acb5870c7d 100644 --- a/packages/config-loader/src/sources/RemoteConfigSource.test.ts +++ b/packages/config-loader/src/sources/RemoteConfigSource.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { rest } from 'msw'; +import { http, HttpResponse } from 'msw'; import { registerMswTestHooks } from '@backstage/backend-test-utils'; import { setupServer } from 'msw/node'; import { RemoteConfigSource } from './RemoteConfigSource'; @@ -26,15 +26,15 @@ describe('RemoteConfigSource', () => { it('should load config from a remote URL', async () => { worker.use( - rest.get('http://localhost/config.yaml', (_req, res, ctx) => - res( - ctx.body(` + http.get( + 'http://localhost/config.yaml', + () => + new HttpResponse(` app: title: Example App substituted: \${VALUE} escaped: \$\${VALUE} `), - ), ), ); @@ -61,9 +61,10 @@ app: it('should load and parse config from a remote URL', async () => { worker.use( - rest.get('http://localhost/config.json', (_req, res, ctx) => - res( - ctx.body( + http.get( + 'http://localhost/config.json', + () => + new HttpResponse( JSON.stringify({ app: { title: 'Example App', @@ -72,7 +73,6 @@ app: }, }), ), - ), ), ); @@ -102,12 +102,12 @@ app: let fetched = false; worker.use( - rest.get('http://localhost/config.yaml', (_req, res, ctx) => { + http.get('http://localhost/config.yaml', () => { if (!fetched) { fetched = true; - return res(ctx.body('x: 1')); + return new HttpResponse('x: 1'); } - return res(ctx.body('x: 2')); + return new HttpResponse('x: 2'); }), ); diff --git a/packages/core-app-api/CHANGELOG.md b/packages/core-app-api/CHANGELOG.md index cc78499c94..2b2dbeccfd 100644 --- a/packages/core-app-api/CHANGELOG.md +++ b/packages/core-app-api/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/core-app-api +## 1.19.3 + +### Patch Changes + +- 75683ed: Added replay functionality to `AlertApiForwarder` to buffer and replay recent alerts to new subscribers, preventing missed alerts that were posted before subscription. +- 97cd16f: Internal update of translation imports. +- Updated dependencies + - @backstage/core-plugin-api@1.12.1 + +## 1.19.3-next.1 + +### Patch Changes + +- 75683ed: Added replay functionality to `AlertApiForwarder` to buffer and replay recent alerts to new subscribers, preventing missed alerts that were posted before subscription. +- Updated dependencies + - @backstage/config@1.3.6 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/types@1.2.2 + - @backstage/version-bridge@1.0.11 + ## 1.19.3-next.0 ### Patch Changes diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index d0c2d2b512..cd56c90ce8 100644 --- a/packages/core-app-api/package.json +++ b/packages/core-app-api/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/core-app-api", - "version": "1.19.3-next.0", + "version": "1.19.3", "description": "Core app API used by Backstage apps", "backstage": { "role": "web-library" diff --git a/packages/core-app-api/src/apis/implementations/FetchApi/PluginProtocolResolverFetchMiddleware.test.ts b/packages/core-app-api/src/apis/implementations/FetchApi/PluginProtocolResolverFetchMiddleware.test.ts index bd82d58736..2b2545f52f 100644 --- a/packages/core-app-api/src/apis/implementations/FetchApi/PluginProtocolResolverFetchMiddleware.test.ts +++ b/packages/core-app-api/src/apis/implementations/FetchApi/PluginProtocolResolverFetchMiddleware.test.ts @@ -60,12 +60,6 @@ describe('PluginProtocolResolverFetchMiddleware', () => { 'https://real.com:8080/base', 'https://real.com:8080/base?c=d&e=f#g', ], - [ - 'plugin://username:password@x?c=d&e=f#g', - 'x', - 'https://real.com:8080/base', - 'https://username:password@real.com:8080/base?c=d&e=f#g', - ], [ 'plugin://x?c=d&e=f#g', 'x', @@ -106,14 +100,14 @@ describe('PluginProtocolResolverFetchMiddleware', () => { expect(inner.mock.calls[0][0]).toBe('https://elsewhere.com'); expect(inner.mock.calls[0][1].body).toBe('123'); - await outer( - new Request('plugin://a', { - method: 'POST', - body: '123', - }), - ); + const inputRequest = new Request('plugin://a', { + method: 'POST', + body: '123', + }); + + await outer(inputRequest); expect(inner.mock.calls[1][0]).toBe('https://elsewhere.com'); - expect(inner.mock.calls[1][1].body).toEqual(Buffer.from('123', 'utf8')); + expect(inner.mock.calls[1][1]).toBe(inputRequest); }); }); diff --git a/packages/core-app-api/src/apis/implementations/IdentityApi/AppIdentityProxy.test.ts b/packages/core-app-api/src/apis/implementations/IdentityApi/AppIdentityProxy.test.ts index 5993543c33..9d320c4033 100644 --- a/packages/core-app-api/src/apis/implementations/IdentityApi/AppIdentityProxy.test.ts +++ b/packages/core-app-api/src/apis/implementations/IdentityApi/AppIdentityProxy.test.ts @@ -83,12 +83,9 @@ describe('AppIdentityProxy', () => { it('should navigate to target URL on sign out', async () => { const proxy = new AppIdentityProxy(); proxy.setTarget(mockIdentityApi, { signOutTargetUrl: '/foo' }); - Object.defineProperty(window, 'location', { - writable: true, - value: {}, - }); + const navigateSpy = jest.spyOn(proxy as any, 'navigateToUrl'); await proxy.signOut(); - expect(window.location.href).toBe('/foo'); + expect(navigateSpy).toHaveBeenCalledWith('/foo'); }); }); diff --git a/packages/core-app-api/src/apis/implementations/IdentityApi/AppIdentityProxy.ts b/packages/core-app-api/src/apis/implementations/IdentityApi/AppIdentityProxy.ts index 941ec90d66..161092fe9f 100644 --- a/packages/core-app-api/src/apis/implementations/IdentityApi/AppIdentityProxy.ts +++ b/packages/core-app-api/src/apis/implementations/IdentityApi/AppIdentityProxy.ts @@ -133,7 +133,11 @@ export class AppIdentityProxy implements IdentityApi { await this.#cookieAuthSignOut?.(); - window.location.href = this.signOutTargetUrl; + this.navigateToUrl(this.signOutTargetUrl); + } + + private navigateToUrl(url: string): void { + window.location.href = url; } enableCookieAuth(ctx: { diff --git a/packages/core-app-api/src/apis/system/ApiProvider.test.tsx b/packages/core-app-api/src/apis/system/ApiProvider.test.tsx index 095fc88627..4273587c00 100644 --- a/packages/core-app-api/src/apis/system/ApiProvider.test.tsx +++ b/packages/core-app-api/src/apis/system/ApiProvider.test.tsx @@ -117,16 +117,12 @@ describe('ApiProvider', () => { }).toThrow(/^API context is not available/); }).error, ).toEqual([ - expect.objectContaining({ - detail: new Error('API context is not available'), - type: 'unhandled exception', - }), - expect.objectContaining({ - detail: new Error('API context is not available'), - type: 'unhandled exception', - }), - expect.stringMatching( - /^The above error occurred in the component/, + expect.stringContaining('Error: API context is not available'), + expect.objectContaining({ type: 'unhandled-exception' }), + expect.stringContaining('Error: API context is not available'), + expect.objectContaining({ type: 'unhandled-exception' }), + expect.stringContaining( + 'The above error occurred in the component', ), ]); @@ -137,16 +133,12 @@ describe('ApiProvider', () => { }).toThrow(/^API context is not available/); }).error, ).toEqual([ - expect.objectContaining({ - detail: new Error('API context is not available'), - type: 'unhandled exception', - }), - expect.objectContaining({ - detail: new Error('API context is not available'), - type: 'unhandled exception', - }), - expect.stringMatching( - /^The above error occurred in the component/, + expect.stringContaining('Error: API context is not available'), + expect.objectContaining({ type: 'unhandled-exception' }), + expect.stringContaining('Error: API context is not available'), + expect.objectContaining({ type: 'unhandled-exception' }), + expect.stringContaining( + 'The above error occurred in the component', ), ]); }); @@ -163,16 +155,16 @@ describe('ApiProvider', () => { }).toThrow('No implementation available for apiRef{x}'); }).error, ).toEqual([ - expect.objectContaining({ - detail: new Error('No implementation available for apiRef{x}'), - type: 'unhandled exception', - }), - expect.objectContaining({ - detail: new Error('No implementation available for apiRef{x}'), - type: 'unhandled exception', - }), - expect.stringMatching( - /^The above error occurred in the component/, + expect.stringContaining( + 'Error: No implementation available for apiRef{x}', + ), + expect.objectContaining({ type: 'unhandled-exception' }), + expect.stringContaining( + 'Error: No implementation available for apiRef{x}', + ), + expect.objectContaining({ type: 'unhandled-exception' }), + expect.stringContaining( + 'The above error occurred in the component', ), ]); @@ -187,16 +179,16 @@ describe('ApiProvider', () => { }).toThrow('No implementation available for apiRef{x}'); }).error, ).toEqual([ - expect.objectContaining({ - detail: new Error('No implementation available for apiRef{x}'), - type: 'unhandled exception', - }), - expect.objectContaining({ - detail: new Error('No implementation available for apiRef{x}'), - type: 'unhandled exception', - }), - expect.stringMatching( - /^The above error occurred in the component/, + expect.stringContaining( + 'Error: No implementation available for apiRef{x}', + ), + expect.objectContaining({ type: 'unhandled-exception' }), + expect.stringContaining( + 'Error: No implementation available for apiRef{x}', + ), + expect.objectContaining({ type: 'unhandled-exception' }), + expect.stringContaining( + 'The above error occurred in the component', ), ]); }); diff --git a/packages/core-app-api/src/app/AppManager.test.tsx b/packages/core-app-api/src/app/AppManager.test.tsx index 3981da56ad..4a146678bc 100644 --- a/packages/core-app-api/src/app/AppManager.test.tsx +++ b/packages/core-app-api/src/app/AppManager.test.tsx @@ -670,14 +670,10 @@ describe('Integration Test', () => { }); expect(errorLogs).toEqual([ - expect.objectContaining({ - detail: new Error(expectedMessage), - type: 'unhandled exception', - }), - expect.objectContaining({ - detail: new Error(expectedMessage), - type: 'unhandled exception', - }), + expect.stringContaining(`Error: ${expectedMessage}`), + expect.objectContaining({ type: 'unhandled-exception' }), + expect.stringContaining(`Error: ${expectedMessage}`), + expect.objectContaining({ type: 'unhandled-exception' }), expect.stringContaining( 'The above error occurred in the component:', ), @@ -714,14 +710,10 @@ describe('Integration Test', () => { ).rejects.toThrow(expectedMessage); }); expect(errorLogs).toEqual([ - expect.objectContaining({ - detail: new Error(expectedMessage), - type: 'unhandled exception', - }), - expect.objectContaining({ - detail: new Error(expectedMessage), - type: 'unhandled exception', - }), + expect.stringContaining(`Error: ${expectedMessage}`), + expect.objectContaining({ type: 'unhandled-exception' }), + expect.stringContaining(`Error: ${expectedMessage}`), + expect.objectContaining({ type: 'unhandled-exception' }), expect.stringContaining( 'The above error occurred in the component:', ), diff --git a/packages/core-compat-api/CHANGELOG.md b/packages/core-compat-api/CHANGELOG.md index 4f3d30deda..791b2cf1dc 100644 --- a/packages/core-compat-api/CHANGELOG.md +++ b/packages/core-compat-api/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/core-compat-api +## 0.5.5 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/core-plugin-api@1.12.1 + ## 0.5.5-next.0 ### Patch Changes diff --git a/packages/core-compat-api/package.json b/packages/core-compat-api/package.json index 7bb92d26fc..f8d065a611 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.5.5-next.0", + "version": "0.5.5", "backstage": { "role": "web-library" }, diff --git a/packages/core-compat-api/src/convertLegacyApp.test.tsx b/packages/core-compat-api/src/convertLegacyApp.test.tsx index 1cb2b757e3..7094eb798c 100644 --- a/packages/core-compat-api/src/convertLegacyApp.test.tsx +++ b/packages/core-compat-api/src/convertLegacyApp.test.tsx @@ -262,13 +262,16 @@ describe('convertLegacyApp', () => { ], }); + // Increase timeout for async rendering of complex catalog entity pages + const findOptions = { timeout: 5000 }; + // Overview const renderOverviewTest = await renderTestApp({ features: [catalogOverride, ...converted], initialRouteEntries: ['/catalog/default/test/x'], }); await expect( - renderOverviewTest.findByText('overview content'), + renderOverviewTest.findByText('overview content', {}, findOptions), ).resolves.toBeInTheDocument(); renderOverviewTest.unmount(); @@ -277,7 +280,7 @@ describe('convertLegacyApp', () => { initialRouteEntries: ['/catalog/default/other/x'], }); await expect( - renderOverviewOther.findByText('other overview content'), + renderOverviewOther.findByText('other overview content', {}, findOptions), ).resolves.toBeInTheDocument(); renderOverviewOther.unmount(); @@ -287,7 +290,7 @@ describe('convertLegacyApp', () => { initialRouteEntries: ['/catalog/default/test/x/foo'], }); await expect( - renderFooTest.findByText('foo content'), + renderFooTest.findByText('foo content', {}, findOptions), ).resolves.toBeInTheDocument(); renderFooTest.unmount(); @@ -296,7 +299,7 @@ describe('convertLegacyApp', () => { initialRouteEntries: ['/catalog/default/other/x/foo'], }); await expect( - renderFooOther.findByText('other foo content'), + renderFooOther.findByText('other foo content', {}, findOptions), ).resolves.toBeInTheDocument(); renderFooOther.unmount(); @@ -306,7 +309,7 @@ describe('convertLegacyApp', () => { initialRouteEntries: ['/catalog/default/test/x/bar'], }); await expect( - renderBarTest.findByText('bar content'), + renderBarTest.findByText('bar content', {}, findOptions), ).resolves.toBeInTheDocument(); renderBarTest.unmount(); @@ -315,7 +318,7 @@ describe('convertLegacyApp', () => { initialRouteEntries: ['/catalog/default/other/x/bar'], }); await expect( - renderBarOther.findByText('other overview content'), + renderBarOther.findByText('other overview content', {}, findOptions), ).resolves.toBeInTheDocument(); // /bar does not exist, fall back to rendering overview renderBarOther.unmount(); }); diff --git a/packages/core-components/CHANGELOG.md b/packages/core-components/CHANGELOG.md index ea2023e845..7346287cf6 100644 --- a/packages/core-components/CHANGELOG.md +++ b/packages/core-components/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/core-components +## 0.18.4 + +### Patch Changes + +- 9a942a4: Fixed bug in the `LogViewer` component where shift + click always opened a new window instead of just changing the selection. + + In addition, improved the `LogViewer` component by a few usability enhancements: + + - Added support for multiple selections using cmd/ctrl + click + - Improved the generated hash that is added to the URL to also support ranges & multiple selections + - Added an hover effect & info tooltip to the "Copy to clipboard" button to indicate its functionality + - Added some color and a separator to the line numbers to improve readability + +- 207c3c8: long words like urls now breaks to new line on warning panels instead of overflowing the container +- 4c00303: Add `tooltipClasses` prop to `OverflowTooltip` component to allow customisation of the tooltip +- 5d52dab: Add i18n support for LogViewer search control +- f6b49ce: added support for wrapLongLines option in CodeSnippet +- Updated dependencies + - @backstage/core-plugin-api@1.12.1 + - @backstage/theme@0.7.1 + +## 0.18.4-next.2 + +### Patch Changes + +- 4c00303: Add `tooltipClasses` prop to `OverflowTooltip` component to allow customisation of the tooltip +- Updated dependencies + - @backstage/config@1.3.6 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/errors@1.2.7 + - @backstage/theme@0.7.1-next.0 + - @backstage/version-bridge@1.0.11 + ## 0.18.4-next.1 ### Patch Changes diff --git a/packages/core-components/package.json b/packages/core-components/package.json index 2c3cee0c46..536f0ee9f0 100644 --- a/packages/core-components/package.json +++ b/packages/core-components/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/core-components", - "version": "0.18.4-next.1", + "version": "0.18.4", "description": "Core components used by Backstage plugins and apps", "backstage": { "role": "web-library" diff --git a/packages/core-components/report.api.md b/packages/core-components/report.api.md index 02fbb04805..5e842929e6 100644 --- a/packages/core-components/report.api.md +++ b/packages/core-components/report.api.md @@ -188,6 +188,7 @@ export interface CodeSnippetProps { showCopyCodeButton?: boolean; showLineNumbers?: boolean; text: string; + wrapLongLines?: boolean; } // Warning: (ae-forgotten-export) The symbol "Props_12" needs to be exported by the entry point index.d.ts diff --git a/packages/core-components/src/components/CodeSnippet/CodeSnippet.tsx b/packages/core-components/src/components/CodeSnippet/CodeSnippet.tsx index 8c31bc4e6d..e79dc07ad3 100644 --- a/packages/core-components/src/components/CodeSnippet/CodeSnippet.tsx +++ b/packages/core-components/src/components/CodeSnippet/CodeSnippet.tsx @@ -57,6 +57,14 @@ export interface CodeSnippetProps { * Array of line numbers to highlight */ highlightedNumbers?: number[]; + /** + * Whether to style the `` block with `white-space: pre-wrap` or `white-space: pre` + * + * @remarks + * + * Default: false (`white-space: pre`) + */ + wrapLongLines?: boolean; /** * Custom styles applied to code * @@ -79,6 +87,7 @@ export function CodeSnippet(props: CodeSnippetProps) { language, showLineNumbers = false, highlightedNumbers, + wrapLongLines, customStyle, showCopyCodeButton = false, } = props; @@ -94,6 +103,7 @@ export function CodeSnippet(props: CodeSnippetProps) { style={mode} showLineNumbers={showLineNumbers} wrapLines + wrapLongLines={wrapLongLines} lineNumberStyle={{ color: theme.palette.textVerySubtle }} lineProps={(lineNumber: number) => highlightedNumbers?.includes(lineNumber) diff --git a/packages/core-components/src/components/Link/Link.test.tsx b/packages/core-components/src/components/Link/Link.test.tsx index c132d832a2..c178ba6cbf 100644 --- a/packages/core-components/src/components/Link/Link.test.tsx +++ b/packages/core-components/src/components/Link/Link.test.tsx @@ -50,7 +50,7 @@ describe('', () => { External Link, ); const externalLink = screen.getByRole('link', { - name: 'External Link , Opens in a new window', + name: 'External Link, Opens in a new window', }); const externalLinkIcon = container.querySelector('svg'); expect(externalLink).not.toContainElement(externalLinkIcon); @@ -62,6 +62,7 @@ describe('', () => { External Link , ); + // Note: when externalLinkIcon is present, the SVG adds whitespace to the accessible name const externalLink = screen.getByRole('link', { name: 'External Link , Opens in a new window', }); diff --git a/packages/core-components/src/components/TabbedLayout/TabbedLayout.test.tsx b/packages/core-components/src/components/TabbedLayout/TabbedLayout.test.tsx index 1be58d2dcf..3e4ab1df7c 100644 --- a/packages/core-components/src/components/TabbedLayout/TabbedLayout.test.tsx +++ b/packages/core-components/src/components/TabbedLayout/TabbedLayout.test.tsx @@ -47,18 +47,20 @@ describe('TabbedLayout', () => { }); expect(error).toEqual([ + expect.stringContaining( + 'Error: Child of TabbedLayout must be an TabbedLayout.Route', + ), expect.objectContaining({ - detail: new Error( - 'Child of TabbedLayout must be an TabbedLayout.Route', - ), + type: 'unhandled-exception', }), + expect.stringContaining( + 'Error: Child of TabbedLayout must be an TabbedLayout.Route', + ), expect.objectContaining({ - detail: new Error( - 'Child of TabbedLayout must be an TabbedLayout.Route', - ), + type: 'unhandled-exception', }), - expect.stringMatching( - /The above error occurred in the component/, + expect.stringContaining( + 'The above error occurred in the component', ), ]); }); diff --git a/packages/core-components/src/components/Table/Table.test.tsx b/packages/core-components/src/components/Table/Table.test.tsx index dfae66d1c2..dab5a462c2 100644 --- a/packages/core-components/src/components/Table/Table.test.tsx +++ b/packages/core-components/src/components/Table/Table.test.tsx @@ -68,7 +68,7 @@ describe('', () => {
, ); expect(rendered.getByText('second value, first row')).toHaveStyle({ - color: 'blue', + color: 'rgb(0, 0, 255)', // blue }); }); @@ -85,7 +85,7 @@ describe('
', () => {
, ); expect(rendered.getByText('second value, first row')).toHaveStyle({ - color: 'blue', + color: 'rgb(0, 0, 255)', // blue 'font-weight': 700, }); }); @@ -115,10 +115,10 @@ describe('
', () => {
, ); expect(rendered.getByText('second value, first row')).toHaveStyle({ - color: 'green', + color: 'rgb(0, 128, 0)', // green }); expect(rendered.getByText('second value, second row')).toHaveStyle({ - color: 'red', + color: 'rgb(255, 0, 0)', // red }); }); @@ -135,11 +135,11 @@ describe('
', () => {
, ); expect(rendered.getByText('second value, first row')).toHaveStyle({ - color: 'green', + color: 'rgb(0, 128, 0)', // green 'font-weight': 700, }); expect(rendered.getByText('second value, second row')).toHaveStyle({ - color: 'red', + color: 'rgb(255, 0, 0)', // red 'font-weight': 700, }); }); @@ -165,11 +165,11 @@ describe('
', () => { expect(rendered.getByText(column1.title).closest('th')).not.toHaveStyle( { - backgroundColor: 'pink', + backgroundColor: 'rgb(255, 192, 203)', // pink }, ); expect(rendered.getByText(column2.title).closest('th')).toHaveStyle({ - backgroundColor: 'pink', + backgroundColor: 'rgb(255, 192, 203)', // pink }); }); diff --git a/packages/core-components/src/layout/ErrorBoundary/ErrorBoundary.test.tsx b/packages/core-components/src/layout/ErrorBoundary/ErrorBoundary.test.tsx index 4011fd2125..65e8a55801 100644 --- a/packages/core-components/src/layout/ErrorBoundary/ErrorBoundary.test.tsx +++ b/packages/core-components/src/layout/ErrorBoundary/ErrorBoundary.test.tsx @@ -67,18 +67,20 @@ describe('', () => { }); expect(error).toEqual([ + expect.stringContaining('Error: Bomb'), expect.objectContaining({ - detail: new Error('Bomb'), + type: 'unhandled-exception', }), + expect.stringContaining('Error: Bomb'), expect.objectContaining({ - detail: new Error('Bomb'), + type: 'unhandled-exception', }), - expect.stringMatching( - /^The above error occurred in the component:/, + expect.stringContaining( + 'The above error occurred in the component:', ), - expect.stringMatching(/^ErrorBoundary/), - expect.stringMatching(/Warning: findDOMNode/), // React warning, unfortunate but currently true + expect.stringContaining('ErrorBoundary'), + expect.stringContaining('Warning: findDOMNode'), // React warning, unfortunate but currently true ]); - expect(error.length).toEqual(5); + expect(error.length).toEqual(7); }); }); diff --git a/packages/core-components/src/layout/Sidebar/Items.test.tsx b/packages/core-components/src/layout/Sidebar/Items.test.tsx index 3121228ccd..35a0793409 100644 --- a/packages/core-components/src/layout/Sidebar/Items.test.tsx +++ b/packages/core-components/src/layout/Sidebar/Items.test.tsx @@ -96,7 +96,7 @@ describe('Items', () => { it('should render a button with custom style', async () => { expect( await screen.findByRole('button', { name: /create/i }), - ).toHaveStyle(`background-color: transparent`); + ).toHaveStyle(`background-color: rgba(0, 0, 0, 0)`); // transparent }); it('should send button clicks to analytics', async () => { diff --git a/packages/core-plugin-api/CHANGELOG.md b/packages/core-plugin-api/CHANGELOG.md index a47e87fe66..8c6c617bcb 100644 --- a/packages/core-plugin-api/CHANGELOG.md +++ b/packages/core-plugin-api/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/core-plugin-api +## 1.12.1 + +### Patch Changes + +- 358c6f7: The `useApp` and `useRouteRef` functions are now forwards compatible with the new frontend system. Along with the previous route reference changes this means that there is no longer a need to use `compatWrapper` from `@backstage/core-compat-api` to make code based on `@backstage/core-plugin-api` compatible with `@backstage/frontend-plugin-api` APIs. +- 97cd16f: Reversed the relationship between the old `@backstage/core-plugin-api` and the new `@backstage/frontend-plugin-api`. Previously, the a lot of API definitions and utilities where defined in the old and re-exported from the old, but this change flips that around so that they now reside in the new package and are re-exported from the old. The external API of both packages remain the same, but this is a step towards being able to add further compatibility with the new frontend system built into the old. +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + ## 1.12.1-next.0 ### Patch Changes diff --git a/packages/core-plugin-api/package.json b/packages/core-plugin-api/package.json index 11e4a911c5..ef4982e07e 100644 --- a/packages/core-plugin-api/package.json +++ b/packages/core-plugin-api/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/core-plugin-api", - "version": "1.12.1-next.0", + "version": "1.12.1", "description": "Core API used by Backstage plugins", "backstage": { "role": "web-library" diff --git a/packages/core-plugin-api/src/extensions/extensions.test.tsx b/packages/core-plugin-api/src/extensions/extensions.test.tsx index 75bb4ae443..59fe0d118d 100644 --- a/packages/core-plugin-api/src/extensions/extensions.test.tsx +++ b/packages/core-plugin-api/src/extensions/extensions.test.tsx @@ -26,7 +26,6 @@ import { createReactExtension, createRoutableExtension, } from './extensions'; -import { ForwardedError } from '@backstage/errors'; jest.mock('../app'); @@ -117,7 +116,13 @@ describe('extensions', () => { render(); }); screen.getByText('Error in my-plugin'); - expect(errors[0]).toMatchObject({ detail: new Error('Test error') }); + expect(errors).toEqual([ + expect.stringContaining('Error: Test error'), + expect.objectContaining({ type: 'unhandled-exception' }), + expect.stringContaining('Error: Test error'), + expect.objectContaining({ type: 'unhandled-exception' }), + expect.stringContaining('The above error occurred in'), + ]); }); it('should handle failed lazy loads', async () => { @@ -154,12 +159,17 @@ describe('extensions', () => { screen.getByText( 'Error in my-plugin: Error: Failed lazy loading of the BrokenComponent extension, try to reload the page; caused by Error: Test error', ); - expect(errors[0]).toMatchObject({ - detail: new ForwardedError( - 'Failed lazy loading of the BrokenComponent extension, try to reload the page', - new Error('Test error'), + expect(errors).toEqual([ + expect.stringContaining( + 'Error: Failed lazy loading of the BrokenComponent extension, try to reload the page', ), - }); + expect.objectContaining({ type: 'unhandled-exception' }), + expect.stringContaining( + 'Error: Failed lazy loading of the BrokenComponent extension, try to reload the page', + ), + expect.objectContaining({ type: 'unhandled-exception' }), + expect.stringContaining('The above error occurred in'), + ]); }); it('should wrap extended component with analytics context', async () => { diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index 8c7fd970ab..87129fea1c 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/create-app +## 0.7.8-next.0 + +### Patch Changes + +- Bumped create-app version. +- Updated dependencies + - @backstage/cli-common@0.1.16 + +## 0.7.7 + +### Patch Changes + +- 336db00: Bumped create-app version. +- 2bae83a: Updated engines to support Node 22 or 24 +- c8c2329: Add proxy configuration from env-vars to create-app tasks +- 2bae83a: Bumped dev dependencies `@types/node` +- Updated dependencies + - @backstage/cli-common@0.1.16 + +## 0.7.7-next.2 + +### Patch Changes + +- 2bae83a: Updated engines to support Node 22 or 24 +- 2bae83a: Bumped dev dependencies `@types/node` +- Updated dependencies + - @backstage/cli-common@0.1.16-next.2 + ## 0.7.7-next.1 ### Patch Changes diff --git a/packages/create-app/package.json b/packages/create-app/package.json index af82d507d2..230b6f5ebd 100644 --- a/packages/create-app/package.json +++ b/packages/create-app/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/create-app", - "version": "0.7.7-next.1", + "version": "0.7.8-next.0", "description": "A CLI that helps you create your own Backstage app", "backstage": { "role": "cli" diff --git a/packages/create-app/templates/default-app/package.json.hbs b/packages/create-app/templates/default-app/package.json.hbs index d0a088a7d1..c1e4a51140 100644 --- a/packages/create-app/templates/default-app/package.json.hbs +++ b/packages/create-app/templates/default-app/package.json.hbs @@ -32,6 +32,10 @@ "@backstage/cli": "^{{version '@backstage/cli'}}", "@backstage/e2e-test-utils": "^{{version '@backstage/e2e-test-utils'}}", "@playwright/test": "^1.32.3", + "@jest/environment-jsdom-abstract": "^30.0.0", + "@types/jest": "^30.0.0", + "jest": "^30.2.0", + "jsdom": "^27.1.0", "node-gyp": "^10.0.0", "prettier": "^2.3.2", "typescript": "~5.8.0" diff --git a/packages/dev-utils/CHANGELOG.md b/packages/dev-utils/CHANGELOG.md index 1b26653336..d1c9be0ec3 100644 --- a/packages/dev-utils/CHANGELOG.md +++ b/packages/dev-utils/CHANGELOG.md @@ -1,5 +1,34 @@ # @backstage/dev-utils +## 1.1.19-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/ui@0.11.0-next.0 + - @backstage/app-defaults@1.7.3 + - @backstage/catalog-model@1.7.6 + - @backstage/core-app-api@1.19.3 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/integration-react@1.2.13 + - @backstage/theme@0.7.1 + - @backstage/plugin-catalog-react@1.21.4 + +## 1.1.18 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.19.3 + - @backstage/ui@0.10.0 + - @backstage/core-components@0.18.4 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/theme@0.7.1 + - @backstage/app-defaults@1.7.3 + - @backstage/integration-react@1.2.13 + ## 1.1.18-next.1 ### Patch Changes diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index 5b0c9bbee7..5c9795627d 100644 --- a/packages/dev-utils/package.json +++ b/packages/dev-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/dev-utils", - "version": "1.1.18-next.1", + "version": "1.1.19-next.0", "description": "Utilities for developing Backstage plugins.", "backstage": { "role": "web-library" diff --git a/packages/e2e-test/CHANGELOG.md b/packages/e2e-test/CHANGELOG.md index e65f1ffaf5..76fd95f56e 100644 --- a/packages/e2e-test/CHANGELOG.md +++ b/packages/e2e-test/CHANGELOG.md @@ -1,5 +1,22 @@ # e2e-test +## 0.2.36-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.7.8-next.0 + - @backstage/cli-common@0.1.16 + - @backstage/errors@1.2.7 + +## 0.2.35 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.7.7 + - @backstage/cli-common@0.1.16 + ## 0.2.35-next.0 ### Patch Changes diff --git a/packages/e2e-test/package.json b/packages/e2e-test/package.json index e70f2f8105..5773464cb1 100644 --- a/packages/e2e-test/package.json +++ b/packages/e2e-test/package.json @@ -1,6 +1,6 @@ { "name": "e2e-test", - "version": "0.2.35-next.0", + "version": "0.2.36-next.0", "description": "E2E test for verifying Backstage packages", "backstage": { "role": "cli" diff --git a/packages/errors/src/errors/common.test.ts b/packages/errors/src/errors/common.test.ts index dfa9743616..4c496614ab 100644 --- a/packages/errors/src/errors/common.test.ts +++ b/packages/errors/src/errors/common.test.ts @@ -23,7 +23,7 @@ describe('common', () => { const error = new E('abcdef'); expect(error.name).toBe(name); expect(error.message).toBe('abcdef'); - expect(error.stack).toContain(__filename); + expect(error.stack).toContain('common.test.ts'); expect(error.toString()).toContain(name); expect(error.toString()).toContain('abcdef'); } diff --git a/packages/frontend-app-api/CHANGELOG.md b/packages/frontend-app-api/CHANGELOG.md index 2d46087f47..625c96f42a 100644 --- a/packages/frontend-app-api/CHANGELOG.md +++ b/packages/frontend-app-api/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/frontend-app-api +## 0.13.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.19.3 + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-plugin-api@1.12.1 + - @backstage/frontend-defaults@0.3.4 + ## 0.13.3-next.0 ### Patch Changes diff --git a/packages/frontend-app-api/package.json b/packages/frontend-app-api/package.json index f69d3d1f13..1c1f486e12 100644 --- a/packages/frontend-app-api/package.json +++ b/packages/frontend-app-api/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/frontend-app-api", - "version": "0.13.3-next.0", + "version": "0.13.3", "backstage": { "role": "web-library" }, diff --git a/packages/frontend-defaults/CHANGELOG.md b/packages/frontend-defaults/CHANGELOG.md index aeacb83d31..eea14a159c 100644 --- a/packages/frontend-defaults/CHANGELOG.md +++ b/packages/frontend-defaults/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/frontend-defaults +## 0.3.4 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-app@0.3.3 + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/frontend-app-api@0.13.3 + ## 0.3.4-next.0 ### Patch Changes diff --git a/packages/frontend-defaults/package.json b/packages/frontend-defaults/package.json index 17b11a391d..9cfacb3237 100644 --- a/packages/frontend-defaults/package.json +++ b/packages/frontend-defaults/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/frontend-defaults", - "version": "0.3.4-next.0", + "version": "0.3.4", "backstage": { "role": "web-library" }, diff --git a/packages/frontend-dynamic-feature-loader/CHANGELOG.md b/packages/frontend-dynamic-feature-loader/CHANGELOG.md index 43df44d8dc..58cb740bd5 100644 --- a/packages/frontend-dynamic-feature-loader/CHANGELOG.md +++ b/packages/frontend-dynamic-feature-loader/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/frontend-dynamic-feature-loader +## 0.1.8 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + ## 0.1.8-next.0 ### Patch Changes diff --git a/packages/frontend-dynamic-feature-loader/package.json b/packages/frontend-dynamic-feature-loader/package.json index 11a10cfee6..c8771ca154 100644 --- a/packages/frontend-dynamic-feature-loader/package.json +++ b/packages/frontend-dynamic-feature-loader/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/frontend-dynamic-feature-loader", - "version": "0.1.8-next.0", + "version": "0.1.8", "backstage": { "role": "web-library" }, diff --git a/packages/frontend-dynamic-feature-loader/src/loader.test.tsx b/packages/frontend-dynamic-feature-loader/src/loader.test.tsx index b2f6486766..c0bf5822cc 100644 --- a/packages/frontend-dynamic-feature-loader/src/loader.test.tsx +++ b/packages/frontend-dynamic-feature-loader/src/loader.test.tsx @@ -655,7 +655,7 @@ describe('dynamicFrontendFeaturesLoader', () => { const errorCalls = mocks.console.error.mock.calls.flatMap(e => e[0]); expect(errorCalls).toEqual([ - `Failed fetching module federation configuration of dynamic frontend plugins: FetchError: invalid json response body at http://localhost:7007/.backstage/dynamic-features/remotes reason: Unexpected end of JSON input`, + `Failed fetching module federation configuration of dynamic frontend plugins: SyntaxError: Unexpected end of JSON input`, ]); const warnCalls = mocks.console.warn.mock.calls.flatMap(e => e[0]); expect(warnCalls).toEqual([]); diff --git a/packages/frontend-internal/CHANGELOG.md b/packages/frontend-internal/CHANGELOG.md index d1adc69391..de5b02e547 100644 --- a/packages/frontend-internal/CHANGELOG.md +++ b/packages/frontend-internal/CHANGELOG.md @@ -1,5 +1,12 @@ # @internal/frontend +## 0.0.16 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + ## 0.0.16-next.0 ### Patch Changes diff --git a/packages/frontend-internal/package.json b/packages/frontend-internal/package.json index 4ac3285d9f..705aec5835 100644 --- a/packages/frontend-internal/package.json +++ b/packages/frontend-internal/package.json @@ -1,6 +1,6 @@ { "name": "@internal/frontend", - "version": "0.0.16-next.0", + "version": "0.0.16", "backstage": { "role": "web-library", "inline": true @@ -25,8 +25,7 @@ "dependencies": { "@backstage/frontend-plugin-api": "workspace:^", "@backstage/types": "workspace:^", - "@backstage/version-bridge": "workspace:^", - "zod": "^3.22.4" + "@backstage/version-bridge": "workspace:^" }, "devDependencies": { "@backstage/cli": "workspace:^", diff --git a/packages/frontend-plugin-api/CHANGELOG.md b/packages/frontend-plugin-api/CHANGELOG.md index c0c6b6ec0e..f2c4f2029c 100644 --- a/packages/frontend-plugin-api/CHANGELOG.md +++ b/packages/frontend-plugin-api/CHANGELOG.md @@ -1,5 +1,34 @@ # @backstage/frontend-plugin-api +## 0.13.2 + +### Patch Changes + +- 75683ed: Added a new `errorPresentation` prop to `ExtensionBoundary` to control how errors are presented to the user. The default is `'error-display'`, which is the current behavior of showing the error in the `ErrorDisplay` component. The new option is `'error-api'`, posts errors to the `ErrorApi` and does not allow retries. + + The `AppRootElementBlueprint` now wraps its element in an `ErrorBoundary` using the new `'error-api'` presentation mode. + +- 0bc1ce9: Fixed a versioning conflict that could result in a `.withContext` is not a function error. +- f3f84f1: Made the return type of `.withOverrides` to be simplified. +- 97cd16f: Reversed the relationship between the old `@backstage/core-plugin-api` and the new `@backstage/frontend-plugin-api`. Previously, the a lot of API definitions and utilities where defined in the old and re-exported from the old, but this change flips that around so that they now reside in the new package and are re-exported from the old. The external API of both packages remain the same, but this is a step towards being able to add further compatibility with the new frontend system built into the old. +- 9b8bde4: Removed unnecessary dependencies on `@backstage/core-components`, `@backstage/config`, `@material-ui/core`, and `lodash`. + +## 0.13.2-next.1 + +### Patch Changes + +- 75683ed: Added a new `errorPresentation` prop to `ExtensionBoundary` to control how errors are presented to the user. The default is `'error-display'`, which is the current behavior of showing the error in the `ErrorDisplay` component. The new option is `'error-api'`, posts errors to the `ErrorApi` and does not allow retries. + + The `AppRootElementBlueprint` now wraps its element in an `ErrorBoundary` using the new `'error-api'` presentation mode. + +- f3f84f1: Made the return type of `.withOverrides` to be simplified. +- Updated dependencies + - @backstage/core-components@0.18.4-next.2 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/version-bridge@1.0.11 + ## 0.13.2-next.0 ### Patch Changes diff --git a/packages/frontend-plugin-api/package.json b/packages/frontend-plugin-api/package.json index 25c40b2e0a..bda034ac78 100644 --- a/packages/frontend-plugin-api/package.json +++ b/packages/frontend-plugin-api/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/frontend-plugin-api", - "version": "0.13.2-next.0", + "version": "0.13.2", "backstage": { "role": "web-library" }, @@ -40,18 +40,15 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/config": "workspace:^", - "@backstage/core-components": "workspace:^", "@backstage/errors": "workspace:^", "@backstage/types": "workspace:^", "@backstage/version-bridge": "workspace:^", - "@material-ui/core": "^4.12.4", - "lodash": "^4.17.21", "zod": "^3.22.4", "zod-to-json-schema": "^3.21.4" }, "devDependencies": { "@backstage/cli": "workspace:^", + "@backstage/config": "workspace:^", "@backstage/frontend-app-api": "workspace:^", "@backstage/frontend-test-utils": "workspace:^", "@backstage/test-utils": "workspace:^", diff --git a/packages/frontend-plugin-api/report.api.md b/packages/frontend-plugin-api/report.api.md index e45401304b..fbe7110d80 100644 --- a/packages/frontend-plugin-api/report.api.md +++ b/packages/frontend-plugin-api/report.api.md @@ -6,7 +6,7 @@ import { AnyRouteRefParams as AnyRouteRefParams_2 } from '@backstage/frontend-plugin-api'; import { ApiRef as ApiRef_2 } from '@backstage/frontend-plugin-api'; import { ComponentType } from 'react'; -import { Config } from '@backstage/config'; +import type { Config } from '@backstage/config'; import { ConfigurableExtensionDataRef as ConfigurableExtensionDataRef_2 } from '@backstage/frontend-plugin-api'; import { Expand } from '@backstage/types'; import { ExpandRecursive } from '@backstage/types'; @@ -23,7 +23,7 @@ import { PropsWithChildren } from 'react'; import { ReactNode } from 'react'; import { RouteRef as RouteRef_2 } from '@backstage/frontend-plugin-api'; import { SwappableComponentRef as SwappableComponentRef_2 } from '@backstage/frontend-plugin-api'; -import { z } from 'zod'; +import type { z } from 'zod'; // @public export type AlertApi = { diff --git a/packages/frontend-plugin-api/src/apis/definitions/ConfigApi.ts b/packages/frontend-plugin-api/src/apis/definitions/ConfigApi.ts index d3bada9e46..f935dfa3af 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/ConfigApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/ConfigApi.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { ApiRef, createApiRef } from '../system'; -import { Config } from '@backstage/config'; +import type { Config } from '@backstage/config'; /** * The Config API is used to provide a mechanism to access the diff --git a/packages/frontend-plugin-api/src/components/AppNodeProvider.test.tsx b/packages/frontend-plugin-api/src/components/AppNodeProvider.test.tsx index fcc3b74c59..0a73f90dde 100644 --- a/packages/frontend-plugin-api/src/components/AppNodeProvider.test.tsx +++ b/packages/frontend-plugin-api/src/components/AppNodeProvider.test.tsx @@ -70,12 +70,10 @@ describe('AppNodeProvider', () => { ).toThrow('AppNodeContext v1 not available'); }); expect(error).toEqual([ - expect.objectContaining({ - detail: new Error('AppNodeContext v1 not available'), - }), - expect.objectContaining({ - detail: new Error('AppNodeContext v1 not available'), - }), + expect.stringContaining('Error: AppNodeContext v1 not available'), + expect.objectContaining({ type: 'unhandled-exception' }), + expect.stringContaining('Error: AppNodeContext v1 not available'), + expect.objectContaining({ type: 'unhandled-exception' }), expect.stringContaining( 'The above error occurred in the component:', ), diff --git a/packages/frontend-plugin-api/src/schema/createSchemaFromZod.ts b/packages/frontend-plugin-api/src/schema/createSchemaFromZod.ts index 85f9d5c44a..b15ff980ec 100644 --- a/packages/frontend-plugin-api/src/schema/createSchemaFromZod.ts +++ b/packages/frontend-plugin-api/src/schema/createSchemaFromZod.ts @@ -15,7 +15,7 @@ */ import { JsonObject } from '@backstage/types'; -import { z, ZodSchema, ZodTypeDef } from 'zod'; +import { z, type ZodSchema, type ZodTypeDef } from 'zod'; import zodToJsonSchema from 'zod-to-json-schema'; import { PortableSchema } from './types'; diff --git a/packages/frontend-plugin-api/src/wiring/createExtension.ts b/packages/frontend-plugin-api/src/wiring/createExtension.ts index 9b55505056..6e4aba2910 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtension.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtension.ts @@ -26,7 +26,7 @@ import { } from '@internal/frontend'; import { ExtensionDataRef, ExtensionDataValue } from './createExtensionDataRef'; import { ExtensionInput } from './createExtensionInput'; -import { z } from 'zod'; +import type { z } from 'zod'; import { createSchemaFromZod } from '../schema/createSchemaFromZod'; import { OpaqueExtensionDefinition } from '@internal/frontend'; import { ExtensionDataContainer } from './types'; diff --git a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts index c6723388ae..a7537d27e9 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts @@ -26,7 +26,7 @@ import { ctxParamsSymbol, VerifyExtensionAttachTo, } from './createExtension'; -import { z } from 'zod'; +import type { z } from 'zod'; import { ExtensionInput } from './createExtensionInput'; import { ExtensionDataRef, ExtensionDataValue } from './createExtensionDataRef'; import { createExtensionDataContainer } from '@internal/frontend'; diff --git a/packages/frontend-test-utils/CHANGELOG.md b/packages/frontend-test-utils/CHANGELOG.md index 3adc1d0f0b..c5399dc2e2 100644 --- a/packages/frontend-test-utils/CHANGELOG.md +++ b/packages/frontend-test-utils/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/frontend-test-utils +## 0.4.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-app@0.3.3 + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/test-utils@1.7.14 + - @backstage/frontend-app-api@0.13.3 + ## 0.4.2-next.0 ### Patch Changes diff --git a/packages/frontend-test-utils/package.json b/packages/frontend-test-utils/package.json index 48ed1b6827..d6b63b22da 100644 --- a/packages/frontend-test-utils/package.json +++ b/packages/frontend-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/frontend-test-utils", - "version": "0.4.2-next.0", + "version": "0.4.2", "backstage": { "role": "web-library" }, diff --git a/packages/integration-react/CHANGELOG.md b/packages/integration-react/CHANGELOG.md index cf30e3fadc..e7becc9337 100644 --- a/packages/integration-react/CHANGELOG.md +++ b/packages/integration-react/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/integration-react +## 1.2.13 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/core-plugin-api@1.12.1 + ## 1.2.13-next.0 ### Patch Changes diff --git a/packages/integration-react/package.json b/packages/integration-react/package.json index d5cc25c5c2..9879042ef1 100644 --- a/packages/integration-react/package.json +++ b/packages/integration-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/integration-react", - "version": "1.2.13-next.0", + "version": "1.2.13", "description": "Frontend package for managing integrations towards external systems", "backstage": { "role": "web-library" diff --git a/packages/integration/CHANGELOG.md b/packages/integration/CHANGELOG.md index a45b3d9770..b732447310 100644 --- a/packages/integration/CHANGELOG.md +++ b/packages/integration/CHANGELOG.md @@ -1,5 +1,45 @@ # @backstage/integration +## 1.19.0 + +### Minor Changes + +- 37fba1d: Added support for Bitbucket Cloud OAuth. This introduces an alternative authentication method using a workspace OAuth consumer, alongside App Passwords (deprecated) and API tokens. OAuth does not require a bot or service account and avoids token expiry issues. + + **BREAKING CHANGES** + + - **@backstage/integration** (`src/bitbucketCloud/core.ts`) + + - `getBitbucketCloudRequestOptions` now returns a `Promise` and **must** be awaited. + + - **@backstage/plugin-scaffolder-backend-module-bitbucket-cloud** (`src/actions/helpers.ts`) + - `getBitbucketClient` now returns a `Promise` and **must** be awaited. + - `getAuthorizationHeader` now returns a `Promise` and **must** be awaited. + + **OAuth usage example** + + ```yaml + integrations: + bitbucketCloud: + - clientId: client-id + clientSecret: client-secret + ``` + +### Patch Changes + +- a26a322: Added support for using a GitHub App installation to generate tokens for public repository access when the `publicAccess` option is enabled. When all other authentication methods fail (e.g., the app is not installed in that organization), the provider will now use an available installation to generate a token that can be used to access public repositories as read only. +- fb029b6: Updated luxon types +- e15fdae: Made the github urls case insensitive. + +## 1.18.3-next.1 + +### Patch Changes + +- fb029b6: Updated luxon types +- Updated dependencies + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + ## 1.18.3-next.0 ### Patch Changes diff --git a/packages/integration/config.d.ts b/packages/integration/config.d.ts index a601d63472..4278a8fcfe 100644 --- a/packages/integration/config.d.ts +++ b/packages/integration/config.d.ts @@ -174,7 +174,7 @@ export interface Config { * The username to use for authenticated requests. * @visibility secret */ - username: string; + username?: string; /** * Token used to authenticate requests. * @visibility secret @@ -186,6 +186,16 @@ export interface Config { * @deprecated Use `token` instead. */ appPassword?: string; + /** + * OAuth client ID for Bitbucket Cloud. + * @visibility secret + */ + clientId?: string; + /** + * OAuth client secret for Bitbucket Cloud. + * @visibility secret + */ + clientSecret?: string; /** * PGP signing key for signing commits. * @visibility secret @@ -330,6 +340,10 @@ export interface Config { * https://docs.github.com/en/rest/reference/apps#list-installations-for-the-authenticated-app--code-samples */ allowedInstallationOwners?: string[]; + /** + * If true, then an installation token will be issued for access when no other token is available. + */ + publicAccess?: boolean; }>; }>; diff --git a/packages/integration/package.json b/packages/integration/package.json index 41eeb67e06..a7f65efc9f 100644 --- a/packages/integration/package.json +++ b/packages/integration/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/integration", - "version": "1.18.3-next.0", + "version": "1.19.0", "description": "Helpers for managing integrations towards external systems", "backstage": { "role": "common-library" diff --git a/packages/integration/report.api.md b/packages/integration/report.api.md index f642058ccd..561dea979d 100644 --- a/packages/integration/report.api.md +++ b/packages/integration/report.api.md @@ -250,6 +250,8 @@ export type BitbucketCloudIntegrationConfig = { username?: string; appPassword?: string; token?: string; + clientId?: string; + clientSecret?: string; commitSigningKey?: string; }; @@ -450,12 +452,18 @@ export function getBitbucketCloudFileFetchUrl( config: BitbucketCloudIntegrationConfig, ): string; +// @public +export function getBitbucketCloudOAuthToken( + clientId: string, + clientSecret: string, +): Promise; + // @public export function getBitbucketCloudRequestOptions( config: BitbucketCloudIntegrationConfig, -): { +): Promise<{ headers: Record; -}; +}>; // @public @deprecated export function getBitbucketDefaultBranch( @@ -665,6 +673,7 @@ export type GithubAppConfig = { clientId: string; clientSecret: string; allowedInstallationOwners?: string[]; + publicAccess?: boolean; }; // @public diff --git a/packages/integration/src/azure/core.test.ts b/packages/integration/src/azure/core.test.ts index 601057e499..fbd6747f56 100644 --- a/packages/integration/src/azure/core.test.ts +++ b/packages/integration/src/azure/core.test.ts @@ -73,7 +73,7 @@ describe('azure core', () => { }, { url: 'com/a/b/blob/master/path/to/c.yaml', - error: 'Invalid URL: com/a/b/blob/master/path/to/c.yaml', + error: 'Invalid URL', }, ])('should handle error path %#', ({ url, error }) => { expect(() => getAzureFileFetchUrl(url)).toThrow(error); diff --git a/packages/integration/src/bitbucketCloud/config.test.ts b/packages/integration/src/bitbucketCloud/config.test.ts index 9488c8b5f7..57e8803a14 100644 --- a/packages/integration/src/bitbucketCloud/config.test.ts +++ b/packages/integration/src/bitbucketCloud/config.test.ts @@ -85,6 +85,39 @@ describe('readBitbucketCloudIntegrationConfig', () => { ).toThrow(/token/); }); + it('reads OAuth configuration', () => { + const output = readBitbucketCloudIntegrationConfig( + buildConfig({ + clientId: 'my-client-id', + clientSecret: 'my-client-secret', + }), + ); + expect(output).toEqual({ + host: BITBUCKET_CLOUD_HOST, + apiBaseUrl: BITBUCKET_CLOUD_API_BASE_URL, + clientId: 'my-client-id', + clientSecret: 'my-client-secret', + }); + }); + + it('rejects incomplete OAuth configuration', () => { + expect(() => + readBitbucketCloudIntegrationConfig( + buildConfig({ + clientId: 'my-client-id', + }), + ), + ).toThrow(/incomplete OAuth configuration/); + + expect(() => + readBitbucketCloudIntegrationConfig( + buildConfig({ + clientSecret: 'my-client-secret', + }), + ), + ).toThrow(/incomplete OAuth configuration/); + }); + it('credentials hidden on the frontend', async () => { const frontendConfig = await buildFrontendConfig({ token: 't', @@ -103,6 +136,24 @@ describe('readBitbucketCloudIntegrationConfig', () => { ]); }); + it('OAuth credentials hidden on the frontend', async () => { + const frontendConfig = await buildFrontendConfig({ + clientId: 'my-client-id', + clientSecret: 'my-client-secret', + }); + expect( + readBitbucketCloudIntegrationConfigs( + frontendConfig.getOptionalConfigArray('integrations.bitbucketCloud') ?? + [], + ), + ).toEqual([ + { + host: BITBUCKET_CLOUD_HOST, + apiBaseUrl: BITBUCKET_CLOUD_API_BASE_URL, + }, + ]); + }); + // TODO: appPassword can be removed once fully // deprecated by BitBucket on 9th June 2026. describe('handles deprecated appPassword', () => { diff --git a/packages/integration/src/bitbucketCloud/config.ts b/packages/integration/src/bitbucketCloud/config.ts index 0e08e95a79..e47b215f98 100644 --- a/packages/integration/src/bitbucketCloud/config.ts +++ b/packages/integration/src/bitbucketCloud/config.ts @@ -54,6 +54,20 @@ export type BitbucketCloudIntegrationConfig = { */ token?: string; + /** + * The OAuth client ID for Bitbucket Cloud. + * + * See https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/ + */ + clientId?: string; + + /** + * The OAuth client secret for Bitbucket Cloud. + * + * See https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/ + */ + clientSecret?: string; + /** PGP private key for signing commits. */ commitSigningKey?: string; }; @@ -71,24 +85,36 @@ export function readBitbucketCloudIntegrationConfig( const apiBaseUrl = BITBUCKET_CLOUD_API_BASE_URL; // If config is provided, we assume authenticated access is desired // (as the anonymous one is provided by default). - const username = config.getString('username'); + const username = config.getOptionalString('username'); // TODO: appPassword can be removed once fully // deprecated by BitBucket on 9th June 2026. const appPassword = config.getOptionalString('appPassword')?.trim(); const token = config.getOptionalString('token'); + const clientId = config.getOptionalString('clientId')?.trim(); + const clientSecret = config.getOptionalString('clientSecret')?.trim(); - if (!token && !appPassword) { + // Validate: if username is provided, token or appPassword is required + if (username && !token && !appPassword) { throw new Error( `Bitbucket Cloud integration must be configured with as username and either a token or an appPassword.`, ); } + // Validate: OAuth requires both clientId and clientSecret + if ((clientId && !clientSecret) || (clientSecret && !clientId)) { + throw new Error( + `Bitbucket Cloud integration has incomplete OAuth configuration. Both clientId and clientSecret are required.`, + ); + } + return { host, apiBaseUrl, username, appPassword, token, + clientId, + clientSecret, commitSigningKey: config.getOptionalString('commitSigningKey'), }; } diff --git a/packages/integration/src/bitbucketCloud/core.test.ts b/packages/integration/src/bitbucketCloud/core.test.ts index fa8fc2ae43..4f46b5ad42 100644 --- a/packages/integration/src/bitbucketCloud/core.test.ts +++ b/packages/integration/src/bitbucketCloud/core.test.ts @@ -28,13 +28,15 @@ import { // Mock constants const BITBUCKET_CLOUD_HOST = 'bitbucket.org'; const BITBUCKET_CLOUD_API_BASE_URL = 'https://api.bitbucket.org/2.0'; +const BITBUCKET_CLOUD_OAUTH_TOKEN_URL = + 'https://bitbucket.org/site/oauth2/access_token'; describe('bitbucketCloud core', () => { const worker = setupServer(); registerMswTestHooks(worker); describe('getBitbucketCloudRequestOptions', () => { - it('insert basic auth when needed', () => { + it('insert basic auth when needed', async () => { const withUsernameAndToken: BitbucketCloudIntegrationConfig = { host: BITBUCKET_CLOUD_HOST, apiBaseUrl: BITBUCKET_CLOUD_API_BASE_URL, @@ -54,20 +56,72 @@ describe('bitbucketCloud core', () => { apiBaseUrl: BITBUCKET_CLOUD_API_BASE_URL, }; expect( - (getBitbucketCloudRequestOptions(withUsernameAndToken).headers as any) + (await getBitbucketCloudRequestOptions(withUsernameAndToken)).headers .Authorization, ).toEqual('Basic c29tZS11c2VyQGRvbWFpbi5jb206bXktdG9rZW4='); expect( - ( - getBitbucketCloudRequestOptions(withUsernameAndPassword) - .headers as any - ).Authorization, + (await getBitbucketCloudRequestOptions(withUsernameAndPassword)).headers + .Authorization, ).toEqual('Basic c29tZS11c2VyOm15LXNlY3JldA=='); expect( - (getBitbucketCloudRequestOptions(withoutUsername).headers as any) + (await getBitbucketCloudRequestOptions(withoutUsername)).headers .Authorization, ).toBeUndefined(); }); + + it('handles OAuth token fetch errors', async () => { + // Test error handling + worker.use( + rest.post(BITBUCKET_CLOUD_OAUTH_TOKEN_URL, (_, res, ctx) => + res(ctx.status(401), ctx.json({ error: 'invalid_client' })), + ), + ); + + const withOAuth: BitbucketCloudIntegrationConfig = { + host: BITBUCKET_CLOUD_HOST, + apiBaseUrl: BITBUCKET_CLOUD_API_BASE_URL, + clientId: 'test-client-id', + clientSecret: 'test-client-secret', + }; + + await expect(getBitbucketCloudRequestOptions(withOAuth)).rejects.toThrow( + /Failed to fetch OAuth token/, + ); + }); + + it('uses OAuth Bearer token and caches it', async () => { + // Test OAuth + caching + let callCount = 0; + worker.use( + rest.post(BITBUCKET_CLOUD_OAUTH_TOKEN_URL, (_, res, ctx) => { + callCount++; + return res( + ctx.status(200), + ctx.json({ + access_token: 'test-oauth-token', + expires_in: 3600, + }), + ); + }), + ); + + const withOAuth: BitbucketCloudIntegrationConfig = { + host: BITBUCKET_CLOUD_HOST, + apiBaseUrl: BITBUCKET_CLOUD_API_BASE_URL, + clientId: 'test-client-id', + clientSecret: 'test-client-secret', + }; + + // First call should fetch token + const result1 = await getBitbucketCloudRequestOptions(withOAuth); + expect(result1.headers.Authorization).toEqual('Bearer test-oauth-token'); + expect(callCount).toBe(1); + + // Second call should use cached token (proves caching works) + const result2 = await getBitbucketCloudRequestOptions(withOAuth); + expect(result2.headers.Authorization).toEqual('Bearer test-oauth-token'); + expect(callCount).toBe(1); // Still 1, proving cache was used + }); }); describe('getBitbucketCloudFileFetchUrl', () => { diff --git a/packages/integration/src/bitbucketCloud/core.ts b/packages/integration/src/bitbucketCloud/core.ts index a97de872de..9beb3bd748 100644 --- a/packages/integration/src/bitbucketCloud/core.ts +++ b/packages/integration/src/bitbucketCloud/core.ts @@ -17,6 +17,100 @@ import fetch from 'cross-fetch'; import parseGitUrl from 'git-url-parse'; import { BitbucketCloudIntegrationConfig } from './config'; +import { DateTime } from 'luxon'; + +type OAuthTokenData = { + token: string; + expiresAt: DateTime; +}; + +// In-memory token cache (single entry since there's only one Bitbucket Cloud integration) +let cachedToken: OAuthTokenData | undefined; + +// Track in-flight token refresh request to prevent concurrent fetches +let refreshPromise: Promise | undefined; + +/** + * Fetches an OAuth access token from Bitbucket Cloud using client credentials flow. + * Tokens are cached with a 10-minute grace period to account for clock skew. + * Implements concurrent refresh protection to prevent multiple simultaneous token requests. + * + * @param clientId - OAuth client ID + * @param clientSecret - OAuth client secret + * @public + */ +export async function getBitbucketCloudOAuthToken( + clientId: string, + clientSecret: string, +): Promise { + // Check cache + if (cachedToken && DateTime.now() < cachedToken.expiresAt) { + return cachedToken.token; + } + + // Check if there's already a refresh in progress + if (refreshPromise) { + return refreshPromise; + } + + // Start a new token fetch and track it + refreshPromise = (async () => { + try { + // Fetch new token + const credentials = Buffer.from( + `${clientId}:${clientSecret}`, + 'utf8', + ).toString('base64'); + + const response = await fetch( + 'https://bitbucket.org/site/oauth2/access_token', + { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + Authorization: `Basic ${credentials}`, + }, + body: 'grant_type=client_credentials', + }, + ); + + if (!response.ok) { + throw new Error( + `Failed to fetch OAuth token from Bitbucket Cloud: ${response.status} ${response.statusText}`, + ); + } + + const data = await response.json(); + + if (!data.access_token) { + throw new Error('OAuth token response missing access_token field'); + } + + // Calculate expiration with 10-minute grace period + const expiresIn = data.expires_in || 3600; // Default to 1 hour + const expiresAt = DateTime.now() + .plus({ seconds: expiresIn }) + .minus({ minutes: 10 }); + + // Cache the token + cachedToken = { + token: data.access_token, + expiresAt, + }; + + return data.access_token; + } catch (error) { + throw new Error( + `Failed to fetch OAuth token for Bitbucket Cloud: ${error}`, + ); + } finally { + // Clean up the in-flight promise tracking + refreshPromise = undefined; + } + })(); + + return refreshPromise; +} /** * Given a URL pointing to a path on a provider, returns the default branch. @@ -34,7 +128,7 @@ export async function getBitbucketCloudDefaultBranch( const branchUrl = `${config.apiBaseUrl}/repositories/${project}/${repoName}`; const response = await fetch( branchUrl, - getBitbucketCloudRequestOptions(config), + await getBitbucketCloudRequestOptions(config), ); if (!response.ok) { @@ -118,18 +212,29 @@ export function getBitbucketCloudFileFetchUrl( /** * Gets the request options necessary to make requests to a given provider. * Returns headers for authenticating with Bitbucket Cloud. - * Supports both username/token and username/appPassword auth. + * Supports OAuth (clientId/clientSecret), username/token, and username/appPassword auth. * * @param config - The relevant provider config * @public */ -export function getBitbucketCloudRequestOptions( +export async function getBitbucketCloudRequestOptions( config: BitbucketCloudIntegrationConfig, -): { +): Promise<{ headers: Record; -} { +}> { const headers: Record = {}; + // OAuth authentication (clientId/clientSecret) + if (config.clientId && config.clientSecret) { + const token = await getBitbucketCloudOAuthToken( + config.clientId, + config.clientSecret, + ); + headers.Authorization = `Bearer ${token}`; + return { headers }; + } + + // Basic authentication (username + token/appPassword) // TODO: appPassword can be removed once fully // deprecated by BitBucket on 9th June 2026. if (config.username && (config.token ?? config.appPassword)) { diff --git a/packages/integration/src/bitbucketCloud/index.ts b/packages/integration/src/bitbucketCloud/index.ts index 7119d3ea90..d0c11136b3 100644 --- a/packages/integration/src/bitbucketCloud/index.ts +++ b/packages/integration/src/bitbucketCloud/index.ts @@ -24,5 +24,6 @@ export { getBitbucketCloudDefaultBranch, getBitbucketCloudDownloadUrl, getBitbucketCloudFileFetchUrl, + getBitbucketCloudOAuthToken, getBitbucketCloudRequestOptions, } from './core'; diff --git a/packages/integration/src/github/GithubIntegration.test.ts b/packages/integration/src/github/GithubIntegration.test.ts index c54d4db2ef..70f1c4a16c 100644 --- a/packages/integration/src/github/GithubIntegration.test.ts +++ b/packages/integration/src/github/GithubIntegration.test.ts @@ -134,24 +134,4 @@ describe('replaceGithubUrlType', () => { ), ).toBe('https://github.com/backstage/backstage/blob/tree/README.md'); }); - it('should replace with lowercase', () => { - expect( - replaceGithubUrlType( - 'https://githuB.com/backstage/backstage/blob/master/README.md', - 'edit', - ), - ).toBe('https://github.com/backstage/backstage/edit/master/README.md'); - expect( - replaceGithubUrlType( - 'https://github.com/Backstage/backstage/blob/master/README.md', - 'edit', - ), - ).toBe('https://github.com/backstage/backstage/edit/master/README.md'); - expect( - replaceGithubUrlType( - 'https://github.com/backstage/Backstage/blob/master/README.md', - 'edit', - ), - ).toBe('https://github.com/backstage/backstage/edit/master/README.md'); - }); }); diff --git a/packages/integration/src/github/GithubIntegration.ts b/packages/integration/src/github/GithubIntegration.ts index 79d5e7f421..880a2bed21 100644 --- a/packages/integration/src/github/GithubIntegration.ts +++ b/packages/integration/src/github/GithubIntegration.ts @@ -95,9 +95,7 @@ export function replaceGithubUrlType( return url.replace( /\/\/([^/]+)\/([^/]+)\/([^/]+)\/(blob|tree|edit)\//, (_, host, owner, repo) => { - return `//${host.toLocaleLowerCase('en-US')}/${owner.toLocaleLowerCase( - 'en-US', - )}/${repo.toLocaleLowerCase('en-US')}/${type}/`; + return `//${host}/${owner}/${repo}/${type}/`; }, ); } diff --git a/packages/integration/src/github/SingleInstanceGithubCredentialsProvider.test.ts b/packages/integration/src/github/SingleInstanceGithubCredentialsProvider.test.ts index 0468e96e14..fefccf22f6 100644 --- a/packages/integration/src/github/SingleInstanceGithubCredentialsProvider.test.ts +++ b/packages/integration/src/github/SingleInstanceGithubCredentialsProvider.test.ts @@ -563,4 +563,330 @@ describe('SingleInstanceGithubCredentialsProvider tests', () => { 2, ); }); + + describe('public access', () => { + it('should use an installation token when public access is enabled and owner is not in allowed list', async () => { + const githubProvider = SingleInstanceGithubCredentialsProvider.create({ + host: 'github.com', + apps: [ + { + appId: 1, + privateKey: 'privateKey', + webhookSecret: '123', + clientId: 'CLIENT_ID', + clientSecret: 'CLIENT_SECRET', + allowedInstallationOwners: ['other-org'], + publicAccess: true, + }, + ], + }); + + octokit.apps.listInstallations.mockResolvedValue({ + headers: { + etag: '123', + }, + data: [ + { + id: 1, + repository_selection: 'all', + account: { + login: 'other-org', + }, + }, + ], + } as RestEndpointMethodTypes['apps']['listInstallations']['response']); + + octokit.apps.createInstallationAccessToken.mockResolvedValueOnce({ + data: { + expires_at: DateTime.local().plus({ hours: 1 }).toString(), + token: 'public_access_token', + }, + } as RestEndpointMethodTypes['apps']['createInstallationAccessToken']['response']); + + const { token, headers, type } = await githubProvider.getCredentials({ + url: 'https://github.com/some-public-org/some-repo', + }); + + expect(type).toEqual('app'); + expect(token).toEqual('public_access_token'); + expect(headers).toEqual({ Authorization: 'Bearer public_access_token' }); + }); + + it('should use an installation token when public access is enabled and no installation exists for owner', async () => { + const githubProvider = SingleInstanceGithubCredentialsProvider.create({ + host: 'github.com', + apps: [ + { + appId: 1, + privateKey: 'privateKey', + webhookSecret: '123', + clientId: 'CLIENT_ID', + clientSecret: 'CLIENT_SECRET', + publicAccess: true, + }, + ], + }); + + octokit.apps.listInstallations.mockResolvedValue({ + headers: { + etag: '123', + }, + data: [ + { + id: 42, + repository_selection: 'all', + account: { + login: 'installed-org', + }, + }, + ], + } as RestEndpointMethodTypes['apps']['listInstallations']['response']); + + octokit.apps.createInstallationAccessToken.mockResolvedValueOnce({ + data: { + expires_at: DateTime.local().plus({ hours: 1 }).toString(), + token: 'public_installation_token', + }, + } as RestEndpointMethodTypes['apps']['createInstallationAccessToken']['response']); + + const { token, headers, type } = await githubProvider.getCredentials({ + url: 'https://github.com/non-installed-org/some-repo', + }); + + expect(type).toEqual('app'); + expect(token).toEqual('public_installation_token'); + expect(headers).toEqual({ + Authorization: 'Bearer public_installation_token', + }); + }); + + it('should not use public access when normal installation credentials are available', async () => { + const githubProvider = SingleInstanceGithubCredentialsProvider.create({ + host: 'github.com', + apps: [ + { + appId: 1, + privateKey: 'privateKey', + webhookSecret: '123', + clientId: 'CLIENT_ID', + clientSecret: 'CLIENT_SECRET', + publicAccess: true, + }, + ], + }); + + octokit.apps.listInstallations.mockResolvedValue({ + headers: { + etag: '123', + }, + data: [ + { + id: 1, + repository_selection: 'all', + account: { + login: 'backstage', + }, + }, + ], + } as RestEndpointMethodTypes['apps']['listInstallations']['response']); + + octokit.apps.createInstallationAccessToken.mockResolvedValueOnce({ + data: { + expires_at: DateTime.local().plus({ hours: 1 }).toString(), + token: 'normal_token', + }, + } as RestEndpointMethodTypes['apps']['createInstallationAccessToken']['response']); + + const { token, type } = await githubProvider.getCredentials({ + url: 'https://github.com/backstage/repo', + }); + + expect(type).toEqual('app'); + expect(token).toEqual('normal_token'); + // createInstallationAccessToken should only be called once for the normal flow + expect(octokit.apps.createInstallationAccessToken).toHaveBeenCalledTimes( + 1, + ); + }); + + it('should fall back to configured token when public access fails', async () => { + const githubProvider = SingleInstanceGithubCredentialsProvider.create({ + host: 'github.com', + apps: [ + { + appId: 1, + privateKey: 'privateKey', + webhookSecret: '123', + clientId: 'CLIENT_ID', + clientSecret: 'CLIENT_SECRET', + allowedInstallationOwners: ['other-org'], + publicAccess: true, + }, + ], + token: 'fallback_token', + }); + + octokit.apps.listInstallations.mockResolvedValue({ + headers: { + etag: '123', + }, + data: [], + } as unknown as RestEndpointMethodTypes['apps']['listInstallations']['response']); + + const { token, type } = await githubProvider.getCredentials({ + url: 'https://github.com/some-org/repo', + }); + + expect(type).toEqual('token'); + expect(token).toEqual('fallback_token'); + }); + + it('should return undefined when public access is disabled and no installation exists', async () => { + const githubProvider = SingleInstanceGithubCredentialsProvider.create({ + host: 'github.com', + apps: [ + { + appId: 1, + privateKey: 'privateKey', + webhookSecret: '123', + clientId: 'CLIENT_ID', + clientSecret: 'CLIENT_SECRET', + allowedInstallationOwners: ['other-org'], + // publicAccess is not set (defaults to false) + }, + ], + }); + + octokit.apps.listInstallations.mockResolvedValue({ + headers: { + etag: '123', + }, + data: [ + { + id: 1, + repository_selection: 'all', + account: { + login: 'other-org', + }, + }, + ], + } as RestEndpointMethodTypes['apps']['listInstallations']['response']); + + const { token, headers } = await githubProvider.getCredentials({ + url: 'https://github.com/some-org/repo', + }); + + expect(token).toBeUndefined(); + expect(headers).toBeUndefined(); + }); + + it('should cache public access tokens separately from regular tokens', async () => { + const githubProvider = SingleInstanceGithubCredentialsProvider.create({ + host: 'github.com', + apps: [ + { + appId: 1, + privateKey: 'privateKey', + webhookSecret: '123', + clientId: 'CLIENT_ID', + clientSecret: 'CLIENT_SECRET', + allowedInstallationOwners: ['installed-org'], + publicAccess: true, + }, + ], + }); + + octokit.apps.listInstallations.mockResolvedValue({ + headers: { + etag: '123', + }, + data: [ + { + id: 1, + repository_selection: 'all', + account: { + login: 'installed-org', + }, + }, + ], + } as RestEndpointMethodTypes['apps']['listInstallations']['response']); + + octokit.apps.createInstallationAccessToken.mockResolvedValue({ + data: { + expires_at: DateTime.local().plus({ hours: 1 }).toString(), + token: 'public_token', + }, + } as RestEndpointMethodTypes['apps']['createInstallationAccessToken']['response']); + + // First call for a public org + await githubProvider.getCredentials({ + url: 'https://github.com/public-org/repo', + }); + + // Second call for the same public org should use cached token + await githubProvider.getCredentials({ + url: 'https://github.com/public-org/repo', + }); + + // createInstallationAccessToken should only be called once due to caching + expect(octokit.apps.createInstallationAccessToken).toHaveBeenCalledTimes( + 1, + ); + }); + + it('should use public access with multiple apps when only one has publicAccess enabled', async () => { + const githubProvider = SingleInstanceGithubCredentialsProvider.create({ + host: 'github.com', + apps: [ + { + appId: 1, + privateKey: 'privateKey', + webhookSecret: '123', + clientId: 'CLIENT_ID', + clientSecret: 'CLIENT_SECRET', + allowedInstallationOwners: ['org-1'], + // publicAccess not set, defaults to false + }, + { + appId: 2, + privateKey: 'privateKey2', + webhookSecret: '456', + clientId: 'CLIENT_ID_2', + clientSecret: 'CLIENT_SECRET_2', + allowedInstallationOwners: ['org-2'], + publicAccess: true, + }, + ], + }); + + octokit.apps.listInstallations.mockResolvedValue({ + headers: { + etag: '123', + }, + data: [ + { + id: 1, + repository_selection: 'all', + account: { + login: 'org-2', + }, + }, + ], + } as RestEndpointMethodTypes['apps']['listInstallations']['response']); + + octokit.apps.createInstallationAccessToken.mockResolvedValueOnce({ + data: { + expires_at: DateTime.local().plus({ hours: 1 }).toString(), + token: 'public_access_from_app_2', + }, + } as RestEndpointMethodTypes['apps']['createInstallationAccessToken']['response']); + + const { token, type } = await githubProvider.getCredentials({ + url: 'https://github.com/unknown-org/repo', + }); + + expect(type).toEqual('app'); + expect(token).toEqual('public_access_from_app_2'); + }); + }); }); diff --git a/packages/integration/src/github/SingleInstanceGithubCredentialsProvider.ts b/packages/integration/src/github/SingleInstanceGithubCredentialsProvider.ts index d2c1e37a65..40d166b223 100644 --- a/packages/integration/src/github/SingleInstanceGithubCredentialsProvider.ts +++ b/packages/integration/src/github/SingleInstanceGithubCredentialsProvider.ts @@ -100,6 +100,7 @@ class GithubAppManager { private readonly baseAuthConfig: { appId: number; privateKey: string }; private readonly cache = new Cache(); private readonly allowedInstallationOwners: string[] | undefined; // undefined allows all installations + public readonly publicAccess: boolean; constructor(config: GithubAppConfig, baseUrl?: string) { this.allowedInstallationOwners = config.allowedInstallationOwners?.map( @@ -116,6 +117,7 @@ class GithubAppManager { authStrategy: createAppAuth, auth: this.baseAuthConfig, }); + this.publicAccess = config.publicAccess ?? false; } async getInstallationCredentials( @@ -170,6 +172,30 @@ class GithubAppManager { }); } + async getPublicInstallationToken(): Promise<{ accessToken: string }> { + const [installation] = await this.getInstallations(); + + if (!installation) { + throw new Error(`No installation found for public app`); + } + + return this.cache.getOrCreateToken( + `public:${installation.id}`, + undefined, + async () => { + const result = await this.appClient.apps.createInstallationAccessToken({ + installation_id: installation.id, + headers: HEADERS, + }); + + return { + token: result.data.token, + expiresAt: DateTime.fromISO(result.data.expires_at), + }; + }, + ); + } + getInstallations(): Promise< RestEndpointMethodTypes['apps']['listInstallations']['response']['data'] > { @@ -185,12 +211,14 @@ class GithubAppManager { inst.account.login?.toLocaleLowerCase('en-US') === owner.toLocaleLowerCase('en-US'), ); + if (installation) { return { installationId: installation.id, suspended: Boolean(installation.suspended_by), }; } + const notFoundError = new Error( `No app installation found for ${owner} in ${this.baseAuthConfig.appId}`, ); @@ -245,10 +273,26 @@ export class GithubAppCredentialsMux { const result = results.find( resultItem => resultItem.credentials?.accessToken, ); + if (result) { return result.credentials!.accessToken; } + // If there was no token returned, then let's find a public access app and use an installation to get a token. + const publicAccessApp = this.apps.find(app => app.publicAccess); + if (publicAccessApp) { + const publicResult = await publicAccessApp + .getPublicInstallationToken() + .then( + credentials => ({ credentials, error: undefined }), + error => ({ credentials: undefined, error }), + ); + + if (publicResult.credentials?.accessToken) { + return publicResult.credentials.accessToken; + } + } + const errors = results.map(r => r.error); const notNotFoundError = errors.find(err => err?.name !== 'NotFoundError'); if (notNotFoundError) { diff --git a/packages/integration/src/github/config.ts b/packages/integration/src/github/config.ts index 74a0267d62..f755b84c2a 100644 --- a/packages/integration/src/github/config.ts +++ b/packages/integration/src/github/config.ts @@ -109,6 +109,10 @@ export type GithubAppConfig = { * https://docs.github.com/en/rest/reference/apps#list-installations-for-the-authenticated-app--code-samples */ allowedInstallationOwners?: string[]; + /** + * If true, then an installation token will be issued for access when no other token is available. + */ + publicAccess?: boolean; }; /** @@ -133,6 +137,7 @@ export function readGithubIntegrationConfig( allowedInstallationOwners: c.getOptionalStringArray( 'allowedInstallationOwners', ), + publicAccess: c.getOptionalBoolean('publicAccess'), })); if (!isValidHost(host)) { diff --git a/packages/repo-tools/CHANGELOG.md b/packages/repo-tools/CHANGELOG.md index 36723eaecf..80904e4d06 100644 --- a/packages/repo-tools/CHANGELOG.md +++ b/packages/repo-tools/CHANGELOG.md @@ -1,5 +1,40 @@ # @backstage/repo-tools +## 0.16.1 + +### Patch Changes + +- 688f070: Updated to use new utilities from `@backstage/cli-common`. +- 85895f9: Updates OpenAPI generator templates to preserve original property names (like 'group-name', 'user-id') from OpenAPI specs when propertyNaming=original is specified. Previously, these were always converted to camelCase regardless of the propertyNaming setting. + + - Updates modelGeneric.mustache templates in both client and server generators + - Updates modelTaggedUnion.mustache templates in both client and server generators + - Uses {{baseName}} when available, falls back to {{name}} for backward compatibility + - Maintains backward compatibility - no changes when propertyNaming=original is not used + +- 2bae83a: Bump `@microsoft/api-documenter` and `@microsoft/api-extractor` to latest versions. +- d1e38a7: Properly create workspace in OS temporary directory for `generate-patch` command +- 2bae83a: Bumped dev dependencies `@types/node` +- Updated dependencies + - @backstage/cli-node@0.2.16 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/cli-common@0.1.16 + - @backstage/config-loader@1.10.7 + +## 0.16.1-next.2 + +### Patch Changes + +- 2bae83a: Bump `@microsoft/api-documenter` and `@microsoft/api-extractor` to latest versions. +- 2bae83a: Bumped dev dependencies `@types/node` +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config-loader@1.10.7-next.1 + - @backstage/cli-common@0.1.16-next.2 + - @backstage/catalog-model@1.7.6 + - @backstage/cli-node@0.2.16-next.1 + - @backstage/errors@1.2.7 + ## 0.16.1-next.1 ### Patch Changes diff --git a/packages/repo-tools/package.json b/packages/repo-tools/package.json index 8fb56a229a..8cf1b48d06 100644 --- a/packages/repo-tools/package.json +++ b/packages/repo-tools/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/repo-tools", - "version": "0.16.1-next.1", + "version": "0.16.1", "description": "CLI for Backstage repo tooling ", "backstage": { "role": "cli" diff --git a/packages/scaffolder-internal/CHANGELOG.md b/packages/scaffolder-internal/CHANGELOG.md index 26f3232259..35db413d8f 100644 --- a/packages/scaffolder-internal/CHANGELOG.md +++ b/packages/scaffolder-internal/CHANGELOG.md @@ -1,5 +1,13 @@ # @internal/scaffolder +## 0.0.16 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/plugin-scaffolder-react@1.19.4 + ## 0.0.16-next.0 ### Patch Changes diff --git a/packages/scaffolder-internal/package.json b/packages/scaffolder-internal/package.json index 94ec12f591..98d76bb84e 100644 --- a/packages/scaffolder-internal/package.json +++ b/packages/scaffolder-internal/package.json @@ -1,6 +1,6 @@ { "name": "@internal/scaffolder", - "version": "0.0.16-next.0", + "version": "0.0.16", "backstage": { "role": "web-library", "inline": true diff --git a/packages/techdocs-cli-embedded-app/CHANGELOG.md b/packages/techdocs-cli-embedded-app/CHANGELOG.md index 455f18d38f..825252391b 100644 --- a/packages/techdocs-cli-embedded-app/CHANGELOG.md +++ b/packages/techdocs-cli-embedded-app/CHANGELOG.md @@ -1,5 +1,63 @@ # techdocs-cli-embedded-app +## 0.2.116-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/ui@0.11.0-next.0 + - @backstage/cli@0.35.2-next.0 + - @backstage/app-defaults@1.7.3 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/core-app-api@1.19.3 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/integration-react@1.2.13 + - @backstage/test-utils@1.7.14 + - @backstage/theme@0.7.1 + - @backstage/plugin-catalog@1.32.1 + - @backstage/plugin-techdocs@1.16.1 + - @backstage/plugin-techdocs-react@1.3.6 + +## 0.2.115 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.19.3 + - @backstage/cli@0.35.0 + - @backstage/ui@0.10.0 + - @backstage/plugin-techdocs@1.16.1 + - @backstage/plugin-catalog@1.32.1 + - @backstage/core-components@0.18.4 + - @backstage/test-utils@1.7.14 + - @backstage/core-plugin-api@1.12.1 + - @backstage/theme@0.7.1 + - @backstage/app-defaults@1.7.3 + - @backstage/integration-react@1.2.13 + - @backstage/plugin-techdocs-react@1.3.6 + +## 0.2.115-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.19.3-next.1 + - @backstage/cli@0.35.0-next.2 + - @backstage/plugin-techdocs@1.16.1-next.2 + - @backstage/plugin-catalog@1.32.1-next.1 + - @backstage/core-components@0.18.4-next.2 + - @backstage/app-defaults@1.7.3-next.0 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/integration-react@1.2.13-next.0 + - @backstage/test-utils@1.7.14-next.0 + - @backstage/theme@0.7.1-next.0 + - @backstage/ui@0.10.0-next.1 + - @backstage/plugin-techdocs-react@1.3.6-next.0 + ## 0.2.115-next.1 ### Patch Changes diff --git a/packages/techdocs-cli-embedded-app/package.json b/packages/techdocs-cli-embedded-app/package.json index a8a3ba85f4..151be92be9 100644 --- a/packages/techdocs-cli-embedded-app/package.json +++ b/packages/techdocs-cli-embedded-app/package.json @@ -1,6 +1,6 @@ { "name": "techdocs-cli-embedded-app", - "version": "0.2.115-next.1", + "version": "0.2.116-next.0", "backstage": { "role": "frontend" }, diff --git a/packages/techdocs-cli-embedded-app/src/LiveReloadAddon.test.tsx b/packages/techdocs-cli-embedded-app/src/LiveReloadAddon.test.tsx index 1a80def9e9..ec99f405ae 100644 --- a/packages/techdocs-cli-embedded-app/src/LiveReloadAddon.test.tsx +++ b/packages/techdocs-cli-embedded-app/src/LiveReloadAddon.test.tsx @@ -15,7 +15,7 @@ */ import { render } from '@testing-library/react'; -import { TechDocsLiveReload } from './LiveReloadAddon'; +import { TechDocsLiveReload, utils } from './LiveReloadAddon'; jest.mock('@backstage/plugin-techdocs-react', () => ({ useShadowRootElements: jest.fn(() => [ @@ -38,12 +38,11 @@ jest.mock('@backstage/plugin-techdocs-react', () => ({ describe('TechDocsLiveReload', () => { const originalXHR = global.XMLHttpRequest; - let originalLocation: Location; let openSpy: jest.Mock; let sendSpy: jest.Mock; + let reloadPageSpy: jest.SpyInstance; beforeEach(() => { - originalLocation = window.location; openSpy = jest.fn(); sendSpy = jest.fn(function (this: any) { // simulate long-poll response that does NOT trigger reload (epoch unchanged) @@ -65,9 +64,11 @@ describe('TechDocsLiveReload', () => { global.XMLHttpRequest = MockXHR as any; - // Replace window.location with a mutable object for tests - delete (window as any).location; - (window as any).location = { ...originalLocation, reload: jest.fn() }; + // Spy on the utils object's reloadPage method + reloadPageSpy = jest + .spyOn(utils, 'reloadPage') + .mockImplementation(() => {}); + jest.spyOn(window, 'addEventListener').mockImplementation(() => {}); jest.spyOn(window, 'removeEventListener').mockImplementation(() => {}); Object.defineProperty(document, 'visibilityState', { @@ -79,23 +80,17 @@ describe('TechDocsLiveReload', () => { afterEach(() => { global.XMLHttpRequest = originalXHR; jest.restoreAllMocks(); - // restore original window.location - delete (window as any).location; - (window as any).location = originalLocation; }); it('polls livereload endpoint and does not reload when epoch unchanged', async () => { - const reloadSpy = window.location.reload as unknown as jest.Mock; render(); expect(openSpy).toHaveBeenCalledWith('GET', '/.livereload/10/1'); // give microtask queue a tick await new Promise(res => setTimeout(res, 0)); - expect(reloadSpy).not.toHaveBeenCalled(); + expect(reloadPageSpy).not.toHaveBeenCalled(); }); it('reloads when server epoch increases', async () => { - const reloadSpy = window.location.reload as unknown as jest.Mock; - sendSpy.mockImplementation(function (this: any) { setTimeout(() => { (this as any).status = 200; @@ -106,6 +101,6 @@ describe('TechDocsLiveReload', () => { render(); await new Promise(res => setTimeout(res, 0)); - expect(reloadSpy).toHaveBeenCalled(); + expect(reloadPageSpy).toHaveBeenCalled(); }); }); diff --git a/packages/techdocs-cli-embedded-app/src/LiveReloadAddon.tsx b/packages/techdocs-cli-embedded-app/src/LiveReloadAddon.tsx index 905a339c72..393704da97 100644 --- a/packages/techdocs-cli-embedded-app/src/LiveReloadAddon.tsx +++ b/packages/techdocs-cli-embedded-app/src/LiveReloadAddon.tsx @@ -17,6 +17,13 @@ import { useShadowRootElements } from '@backstage/plugin-techdocs-react'; import { useEffect, useRef } from 'react'; +/** @internal Exported for testing - allows spying on reloads without spying + * on window.location. + */ +export const utils = { + reloadPage: () => window.location.reload(), +}; + interface TechDocsLiveReloadProps { /** Whether to enable livereload (default: true in development) */ enabled?: boolean; @@ -69,7 +76,7 @@ export const TechDocsLiveReload = ({ reqRef.current = new XMLHttpRequest(); reqRef.current.onloadend = function handleLoadEnd(this: XMLHttpRequest) { if (parseFloat(this.responseText) > epoch) { - window.location.reload(); + utils.reloadPage(); } else { timeoutRef.current = setTimeout(poll, this.status === 200 ? 0 : 3000); } diff --git a/packages/techdocs-cli/CHANGELOG.md b/packages/techdocs-cli/CHANGELOG.md index 7ab69cbd97..0c0e893438 100644 --- a/packages/techdocs-cli/CHANGELOG.md +++ b/packages/techdocs-cli/CHANGELOG.md @@ -1,5 +1,39 @@ # @techdocs/cli +## 1.10.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.14.1-next.0 + - @backstage/catalog-model@1.7.6 + - @backstage/cli-common@0.1.16 + - @backstage/config@1.3.6 + - @backstage/plugin-techdocs-node@1.13.10 + +## 1.10.3 + +### Patch Changes + +- 43629b1: Updated to use new utilities from `@backstage/cli-common`. +- 2bae83a: Bumped dev dependencies `@types/node` +- Updated dependencies + - @backstage/backend-defaults@0.14.0 + - @backstage/plugin-techdocs-node@1.13.10 + - @backstage/cli-common@0.1.16 + +## 1.10.3-next.2 + +### Patch Changes + +- 2bae83a: Bumped dev dependencies `@types/node` +- Updated dependencies + - @backstage/backend-defaults@0.14.0-next.1 + - @backstage/plugin-techdocs-node@1.13.10-next.1 + - @backstage/cli-common@0.1.16-next.2 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + ## 1.10.3-next.1 ### Patch Changes diff --git a/packages/techdocs-cli/package.json b/packages/techdocs-cli/package.json index d8aff1bc89..2924f1deb1 100644 --- a/packages/techdocs-cli/package.json +++ b/packages/techdocs-cli/package.json @@ -1,6 +1,6 @@ { "name": "@techdocs/cli", - "version": "1.10.3-next.1", + "version": "1.10.4-next.0", "description": "Utility CLI for managing TechDocs sites in Backstage.", "backstage": { "role": "cli" diff --git a/packages/test-utils/CHANGELOG.md b/packages/test-utils/CHANGELOG.md index 0d2d782969..71c5aca50a 100644 --- a/packages/test-utils/CHANGELOG.md +++ b/packages/test-utils/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/test-utils +## 1.7.14 + +### Patch Changes + +- 97cd16f: Internal update of translation imports. +- Updated dependencies + - @backstage/core-app-api@1.19.3 + - @backstage/core-plugin-api@1.12.1 + - @backstage/theme@0.7.1 + - @backstage/plugin-permission-react@0.4.39 + ## 1.7.14-next.0 ### Patch Changes diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index e14805b620..2e12255bd0 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/test-utils", - "version": "1.7.14-next.0", + "version": "1.7.14", "description": "Utilities to test Backstage plugins and apps.", "backstage": { "role": "web-library" diff --git a/packages/test-utils/src/testUtils/apis/FetchApi/MockFetchApi.ts b/packages/test-utils/src/testUtils/apis/FetchApi/MockFetchApi.ts index 3d02db0124..661d202379 100644 --- a/packages/test-utils/src/testUtils/apis/FetchApi/MockFetchApi.ts +++ b/packages/test-utils/src/testUtils/apis/FetchApi/MockFetchApi.ts @@ -127,7 +127,9 @@ function baseImplementation( ): typeof crossFetch { const implementation = options?.baseImplementation; if (!implementation) { - return crossFetch; + // Return a wrapper that evaluates global.fetch at call time, not construction time. + // This allows MSW to patch global.fetch after MockFetchApi is constructed. + return (input, init) => global.fetch(input, init); } else if (implementation === 'none') { return () => Promise.resolve(new Response()); } diff --git a/packages/test-utils/src/testUtils/appWrappers.test.tsx b/packages/test-utils/src/testUtils/appWrappers.test.tsx index 42a3f8e092..158499374e 100644 --- a/packages/test-utils/src/testUtils/appWrappers.test.tsx +++ b/packages/test-utils/src/testUtils/appWrappers.test.tsx @@ -92,17 +92,15 @@ describe('wrapInTestApp', () => { }); expect(error).toEqual([ - expect.objectContaining({ - detail: new Error( - 'MockErrorApi received unexpected error, Error: NOPE', - ), - }), - expect.objectContaining({ - detail: new Error( - 'MockErrorApi received unexpected error, Error: NOPE', - ), - }), - expect.stringMatching(/^The above error occurred in the component:/), + expect.stringContaining( + 'Error: MockErrorApi received unexpected error, Error: NOPE', + ), + expect.objectContaining({ type: 'unhandled-exception' }), + expect.stringContaining( + 'Error: MockErrorApi received unexpected error, Error: NOPE', + ), + expect.objectContaining({ type: 'unhandled-exception' }), + expect.stringContaining('The above error occurred in the component:'), ]); }); diff --git a/packages/theme/CHANGELOG.md b/packages/theme/CHANGELOG.md index 3eb2340d47..bbe9ae3fc9 100644 --- a/packages/theme/CHANGELOG.md +++ b/packages/theme/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/theme +## 0.7.1 + +### Patch Changes + +- fa06f6b: Added a `themeName` prop to `UnifiedThemeProvider`, enabling Backstage UI `data-theme-name` CSS attribute to be set based on active theme. + ## 0.7.1-next.0 ### Patch Changes diff --git a/packages/theme/package.json b/packages/theme/package.json index cc0fe2237a..645255d601 100644 --- a/packages/theme/package.json +++ b/packages/theme/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/theme", - "version": "0.7.1-next.0", + "version": "0.7.1", "description": "material-ui theme for use with Backstage.", "backstage": { "role": "web-library" diff --git a/packages/ui/CHANGELOG.md b/packages/ui/CHANGELOG.md index 9f867ba2ed..c692731a10 100644 --- a/packages/ui/CHANGELOG.md +++ b/packages/ui/CHANGELOG.md @@ -1,5 +1,80 @@ # @backstage/ui +## 0.11.0-next.0 + +### Minor Changes + +- 4ea1d15: **BREAKING**: Renamed CSS variable `--bui-bg` to `--bui-bg-surface-0` for consistency. + +### Patch Changes + +- 1880402: Fixes app background color on dark mode. +- 9c76682: build(deps-dev): bump `storybook` from 10.1.9 to 10.1.10 +- b4a4911: Fixed SearchField `startCollapsed` prop not working correctly in Backstage UI. The field now properly starts in a collapsed state, expands when clicked and focused, and collapses back when unfocused with no input. Also fixed CSS logic to work correctly in all layout contexts (flex row, flex column, and regular containers). + + Affected components: SearchField + +## 0.10.0 + +### Minor Changes + +- 16543fa: **Breaking change** The `Cell` component has been refactored to be a generic wrapper component that accepts `children` for custom cell content. The text-specific functionality (previously part of `Cell`) has been moved to a new `CellText` component. + + ### Migration Guide + + If you were using `Cell` with text-specific props (`title`, `description`, `leadingIcon`, `href`), you need to update your code to use `CellText` instead: + + **Before:** + + ```tsx + } + href="/path" + /> + ``` + + **After:** + + ```tsx + } + href="/path" + /> + ``` + + For custom cell content, use the new generic `Cell` component: + + ```tsx + {/* Your custom content */} + ``` + +### Patch Changes + +- 50b7927: Fixed Checkbox indicator showing checkmark color when unchecked. + + Affected components: Checkbox + +- 5bacf55: Fixed `ButtonIcon` incorrectly applying `className` to inner elements instead of only the root element. + + Affected components: ButtonIcon + +- b3ad928: Fixed Table Row component to correctly handle cases where no `href` is provided, preventing unnecessary router provider wrapping and fixing the cursor incorrectly showing as a pointer despite the element not being a link. + + Affected components: Row + +- a20d317: Added row selection support with visual state styling for hover, selected, and pressed states. Fixed checkbox rendering to only show for multi-select toggle mode. + + Affected components: Table, TableHeader, Row, Column + +- fe7c751: Fixed `useTable` hook to prioritize `providedRowCount` over data length for accurate row count in server-side pagination scenarios. +- c145031: Fixed Table column sorting indicator to show up arrow when no sort is active, correctly indicating that clicking will sort ascending. + + Affected components: Column + ## 0.10.0-next.1 ### Minor Changes diff --git a/packages/ui/css/styles.css b/packages/ui/css/styles.css index c96eda05c9..f79b954080 100644 --- a/packages/ui/css/styles.css +++ b/packages/ui/css/styles.css @@ -51,9 +51,10 @@ --bui-gray-6: #8c8c8c; --bui-gray-7: #757575; --bui-gray-8: #595959; - --bui-bg: var(--bui-gray-1); + --bui-bg-surface-0: var(--bui-gray-1); --bui-bg-surface-1: var(--bui-white); - --bui-bg-surface-2: var(--bui-gray-2); + --bui-bg-surface-2: var(--bui-gray-1); + --bui-bg-surface-3: var(--bui-gray-2); --bui-bg-solid: #1f5493; --bui-bg-solid-hover: #163a66; --bui-bg-solid-pressed: #0f2b4e; @@ -99,9 +100,10 @@ --bui-gray-6: #7b7b7b; --bui-gray-7: #9e9e9e; --bui-gray-8: #b4b4b4; - --bui-bg: #333; - --bui-bg-surface-1: #424242; + --bui-bg-surface-0: #333; + --bui-bg-surface-1: var(--bui-gray-1); --bui-bg-surface-2: var(--bui-gray-2); + --bui-bg-surface-3: var(--bui-gray-3); --bui-bg-solid: #9cc9ff; --bui-bg-solid-hover: #83b9fd; --bui-bg-solid-pressed: #83b9fd; @@ -239,7 +241,7 @@ } body { - background-color: var(--bui-bg); + background-color: var(--bui-bg-surface-0); color: var(--bui-fg-primary); font-family: var(--bui-font-regular); font-weight: var(--bui-font-weight-regular); diff --git a/packages/ui/package.json b/packages/ui/package.json index 3ac6e991c8..a5461c6726 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/ui", - "version": "0.10.0-next.1", + "version": "0.11.0-next.0", "backstage": { "role": "web-library" }, @@ -50,7 +50,7 @@ "@types/react": "^18.0.0", "@types/react-dom": "^18.0.0", "chalk": "^5.4.1", - "eslint-plugin-storybook": "^9.1.7", + "eslint-plugin-storybook": "^10.1.9", "glob": "^11.0.1", "globals": "^15.11.0", "lightningcss": "^1.29.1", @@ -58,7 +58,7 @@ "react": "^18.0.2", "react-dom": "^18.0.2", "react-router-dom": "^6.3.0", - "storybook": "^9.1.7" + "storybook": "^10.1.10" }, "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0", diff --git a/packages/ui/src/components/Accordion/Accordion.stories.tsx b/packages/ui/src/components/Accordion/Accordion.stories.tsx index 6640bd5d6a..541cce5c84 100644 --- a/packages/ui/src/components/Accordion/Accordion.stories.tsx +++ b/packages/ui/src/components/Accordion/Accordion.stories.tsx @@ -13,8 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -import type { Meta, StoryObj } from '@storybook/react-vite'; +import preview from '../../../../../.storybook/preview'; import { Accordion, AccordionTrigger, @@ -36,15 +35,12 @@ const Content = () => ( ); -const meta = { +const meta = preview.meta({ title: 'Backstage UI/Accordion', component: Accordion, -} satisfies Meta; +}); -export default meta; -type Story = StoryObj; - -export const Default: Story = { +export const Default = meta.story({ render: () => ( @@ -53,9 +49,9 @@ export const Default: Story = { ), -}; +}); -export const WithSubtitle: Story = { +export const WithSubtitle = meta.story({ render: () => ( ), -}; +}); -export const CustomTrigger: Story = { +export const CustomTrigger = meta.story({ render: () => ( @@ -87,9 +83,9 @@ export const CustomTrigger: Story = { ), -}; +}); -export const DefaultExpanded: Story = { +export const DefaultExpanded = meta.story({ render: () => ( @@ -98,9 +94,9 @@ export const DefaultExpanded: Story = { ), -}; +}); -export const GroupSingleOpen: Story = { +export const GroupSingleOpen = meta.story({ render: () => ( @@ -136,9 +132,9 @@ export const GroupSingleOpen: Story = { ), -}; +}); -export const GroupMultipleOpen: Story = { +export const GroupMultipleOpen = meta.story({ render: () => ( @@ -174,4 +170,4 @@ export const GroupMultipleOpen: Story = { ), -}; +}); diff --git a/packages/ui/src/components/Avatar/Avatar.stories.tsx b/packages/ui/src/components/Avatar/Avatar.stories.tsx index 582d82393e..75c1e68a67 100644 --- a/packages/ui/src/components/Avatar/Avatar.stories.tsx +++ b/packages/ui/src/components/Avatar/Avatar.stories.tsx @@ -13,36 +13,32 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -import type { Meta, StoryObj } from '@storybook/react-vite'; +import preview from '../../../../../.storybook/preview'; import { Avatar } from './index'; import { Flex, Text } from '../..'; -const meta = { +const meta = preview.meta({ title: 'Backstage UI/Avatar', component: Avatar, -} satisfies Meta; +}); -export default meta; -type Story = StoryObj; - -export const Default: Story = { +export const Default = meta.story({ args: { src: 'https://avatars.githubusercontent.com/u/1540635?v=4', name: 'Charles de Dreuille', }, -}; +}); -export const Fallback: Story = { +export const Fallback = meta.story({ args: { - ...Default.args, + ...Default.input.args, src: 'https://avatars.githubusercontent.com/u/15406AAAAAAAAA', }, -}; +}); -export const Sizes: Story = { +export const Sizes = meta.story({ args: { - ...Default.args, + ...Default.input.args, }, render: args => ( @@ -62,11 +58,11 @@ export const Sizes: Story = { ), -}; +}); -export const Purpose: Story = { +export const Purpose = meta.story({ args: { - ...Default.args, + ...Default.input.args, }, render: args => ( @@ -93,4 +89,4 @@ export const Purpose: Story = { ), -}; +}); diff --git a/packages/ui/src/components/Box/Box.stories.tsx b/packages/ui/src/components/Box/Box.stories.tsx index 6637f45740..766a6668c7 100644 --- a/packages/ui/src/components/Box/Box.stories.tsx +++ b/packages/ui/src/components/Box/Box.stories.tsx @@ -1,3 +1,4 @@ +import preview from '../../../../../.storybook/preview'; /* * Copyright 2024 The Backstage Authors * @@ -15,11 +16,10 @@ */ import { ReactNode } from 'react'; -import type { Meta, StoryObj } from '@storybook/react-vite'; import { Box } from './Box'; import { Flex } from '../Flex'; -const meta = { +const meta = preview.meta({ title: 'Backstage UI/Box', component: Box, argTypes: { @@ -31,10 +31,7 @@ const meta = { control: false, }, }, -} satisfies Meta; - -export default meta; -type Story = StoryObj; +}); const diagonalStripePattern = (() => { const svg = ` @@ -47,7 +44,7 @@ const diagonalStripePattern = (() => { return `data:image/svg+xml,${encodeURIComponent(svg)}`; })(); -export const Default: Story = { +export const Default = meta.story({ args: { width: '64px', height: '64px', @@ -63,10 +60,10 @@ export const Default: Story = { color: '#2563eb', }, }, -}; +}); -export const Margin: Story = { - args: { ...Default.args }, +export const Margin = meta.story({ + args: { ...Default.input.args }, render: args => ( @@ -89,10 +86,10 @@ export const Margin: Story = { ), -}; +}); -export const ResponsiveMargin: Story = { - args: { ...Default.args }, +export const ResponsiveMargin = meta.story({ + args: { ...Default.input.args }, render: args => ( @@ -115,10 +112,10 @@ export const ResponsiveMargin: Story = { ), -}; +}); -export const CustomMargin: Story = { - args: { ...Default.args }, +export const CustomMargin = meta.story({ + args: { ...Default.input.args }, render: args => ( @@ -141,10 +138,10 @@ export const CustomMargin: Story = { ), -}; +}); -export const CustomResponsiveMargin: Story = { - args: { ...Default.args }, +export const CustomResponsiveMargin = meta.story({ + args: { ...Default.input.args }, render: args => ( @@ -167,10 +164,10 @@ export const CustomResponsiveMargin: Story = { ), -}; +}); -export const Padding: Story = { - args: { ...Default.args }, +export const Padding = meta.story({ + args: { ...Default.input.args }, render: args => ( @@ -193,10 +190,10 @@ export const Padding: Story = { ), -}; +}); -export const ResponsivePadding: Story = { - args: { ...Default.args }, +export const ResponsivePadding = meta.story({ + args: { ...Default.input.args }, render: args => ( ), -}; +}); -export const CustomPadding: Story = { - args: { ...Default.args }, +export const CustomPadding = meta.story({ + args: { ...Default.input.args }, render: args => ( @@ -263,10 +260,10 @@ export const CustomPadding: Story = { ), -}; +}); -export const CustomResponsivePadding: Story = { - args: { ...Default.args }, +export const CustomResponsivePadding = meta.story({ + args: { ...Default.input.args }, render: args => ( ), -}; +}); const CardDisplay = ({ children }: { children?: ReactNode }) => { return ( @@ -327,7 +324,7 @@ const CardDisplay = ({ children }: { children?: ReactNode }) => { ); }; -export const Display: Story = { +export const Display = meta.story({ render: args => ( @@ -346,4 +343,4 @@ export const Display: Story = { ), -}; +}); diff --git a/packages/ui/src/components/Button/Button.stories.tsx b/packages/ui/src/components/Button/Button.stories.tsx index 4734770aa4..141db4da96 100644 --- a/packages/ui/src/components/Button/Button.stories.tsx +++ b/packages/ui/src/components/Button/Button.stories.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Backstage Authors + * Copyright 2025 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,15 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -import type { Meta, StoryObj } from '@storybook/react-vite'; +import preview from '../../../../../.storybook/preview'; import { Button } from './Button'; import { Flex } from '../Flex'; import { Text } from '../Text'; import { RiArrowRightSLine, RiCloudLine } from '@remixicon/react'; import { useState } from 'react'; -const meta = { +const meta = preview.meta({ title: 'Backstage UI/Button', component: Button, argTypes: { @@ -34,18 +33,15 @@ const meta = { options: ['primary', 'secondary'], }, }, -} satisfies Meta; +}); -export default meta; -type Story = StoryObj; - -export const Default: Story = { +export const Default = meta.story({ args: { children: 'Button', }, -}; +}); -export const Variants: Story = { +export const Variants = meta.story({ args: { children: 'Button', }, @@ -69,9 +65,9 @@ export const Variants: Story = { ), -}; +}); -export const Sizes: Story = { +export const Sizes = meta.story({ args: { children: 'Button', }, @@ -85,9 +81,9 @@ export const Sizes: Story = { ), -}; +}); -export const WithIcons: Story = { +export const WithIcons = meta.story({ args: { children: 'Button', }, @@ -102,9 +98,9 @@ export const WithIcons: Story = { /> ), -}; +}); -export const FullWidth: Story = { +export const FullWidth = meta.story({ args: { children: 'Button', }, @@ -119,9 +115,9 @@ export const FullWidth: Story = { /> ), -}; +}); -export const Disabled: Story = { +export const Disabled = meta.story({ render: () => ( ), -}; +}); -export const Responsive: Story = { +export const Responsive = meta.story({ args: { children: 'Button', variant: { @@ -149,12 +145,12 @@ export const Responsive: Story = { sm: 'medium', }, }, -}; +}); const variants = ['primary', 'secondary'] as const; const sizes = ['small', 'medium'] as const; -export const Playground: Story = { +export const Playground = meta.story({ args: { children: 'Button', }, @@ -212,9 +208,9 @@ export const Playground: Story = { ))} ), -}; +}); -export const Loading: Story = { +export const Loading = meta.story({ render: () => { const [isLoading, setIsLoading] = useState(false); @@ -231,9 +227,9 @@ export const Loading: Story = { ); }, -}; +}); -export const LoadingVariants: Story = { +export const LoadingVariants = meta.story({ render: () => ( Primary @@ -289,4 +285,4 @@ export const LoadingVariants: Story = { ), -}; +}); diff --git a/packages/ui/src/components/ButtonIcon/ButtonIcon.stories.tsx b/packages/ui/src/components/ButtonIcon/ButtonIcon.stories.tsx index 97072c3664..be6dad7754 100644 --- a/packages/ui/src/components/ButtonIcon/ButtonIcon.stories.tsx +++ b/packages/ui/src/components/ButtonIcon/ButtonIcon.stories.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Backstage Authors + * Copyright 2025 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,15 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -import type { Meta, StoryObj } from '@storybook/react-vite'; +import preview from '../../../../../.storybook/preview'; import { ButtonIcon } from './ButtonIcon'; import { Flex } from '../Flex'; import { Text } from '../Text'; import { RiCloudLine } from '@remixicon/react'; import { useState } from 'react'; -const meta = { +const meta = preview.meta({ title: 'Backstage UI/ButtonIcon', component: ButtonIcon, argTypes: { @@ -34,16 +33,13 @@ const meta = { options: ['primary', 'secondary'], }, }, -} satisfies Meta; +}); -export default meta; -type Story = StoryObj; - -export const Default: Story = { +export const Default = meta.story({ render: () => } />, -}; +}); -export const Variants: Story = { +export const Variants = meta.story({ render: () => ( } variant="primary" /> @@ -51,18 +47,18 @@ export const Variants: Story = { } variant="tertiary" /> ), -}; +}); -export const Sizes: Story = { +export const Sizes = meta.story({ render: () => ( } size="small" /> } size="medium" /> ), -}; +}); -export const Disabled: Story = { +export const Disabled = meta.story({ render: () => ( } variant="primary" /> @@ -70,9 +66,9 @@ export const Disabled: Story = { } variant="tertiary" /> ), -}; +}); -export const Responsive: Story = { +export const Responsive = meta.story({ args: { variant: { initial: 'primary', @@ -84,9 +80,9 @@ export const Responsive: Story = { }, }, render: args => } />, -}; +}); -export const Loading: Story = { +export const Loading = meta.story({ render: () => { const [isLoading, setIsLoading] = useState(false); @@ -106,9 +102,9 @@ export const Loading: Story = { /> ); }, -}; +}); -export const LoadingVariants: Story = { +export const LoadingVariants = meta.story({ render: () => ( Primary @@ -172,4 +168,4 @@ export const LoadingVariants: Story = { ), -}; +}); diff --git a/packages/ui/src/components/ButtonLink/ButtonLink.stories.tsx b/packages/ui/src/components/ButtonLink/ButtonLink.stories.tsx index 7d288065a4..4b9b9b747c 100644 --- a/packages/ui/src/components/ButtonLink/ButtonLink.stories.tsx +++ b/packages/ui/src/components/ButtonLink/ButtonLink.stories.tsx @@ -14,13 +14,14 @@ * limitations under the License. */ -import type { Meta, StoryFn, StoryObj } from '@storybook/react-vite'; +import preview from '../../../../../.storybook/preview'; +import type { StoryFn } from '@storybook/react-vite'; import { ButtonLink } from './ButtonLink'; import { Flex } from '../Flex'; import { MemoryRouter } from 'react-router-dom'; import { RiArrowRightSLine, RiCloudLine } from '@remixicon/react'; -const meta = { +const meta = preview.meta({ title: 'Backstage UI/ButtonLink', component: ButtonLink, decorators: [ @@ -40,18 +41,15 @@ const meta = { options: ['primary', 'secondary'], }, }, -} satisfies Meta; +}); -export default meta; -type Story = StoryObj; - -export const Default: Story = { +export const Default = meta.story({ args: { children: 'Button', }, -}; +}); -export const Variants: Story = { +export const Variants = meta.story({ render: () => ( ), -}; +}); -export const Sizes: Story = { +export const Sizes = meta.story({ args: { children: 'Button', }, @@ -96,9 +94,9 @@ export const Sizes: Story = { ), -}; +}); -export const WithIcons: Story = { +export const WithIcons = meta.story({ args: { children: 'Button', }, @@ -113,9 +111,9 @@ export const WithIcons: Story = { /> ), -}; +}); -export const FullWidth: Story = { +export const FullWidth = meta.story({ args: { children: 'Button', }, @@ -130,9 +128,9 @@ export const FullWidth: Story = { /> ), -}; +}); -export const Disabled: Story = { +export const Disabled = meta.story({ render: () => ( @@ -146,9 +144,9 @@ export const Disabled: Story = { ), -}; +}); -export const Responsive: Story = { +export const Responsive = meta.story({ args: { children: 'Button', variant: { @@ -160,4 +158,4 @@ export const Responsive: Story = { sm: 'medium', }, }, -}; +}); diff --git a/packages/ui/src/components/Card/Card.stories.tsx b/packages/ui/src/components/Card/Card.stories.tsx index 170d2b7984..f2a9c9bf07 100644 --- a/packages/ui/src/components/Card/Card.stories.tsx +++ b/packages/ui/src/components/Card/Card.stories.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Backstage Authors + * Copyright 2025 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,21 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -import type { Meta, StoryObj } from '@storybook/react-vite'; +import preview from '../../../../../.storybook/preview'; import { Card, CardHeader, CardBody, CardFooter } from './Card'; import { Text } from '../..'; -const meta = { +const meta = preview.meta({ title: 'Backstage UI/Card', component: Card, subcomponents: { CardHeader, CardBody, CardFooter }, -} satisfies Meta; +}); -export default meta; -type Story = StoryObj; - -export const Default: Story = { +export const Default = meta.story({ render: args => ( Header @@ -35,19 +31,19 @@ export const Default: Story = { Footer ), -}; +}); -export const CustomSize: Story = { +export const CustomSize = meta.story({ args: { style: { width: '300px', height: '200px', }, }, - render: Default.render, -}; + render: Default.input.render, +}); -export const WithLongBody: Story = { +export const WithLongBody = meta.story({ render: () => ( @@ -77,7 +73,7 @@ export const WithLongBody: Story = { ), -}; +}); const ListRow = ({ children }: { children: React.ReactNode }) => { return ( @@ -99,7 +95,7 @@ const ListRow = ({ children }: { children: React.ReactNode }) => { ); }; -export const WithListRow: Story = { +export const WithListRow = meta.story({ render: () => ( @@ -128,4 +124,4 @@ export const WithListRow: Story = { ), -}; +}); diff --git a/packages/ui/src/components/Checkbox/Checkbox.stories.tsx b/packages/ui/src/components/Checkbox/Checkbox.stories.tsx index a41b7f2c8d..c5318cc6fb 100644 --- a/packages/ui/src/components/Checkbox/Checkbox.stories.tsx +++ b/packages/ui/src/components/Checkbox/Checkbox.stories.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Backstage Authors + * Copyright 2025 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,27 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -import type { Meta, StoryObj } from '@storybook/react-vite'; +import preview from '../../../../../.storybook/preview'; import { Checkbox } from './Checkbox'; import { Flex } from '../Flex'; -const meta = { +const meta = preview.meta({ title: 'Backstage UI/Checkbox', component: Checkbox, -} satisfies Meta; +}); -export default meta; -type Story = StoryObj; - -export const Default: Story = { +export const Default = meta.story({ args: { children: 'Accept terms and conditions', }, -}; +}); -export const AllVariants: Story = { - ...Default, +export const AllVariants = meta.story({ + ...Default.input, render: () => ( Unchecked @@ -44,4 +40,4 @@ export const AllVariants: Story = { ), -}; +}); diff --git a/packages/ui/src/components/Container/Container.stories.tsx b/packages/ui/src/components/Container/Container.stories.tsx index 504cb3de87..44ff6f2d17 100644 --- a/packages/ui/src/components/Container/Container.stories.tsx +++ b/packages/ui/src/components/Container/Container.stories.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Backstage Authors + * Copyright 2025 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,12 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -import type { Meta, StoryObj } from '@storybook/react-vite'; +import preview from '../../../../../.storybook/preview'; import { Box } from '../Box/Box'; import { Container } from './Container'; -const meta = { +const meta = preview.meta({ title: 'Backstage UI/Container', component: Container, parameters: { @@ -32,10 +31,7 @@ const meta = { control: 'text', }, }, -} satisfies Meta; - -export default meta; -type Story = StoryObj; +}); const DecorativeBox = () => ( ( /> ); -export const Default: Story = { +export const Default = meta.story({ args: { children: , }, -}; +}); -export const Preview: Story = { +export const Preview = meta.story({ render: () => (
), -}; +}); -export const WithPaddingY: Story = { +export const WithPaddingY = meta.story({ args: { - ...Default.args, + ...Default.input.args, py: '4', }, -}; +}); -export const WithPaddingTop: Story = { +export const WithPaddingTop = meta.story({ args: { - ...Default.args, + ...Default.input.args, pt: '4', }, -}; +}); -export const WithPaddingBottom: Story = { +export const WithPaddingBottom = meta.story({ args: { - ...Default.args, + ...Default.input.args, pb: '4', }, -}; +}); -export const WithMarginY: Story = { +export const WithMarginY = meta.story({ args: { - ...Default.args, + ...Default.input.args, my: '4', }, -}; +}); -export const WithMarginTop: Story = { +export const WithMarginTop = meta.story({ args: { - ...Default.args, + ...Default.input.args, mt: '4', }, -}; +}); -export const WithMarginBottom: Story = { +export const WithMarginBottom = meta.story({ args: { - ...Default.args, + ...Default.input.args, mb: '4', }, -}; +}); diff --git a/packages/ui/src/components/Dialog/Dialog.stories.tsx b/packages/ui/src/components/Dialog/Dialog.stories.tsx index 98d2492913..7c7edc1801 100644 --- a/packages/ui/src/components/Dialog/Dialog.stories.tsx +++ b/packages/ui/src/components/Dialog/Dialog.stories.tsx @@ -13,7 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import type { Meta, StoryObj } from '@storybook/react-vite'; + +import preview from '../../../../../.storybook/preview'; import { Dialog, DialogTrigger, @@ -24,7 +25,7 @@ import { import { Button, Flex, Text, TextField, Select } from '@backstage/ui'; import { useArgs } from 'storybook/preview-api'; -const meta = { +const meta = preview.meta({ title: 'Backstage UI/Dialog', component: Dialog, args: { @@ -35,12 +36,9 @@ const meta = { isOpen: { control: 'boolean' }, defaultOpen: { control: 'boolean' }, }, -} satisfies Meta; +}); -export default meta; -type Story = StoryObj; - -export const Default: Story = { +export const Default = meta.story({ render: args => { return ( @@ -62,17 +60,15 @@ export const Default: Story = { ); }, -}; +}); -export const Open: Story = { +export const Open = Default.extend({ args: { - ...Default.args, defaultOpen: true, }, - render: Default.render, -}; +}); -export const NoTrigger: Story = { +export const NoTrigger = meta.story({ args: { isOpen: true, }, @@ -100,9 +96,9 @@ export const NoTrigger: Story = { ); }, -}; +}); -export const FixedWidth: Story = { +export const FixedWidth = meta.story({ args: { defaultOpen: true, width: 600, @@ -145,35 +141,35 @@ export const FixedWidth: Story = { ), -}; +}); -export const FixedHeight: Story = { +export const FixedHeight = meta.story({ args: { defaultOpen: true, height: 500, }, - render: FixedWidth.render, -}; + render: FixedWidth.input.render, +}); -export const FixedWidthAndHeight: Story = { +export const FixedWidthAndHeight = meta.story({ args: { defaultOpen: true, width: 600, height: 400, }, - render: FixedWidth.render, -}; + render: FixedWidth.input.render, +}); -export const FullWidthAndHeight: Story = { +export const FullWidthAndHeight = meta.story({ args: { defaultOpen: true, width: '100%', height: '100%', }, - render: FixedWidth.render, -}; + render: FixedWidth.input.render, +}); -export const Confirmation: Story = { +export const Confirmation = meta.story({ args: { isOpen: true, }, @@ -199,9 +195,9 @@ export const Confirmation: Story = { ), -}; +}); -export const WithForm: Story = { +export const WithForm = meta.story({ args: { isOpen: true, }, @@ -235,20 +231,20 @@ export const WithForm: Story = { ), -}; +}); -export const PreviewFixedWidthAndHeight: Story = { +export const PreviewFixedWidthAndHeight = meta.story({ args: { defaultOpen: undefined, width: 600, height: 400, }, - render: FixedWidth.render, -}; + render: FixedWidth.input.render, +}); -export const PreviewWithForm: Story = { +export const PreviewWithForm = meta.story({ args: { defaultOpen: undefined, }, - render: WithForm.render, -}; + render: WithForm.input.render, +}); diff --git a/packages/ui/src/components/FieldError/FieldError.stories.tsx b/packages/ui/src/components/FieldError/FieldError.stories.tsx index 1922e12a0d..a0b2a05b92 100644 --- a/packages/ui/src/components/FieldError/FieldError.stories.tsx +++ b/packages/ui/src/components/FieldError/FieldError.stories.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Backstage Authors + * Copyright 2025 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,21 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -import type { Meta, StoryObj } from '@storybook/react-vite'; +import preview from '../../../../../.storybook/preview'; import { TextField, Input, Form } from 'react-aria-components'; import { FieldError } from './FieldError'; -const meta = { +const meta = preview.meta({ title: 'Backstage UI/FieldError', component: FieldError, -} satisfies Meta; - -export default meta; -type Story = StoryObj; +}); // Show error with server validation using Form component -export const WithServerValidation: Story = { +export const WithServerValidation = meta.story({ render: () => (
), -}; +}); // Show error using children -export const WithCustomMessage: Story = { +export const WithCustomMessage = meta.story({ render: () => ( This is a custom error message. ), -}; +}); // Show error with render prop function -export const WithRenderProp: Story = { +export const WithRenderProp = meta.story({ render: () => ( ), -}; +}); diff --git a/packages/ui/src/components/FieldLabel/FieldLabel.stories.tsx b/packages/ui/src/components/FieldLabel/FieldLabel.stories.tsx index d0e8f3e4fb..178df67284 100644 --- a/packages/ui/src/components/FieldLabel/FieldLabel.stories.tsx +++ b/packages/ui/src/components/FieldLabel/FieldLabel.stories.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Backstage Authors + * Copyright 2025 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,11 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -import type { Meta, StoryObj } from '@storybook/react-vite'; +import preview from '../../../../../.storybook/preview'; import { FieldLabel } from './FieldLabel'; -const meta = { +const meta = preview.meta({ title: 'Backstage UI/FieldLabel', component: FieldLabel, argTypes: { @@ -31,35 +30,32 @@ const meta = { control: 'text', }, }, -} satisfies Meta; +}); -export default meta; -type Story = StoryObj; - -export const Default: Story = { +export const Default = meta.story({ args: { label: 'Label', }, -}; +}); -export const WithSecondaryLabel: Story = { +export const WithSecondaryLabel = meta.story({ args: { - ...Default.args, + ...Default.input.args, secondaryLabel: 'Secondary Label', }, -}; +}); -export const WithDescription: Story = { +export const WithDescription = meta.story({ args: { - ...Default.args, + ...Default.input.args, description: 'Description', }, -}; +}); -export const WithAllFields: Story = { +export const WithAllFields = meta.story({ args: { - ...Default.args, + ...Default.input.args, secondaryLabel: 'Secondary Label', description: 'Description', }, -}; +}); diff --git a/packages/ui/src/components/Flex/Flex.stories.tsx b/packages/ui/src/components/Flex/Flex.stories.tsx index 87854e89c7..17ee740997 100644 --- a/packages/ui/src/components/Flex/Flex.stories.tsx +++ b/packages/ui/src/components/Flex/Flex.stories.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Backstage Authors + * Copyright 2025 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,13 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -import type { Meta, StoryObj } from '@storybook/react-vite'; +import preview from '../../../../../.storybook/preview'; import { Flex } from './Flex'; import { Text } from '../Text'; import { Box } from '../Box'; -const meta = { +const meta = preview.meta({ title: 'Backstage UI/Flex', component: Flex, argTypes: { @@ -36,10 +35,7 @@ const meta = { options: ['row', 'column', 'row-reverse', 'column-reverse'], }, }, -} satisfies Meta; - -export default meta; -type Story = StoryObj; +}); const DecorativeBox = ({ width = '48px', @@ -78,7 +74,7 @@ const DecorativeBox = ({ ); }; -export const Default: Story = { +export const Default = meta.story({ args: { children: ( <> @@ -88,23 +84,23 @@ export const Default: Story = { ), }, -}; +}); -export const ColumnDirection: Story = { +export const ColumnDirection = meta.story({ args: { - ...Default.args, + ...Default.input.args, direction: 'column', }, -}; +}); -export const RowDirection: Story = { +export const RowDirection = meta.story({ args: { - ...Default.args, + ...Default.input.args, direction: 'row', }, -}; +}); -export const AlignStartInColumn: Story = { +export const AlignStartInColumn = meta.story({ args: { align: 'start', direction: 'column', @@ -116,9 +112,9 @@ export const AlignStartInColumn: Story = { ), -}; +}); -export const AlignStartInRow: Story = { +export const AlignStartInRow = meta.story({ args: { align: 'start', direction: 'row', @@ -130,9 +126,9 @@ export const AlignStartInRow: Story = { ), -}; +}); -export const AlignCenterInColumn: Story = { +export const AlignCenterInColumn = meta.story({ args: { align: 'center', direction: 'column', @@ -144,9 +140,9 @@ export const AlignCenterInColumn: Story = { ), -}; +}); -export const AlignCenterInRow: Story = { +export const AlignCenterInRow = meta.story({ args: { align: 'center', direction: 'row', @@ -158,9 +154,9 @@ export const AlignCenterInRow: Story = { ), -}; +}); -export const AlignEndInColumn: Story = { +export const AlignEndInColumn = meta.story({ args: { align: 'end', direction: 'column', @@ -172,9 +168,9 @@ export const AlignEndInColumn: Story = { ), -}; +}); -export const AlignEndInRow: Story = { +export const AlignEndInRow = meta.story({ args: { align: 'end', direction: 'row', @@ -186,9 +182,9 @@ export const AlignEndInRow: Story = { ), -}; +}); -export const ResponsiveAlign: Story = { +export const ResponsiveAlign = meta.story({ args: { align: { xs: 'start', md: 'center', lg: 'end' }, }, @@ -199,9 +195,9 @@ export const ResponsiveAlign: Story = { ), -}; +}); -export const ResponsiveGap: Story = { +export const ResponsiveGap = meta.story({ args: { gap: { xs: '4', md: '8', lg: '12' }, }, @@ -212,9 +208,9 @@ export const ResponsiveGap: Story = { ), -}; +}); -export const LargeGap: Story = { +export const LargeGap = meta.story({ args: { gap: '8', }, @@ -225,9 +221,9 @@ export const LargeGap: Story = { ), -}; +}); -export const WithTextTruncate: Story = { +export const WithTextTruncate = meta.story({ render: () => ( @@ -246,4 +242,4 @@ export const WithTextTruncate: Story = { ), -}; +}); diff --git a/packages/ui/src/components/Grid/Grid.stories.tsx b/packages/ui/src/components/Grid/Grid.stories.tsx index 66ea346b4f..56251b6085 100644 --- a/packages/ui/src/components/Grid/Grid.stories.tsx +++ b/packages/ui/src/components/Grid/Grid.stories.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Backstage Authors + * Copyright 2025 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,20 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -import type { Meta, StoryObj } from '@storybook/react-vite'; +import preview from '../../../../../.storybook/preview'; import { Grid } from './Grid'; import type { GridItemProps } from './types'; import { Box } from '../Box/Box'; import { Flex } from '../Flex'; -const meta = { +const meta = preview.meta({ title: 'Backstage UI/Grid', component: Grid.Root, -} satisfies Meta; - -export default meta; -type Story = StoryObj; +}); const FakeBox = () => ( ( /> ); -export const Default: Story = { +export const Default = meta.story({ args: { children: ( <> @@ -51,16 +47,16 @@ export const Default: Story = { ), }, -}; +}); -export const LargeGap: Story = { +export const LargeGap = meta.story({ args: { - ...Default.args, + ...Default.input.args, gap: '64px', }, -}; +}); -export const ColumnSizes: Story = { +export const ColumnSizes = meta.story({ args: { columns: '12', }, @@ -78,9 +74,9 @@ export const ColumnSizes: Story = { ))} ), -}; +}); -export const RowAndColumns: Story = { +export const RowAndColumns = meta.story({ args: { columns: '12', }, @@ -106,4 +102,4 @@ export const RowAndColumns: Story = { ), -}; +}); diff --git a/packages/ui/src/components/Header/Header.module.css b/packages/ui/src/components/Header/Header.module.css index ad50c42e0c..031cfd4d16 100644 --- a/packages/ui/src/components/Header/Header.module.css +++ b/packages/ui/src/components/Header/Header.module.css @@ -27,7 +27,7 @@ left: 0px; right: 0px; height: 16px; - background-color: var(--bui-bg); + background-color: var(--bui-bg-surface-0); z-index: 0; } diff --git a/packages/ui/src/components/Header/Header.stories.tsx b/packages/ui/src/components/Header/Header.stories.tsx index 6ccda8bb50..7d1aa3a00a 100644 --- a/packages/ui/src/components/Header/Header.stories.tsx +++ b/packages/ui/src/components/Header/Header.stories.tsx @@ -14,7 +14,8 @@ * limitations under the License. */ -import type { Meta, StoryObj, StoryFn } from '@storybook/react-vite'; +import preview from '../../../../../.storybook/preview'; +import type { StoryFn } from '@storybook/react-vite'; import { Header } from './Header'; import type { HeaderTab } from './types'; import { @@ -36,16 +37,13 @@ import { } from '@remixicon/react'; import { HeaderPageBreadcrumb } from '../HeaderPage/types'; -const meta = { +const meta = preview.meta({ title: 'Backstage UI/Header', component: Header, parameters: { layout: 'fullscreen', }, -} satisfies Meta; - -export default meta; -type Story = StoryObj; +}); const withRouter = (Story: StoryFn) => ( @@ -199,19 +197,19 @@ const layoutDecorator = [ withRouter, ]; -export const Default: Story = { +export const Default = meta.story({ args: {}, decorators: [withRouter], -}; +}); -export const WithTabs: Story = { +export const WithTabs = meta.story({ args: { tabs, }, decorators: [withRouter], -}; +}); -export const WithCustomActions: Story = { +export const WithCustomActions = meta.story({ args: {}, decorators: [withRouter], render: args => ( @@ -240,20 +238,20 @@ export const WithCustomActions: Story = { } /> ), -}; +}); -export const WithAllOptionsAndTabs: Story = { +export const WithAllOptionsAndTabs = meta.story({ args: { - ...WithCustomActions.args, + ...WithCustomActions.input.args, tabs, }, decorators: [withRouter], - render: WithCustomActions.render, -}; + render: WithCustomActions.input.render, +}); -export const WithHeaderPage: Story = { +export const WithHeaderPage = meta.story({ args: { - ...WithAllOptionsAndTabs.args, + ...WithAllOptionsAndTabs.input.args, }, decorators: [withRouter], render: args => ( @@ -276,9 +274,9 @@ export const WithHeaderPage: Story = { /> ), -}; +}); -export const WithLayout: Story = { +export const WithLayout = meta.story({ decorators: layoutDecorator, render: args => ( <> @@ -291,9 +289,9 @@ export const WithLayout: Story = { /> ), -}; +}); -export const WithLayoutNoTabs: Story = { +export const WithLayoutNoTabs = meta.story({ decorators: layoutDecorator, render: args => ( <> @@ -301,9 +299,9 @@ export const WithLayoutNoTabs: Story = { ), -}; +}); -export const WithEverything: Story = { +export const WithEverything = meta.story({ args: { tabs, titleLink: '/', @@ -333,9 +331,9 @@ export const WithEverything: Story = { /> ), -}; +}); -export const WithMockedURLCampaigns: Story = { +export const WithMockedURLCampaigns = meta.story({ args: { tabs, }, @@ -353,9 +351,9 @@ export const WithMockedURLCampaigns: Story = { ), -}; +}); -export const WithMockedURLIntegrations: Story = { +export const WithMockedURLIntegrations = meta.story({ args: { tabs, }, @@ -373,9 +371,9 @@ export const WithMockedURLIntegrations: Story = { ), -}; +}); -export const WithMockedURLNoMatch: Story = { +export const WithMockedURLNoMatch = meta.story({ args: { tabs, }, @@ -397,9 +395,9 @@ export const WithMockedURLNoMatch: Story = { ), -}; +}); -export const WithTabsMatchingStrategies: Story = { +export const WithTabsMatchingStrategies = meta.story({ args: { title: 'Route Matching Demo', tabs: [ @@ -457,9 +455,9 @@ export const WithTabsMatchingStrategies: Story = { ), -}; +}); -export const WithTabsExactMatching: Story = { +export const WithTabsExactMatching = meta.story({ args: { title: 'Exact Matching Demo', tabs: [ @@ -496,9 +494,9 @@ export const WithTabsExactMatching: Story = { ), -}; +}); -export const WithTabsPrefixMatchingDeep: Story = { +export const WithTabsPrefixMatchingDeep = meta.story({ args: { title: 'Deep Nesting Demo', tabs: [ @@ -548,4 +546,4 @@ export const WithTabsPrefixMatchingDeep: Story = { ), -}; +}); diff --git a/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx b/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx index ab527bcda4..0631a6111d 100644 --- a/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx +++ b/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx @@ -1,3 +1,4 @@ +import preview from '../../../../../.storybook/preview'; /* * Copyright 2025 The Backstage Authors * @@ -14,7 +15,7 @@ * limitations under the License. */ -import type { Meta, StoryObj, StoryFn } from '@storybook/react-vite'; +import type { StoryFn } from '@storybook/react-vite'; import { HeaderPage } from './HeaderPage'; import type { HeaderTab } from '../Header/types'; import { MemoryRouter } from 'react-router-dom'; @@ -29,16 +30,13 @@ import { } from '../../'; import { RiMore2Line } from '@remixicon/react'; -const meta = { +const meta = preview.meta({ title: 'Backstage UI/HeaderPage', component: HeaderPage, parameters: { layout: 'fullscreen', }, -} satisfies Meta; - -export default meta; -type Story = StoryObj; +}); const tabs: HeaderTab[] = [ { @@ -130,25 +128,25 @@ const layoutDecorator = [ ), ]; -export const Default: Story = { +export const Default = meta.story({ args: { title: 'Page Title', }, -}; +}); -export const WithTabs: Story = { +export const WithTabs = meta.story({ args: { - ...Default.args, + ...Default.input.args, tabs, }, decorators: [withRouter], -}; +}); -export const WithCustomActions: Story = { +export const WithCustomActions = meta.story({ decorators: [withRouter], render: () => ( @@ -174,48 +172,44 @@ export const WithCustomActions: Story = { } /> ), -}; +}); -export const WithBreadcrumbs: Story = { +export const WithBreadcrumbs = meta.story({ decorators: [withRouter], args: { - ...Default.args, + ...Default.input.args, breadcrumbs: [{ label: 'Home', href: '/' }], }, -}; +}); -export const WithLongBreadcrumbs: Story = { +export const WithLongBreadcrumbs = meta.story({ decorators: [withRouter], args: { - ...Default.args, + ...Default.input.args, breadcrumbs: [ { label: 'Home', href: '/' }, { label: 'Long Breadcrumb Name', href: '/long-breadcrumb' }, ], }, -}; +}); -export const WithEverything: Story = { +export const WithEverything = meta.story({ decorators: [withRouter], render: () => ( Custom action} breadcrumbs={[{ label: 'Home', href: '/' }]} /> ), -}; +}); -export const WithLayout: Story = { - args: { - ...WithEverything.args, - }, - decorators: [withRouter, ...layoutDecorator], - render: WithEverything.render, -}; +export const WithLayout = WithEverything.extend({ + decorators: [...layoutDecorator], +}); -export const WithTabsMatchingStrategies: Story = { +export const WithTabsMatchingStrategies = meta.story({ args: { title: 'Route Matching Demo', tabs: [ @@ -273,9 +267,9 @@ export const WithTabsMatchingStrategies: Story = { ), -}; +}); -export const WithTabsExactMatching: Story = { +export const WithTabsExactMatching = meta.story({ args: { title: 'Exact Matching Demo', tabs: [ @@ -312,9 +306,9 @@ export const WithTabsExactMatching: Story = { ), -}; +}); -export const WithTabsPrefixMatchingDeep: Story = { +export const WithTabsPrefixMatchingDeep = meta.story({ args: { title: 'Deep Nesting Demo', tabs: [ @@ -364,4 +358,4 @@ export const WithTabsPrefixMatchingDeep: Story = { ), -}; +}); diff --git a/packages/ui/src/components/Link/Link.stories.tsx b/packages/ui/src/components/Link/Link.stories.tsx index 37f142c4dc..7d680e5616 100644 --- a/packages/ui/src/components/Link/Link.stories.tsx +++ b/packages/ui/src/components/Link/Link.stories.tsx @@ -14,13 +14,14 @@ * limitations under the License. */ -import type { Meta, StoryFn, StoryObj } from '@storybook/react-vite'; +import preview from '../../../../../.storybook/preview'; +import type { StoryFn } from '@storybook/react-vite'; import { Link } from './Link'; import { Flex } from '../Flex'; import { Text } from '../Text'; import { MemoryRouter } from 'react-router-dom'; -const meta = { +const meta = preview.meta({ title: 'Backstage UI/Link', component: Link, args: { @@ -33,29 +34,26 @@ const meta = { ), ], -} satisfies Meta; +}); -export default meta; -type Story = StoryObj; - -export const Default: Story = { +export const Default = meta.story({ args: { href: '/', children: 'Sign up for Backstage', }, -}; +}); -export const ExternalLink: Story = { +export const ExternalLink = meta.story({ args: { href: 'https://backstage.io', children: 'Sign up for Backstage', target: '_blank', }, -}; +}); -export const AllVariants: Story = { +export const AllVariants = meta.story({ args: { - ...Default.args, + ...Default.input.args, }, render: args => ( @@ -69,9 +67,9 @@ export const AllVariants: Story = { ), -}; +}); -export const AllColors: Story = { +export const AllColors = meta.story({ render: () => ( ), -}; +}); -export const AllWeights: Story = { +export const AllWeights = meta.story({ render: () => ( @@ -225,9 +223,9 @@ export const AllWeights: Story = { ), -}; +}); -export const Truncate: Story = { +export const Truncate = meta.story({ args: { children: "A man looks at a painting in a museum and says, “Brothers and sisters I have none, but that man's father is my father's son.” Who is in the painting?", @@ -235,21 +233,21 @@ export const Truncate: Story = { truncate: true, style: { width: '480px' }, }, -}; +}); -export const Responsive: Story = { +export const Responsive = meta.story({ args: { - ...Default.args, + ...Default.input.args, variant: { xs: 'title-x-small', md: 'body-x-small', }, }, -}; +}); -export const Playground: Story = { +export const Playground = meta.story({ args: { - ...Default.args, + ...Default.input.args, }, render: args => ( @@ -269,4 +267,4 @@ export const Playground: Story = { ), -}; +}); diff --git a/packages/ui/src/components/Menu/Menu.stories.tsx b/packages/ui/src/components/Menu/Menu.stories.tsx index 7171b3ef83..ffe184d4ae 100644 --- a/packages/ui/src/components/Menu/Menu.stories.tsx +++ b/packages/ui/src/components/Menu/Menu.stories.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import type { Meta, StoryObj } from '@storybook/react-vite'; +import preview from '../../../../../.storybook/preview'; import { MenuTrigger, SubmenuTrigger, @@ -38,7 +38,7 @@ import { import { MemoryRouter } from 'react-router-dom'; import { useEffect, useState } from 'react'; -const meta = { +const meta = preview.meta({ title: 'Backstage UI/Menu', component: MenuTrigger, decorators: [ @@ -48,10 +48,7 @@ const meta = { ), ], -} satisfies Meta; - -export default meta; -type Story = StoryObj; +}); const options = [ { label: 'Apple', value: 'apple' }, @@ -65,7 +62,7 @@ const options = [ { label: 'Honeydew', value: 'honeydew' }, ]; -export const Preview: Story = { +export const Preview = meta.story({ args: { children: null, }, @@ -91,11 +88,11 @@ export const Preview: Story = { ), -}; +}); -export const PreviewSubmenu: Story = { +export const PreviewSubmenu = meta.story({ args: { - ...Preview.args, + ...Preview.input.args, }, render: () => ( @@ -119,11 +116,11 @@ export const PreviewSubmenu: Story = { ), -}; +}); -export const PreviewIcons: Story = { +export const PreviewIcons = meta.story({ args: { - ...Preview.args, + ...Preview.input.args, }, render: () => ( @@ -135,11 +132,11 @@ export const PreviewIcons: Story = { ), -}; +}); -export const PreviewSections: Story = { +export const PreviewSections = meta.story({ args: { - ...Preview.args, + ...Preview.input.args, }, render: () => ( @@ -159,11 +156,11 @@ export const PreviewSections: Story = { ), -}; +}); -export const PreviewSeparators: Story = { +export const PreviewSeparators = meta.story({ args: { - ...Preview.args, + ...Preview.input.args, }, render: () => ( @@ -180,11 +177,11 @@ export const PreviewSeparators: Story = { ), -}; +}); -export const PreviewLinks: Story = { +export const PreviewLinks = meta.story({ args: { - ...Preview.args, + ...Preview.input.args, }, render: () => ( @@ -198,11 +195,11 @@ export const PreviewLinks: Story = { ), -}; +}); -export const Opened: Story = { +export const Opened = meta.story({ args: { - ...Preview.args, + ...Preview.input.args, }, render: () => ( @@ -214,11 +211,11 @@ export const Opened: Story = { ), -}; +}); -export const WithIcons: Story = { +export const WithIcons = meta.story({ args: { - ...Preview.args, + ...Preview.input.args, }, render: () => ( @@ -230,11 +227,11 @@ export const WithIcons: Story = { ), -}; +}); -export const WithSections: Story = { +export const WithSections = meta.story({ args: { - ...Preview.args, + ...Preview.input.args, }, render: () => ( @@ -254,11 +251,11 @@ export const WithSections: Story = { ), -}; +}); -export const WithSeparators: Story = { +export const WithSeparators = meta.story({ args: { - ...Preview.args, + ...Preview.input.args, }, render: () => ( @@ -275,11 +272,11 @@ export const WithSeparators: Story = { ), -}; +}); -export const WithColors: Story = { +export const WithColors = meta.story({ args: { - ...Preview.args, + ...Preview.input.args, }, render: () => ( @@ -295,11 +292,11 @@ export const WithColors: Story = { ), -}; +}); -export const WithLinks: Story = { +export const WithLinks = meta.story({ args: { - ...Preview.args, + ...Preview.input.args, }, render: () => ( @@ -313,11 +310,11 @@ export const WithLinks: Story = { ), -}; +}); -export const Submenu: Story = { +export const Submenu = meta.story({ args: { - ...Preview.args, + ...Preview.input.args, }, render: () => ( @@ -341,11 +338,11 @@ export const Submenu: Story = { ), -}; +}); -export const Virtualized: Story = { +export const Virtualized = meta.story({ args: { - ...Preview.args, + ...Preview.input.args, }, render: () => { const [pokemon, setPokemon] = useState< @@ -376,11 +373,11 @@ export const Virtualized: Story = { ); }, -}; +}); -export const VirtualizedMaxHeight: Story = { +export const VirtualizedMaxHeight = meta.story({ args: { - ...Preview.args, + ...Preview.input.args, }, render: () => { const [pokemon, setPokemon] = useState< @@ -411,9 +408,9 @@ export const VirtualizedMaxHeight: Story = { ); }, -}; +}); -export const WithScroll: Story = { +export const WithScroll = meta.story({ args: { children: null, }, @@ -446,4 +443,4 @@ export const WithScroll: Story = { ), -}; +}); diff --git a/packages/ui/src/components/Menu/MenuAutocomplete.stories.tsx b/packages/ui/src/components/Menu/MenuAutocomplete.stories.tsx index c0e1aca932..af68ec9415 100644 --- a/packages/ui/src/components/Menu/MenuAutocomplete.stories.tsx +++ b/packages/ui/src/components/Menu/MenuAutocomplete.stories.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import type { Meta, StoryObj } from '@storybook/react-vite'; +import preview from '../../../../../.storybook/preview'; import { MenuTrigger, SubmenuTrigger, @@ -26,7 +26,7 @@ import { Button } from '../..'; import { useState, useEffect } from 'react'; import { MemoryRouter } from 'react-router-dom'; -const meta = { +const meta = preview.meta({ title: 'Backstage UI/MenuAutocomplete', component: MenuTrigger, decorators: [ @@ -36,10 +36,7 @@ const meta = { ), ], -} satisfies Meta; - -export default meta; -type Story = StoryObj; +}); const options = [ { label: 'Apple', value: 'apple' }, @@ -53,7 +50,7 @@ const options = [ { label: 'Honeydew', value: 'honeydew' }, ]; -export const Default: Story = { +export const Default = meta.story({ args: { children: null, }, @@ -72,11 +69,11 @@ export const Default: Story = { ), -}; +}); -export const PreviewAutocompleteMenu: Story = { +export const PreviewAutocompleteMenu = meta.story({ args: { - ...Default.args, + ...Default.input.args, }, render: () => ( @@ -93,11 +90,11 @@ export const PreviewAutocompleteMenu: Story = { ), -}; +}); -export const Virtualized: Story = { +export const Virtualized = meta.story({ args: { - ...Default.args, + ...Default.input.args, }, render: () => { const [pokemon, setPokemon] = useState< @@ -132,11 +129,11 @@ export const Virtualized: Story = { ); }, -}; +}); -export const VirtualizedMaxHeight: Story = { +export const VirtualizedMaxHeight = meta.story({ args: { - ...Default.args, + ...Default.input.args, }, render: () => { const [pokemon, setPokemon] = useState< @@ -172,11 +169,11 @@ export const VirtualizedMaxHeight: Story = { ); }, -}; +}); -export const Submenu: Story = { +export const Submenu = meta.story({ args: { - ...Default.args, + ...Default.input.args, }, render: () => ( @@ -197,4 +194,4 @@ export const Submenu: Story = { ), -}; +}); diff --git a/packages/ui/src/components/Menu/MenuAutocompleteListBox.stories.tsx b/packages/ui/src/components/Menu/MenuAutocompleteListBox.stories.tsx index bf66f5f8fd..e1c22fbd9e 100644 --- a/packages/ui/src/components/Menu/MenuAutocompleteListBox.stories.tsx +++ b/packages/ui/src/components/Menu/MenuAutocompleteListBox.stories.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import type { Meta, StoryObj } from '@storybook/react-vite'; +import preview from '../../../../../.storybook/preview'; import { MenuTrigger, MenuAutocompleteListbox, @@ -28,7 +28,7 @@ import { useEffect, useState } from 'react'; import { Selection } from 'react-aria-components'; import { MemoryRouter } from 'react-router-dom'; -const meta = { +const meta = preview.meta({ title: 'Backstage UI/MenuAutocompleteListBox', component: MenuTrigger, decorators: [ @@ -38,10 +38,7 @@ const meta = { ), ], -} satisfies Meta; - -export default meta; -type Story = StoryObj; +}); const options = [ { label: 'Apple', value: 'apple' }, @@ -55,7 +52,7 @@ const options = [ { label: 'Honeydew', value: 'honeydew' }, ]; -export const Default: Story = { +export const Default = meta.story({ args: { children: null, }, @@ -83,11 +80,11 @@ export const Default: Story = { ); }, -}; +}); -export const PreviewListbox: Story = { +export const PreviewListbox = meta.story({ args: { - ...Default.args, + ...Default.input.args, }, render: () => { const [selected, setSelected] = useState( @@ -113,11 +110,11 @@ export const PreviewListbox: Story = { ); }, -}; +}); -export const PreviewListboxMultiple: Story = { +export const PreviewListboxMultiple = meta.story({ args: { - ...Default.args, + ...Default.input.args, }, render: () => { const [selected, setSelected] = useState( @@ -144,11 +141,11 @@ export const PreviewListboxMultiple: Story = { ); }, -}; +}); -export const Submenu: Story = { +export const Submenu = meta.story({ args: { - ...Default.args, + ...Default.input.args, }, render: () => { const [selected, setSelected] = useState( @@ -182,11 +179,11 @@ export const Submenu: Story = { ); }, -}; +}); -export const Virtualized: Story = { +export const Virtualized = meta.story({ args: { - ...Default.args, + ...Default.input.args, }, render: () => { const [pokemon, setPokemon] = useState< @@ -221,11 +218,11 @@ export const Virtualized: Story = { ); }, -}; +}); -export const VirtualizedMaxHeight: Story = { +export const VirtualizedMaxHeight = meta.story({ args: { - ...Default.args, + ...Default.input.args, }, render: () => { const [pokemon, setPokemon] = useState< @@ -261,4 +258,4 @@ export const VirtualizedMaxHeight: Story = { ); }, -}; +}); diff --git a/packages/ui/src/components/Menu/MenuListBox.stories.tsx b/packages/ui/src/components/Menu/MenuListBox.stories.tsx index 72284fb6b9..2297598d0c 100644 --- a/packages/ui/src/components/Menu/MenuListBox.stories.tsx +++ b/packages/ui/src/components/Menu/MenuListBox.stories.tsx @@ -14,14 +14,14 @@ * limitations under the License. */ -import type { Meta, StoryObj } from '@storybook/react-vite'; +import preview from '../../../../../.storybook/preview'; import { MenuTrigger, MenuListBox, MenuListBoxItem } from './index'; import { Button, Flex, Text } from '../..'; import { useEffect, useState } from 'react'; import { Selection } from 'react-aria-components'; import { MemoryRouter } from 'react-router-dom'; -const meta = { +const meta = preview.meta({ title: 'Backstage UI/MenuListBox', component: MenuTrigger, decorators: [ @@ -31,12 +31,9 @@ const meta = { ), ], -} satisfies Meta; +}); -export default meta; -type Story = StoryObj; - -export const Default: Story = { +export const Default = meta.story({ args: { children: null, }, @@ -50,11 +47,11 @@ export const Default: Story = { ), -}; +}); -export const Controlled: Story = { +export const Controlled = meta.story({ args: { - ...Default.args, + ...Default.input.args, }, render: () => { const [selected, setSelected] = useState(new Set(['paul'])); @@ -86,11 +83,11 @@ export const Controlled: Story = { ); }, -}; +}); -export const Virtualized: Story = { +export const Virtualized = meta.story({ args: { - ...Default.args, + ...Default.input.args, }, render: () => { const [pokemon, setPokemon] = useState< @@ -121,11 +118,11 @@ export const Virtualized: Story = { ); }, -}; +}); -export const VirtualizedMaxHeight: Story = { +export const VirtualizedMaxHeight = meta.story({ args: { - ...Default.args, + ...Default.input.args, }, render: () => { const [pokemon, setPokemon] = useState< @@ -156,4 +153,4 @@ export const VirtualizedMaxHeight: Story = { ); }, -}; +}); diff --git a/packages/ui/src/components/PasswordField/PasswordField.stories.tsx b/packages/ui/src/components/PasswordField/PasswordField.stories.tsx index 1867e5b7bf..5f6a74d992 100644 --- a/packages/ui/src/components/PasswordField/PasswordField.stories.tsx +++ b/packages/ui/src/components/PasswordField/PasswordField.stories.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Backstage Authors + * Copyright 2025 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,15 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -import type { Meta, StoryObj } from '@storybook/react-vite'; +import preview from '../../../../../.storybook/preview'; import { PasswordField } from './PasswordField'; import { Form } from 'react-aria-components'; import { Flex } from '../Flex'; import { FieldLabel } from '../FieldLabel'; import { RiSparklingLine } from '@remixicon/react'; -const meta = { +const meta = preview.meta({ title: 'Backstage UI/PasswordField', component: PasswordField, argTypes: { @@ -32,12 +31,9 @@ const meta = { control: 'object', }, }, -} satisfies Meta; +}); -export default meta; -type Story = StoryObj; - -export const Default: Story = { +export const Default = meta.story({ args: { name: 'secret', placeholder: 'Enter a secret', @@ -45,11 +41,11 @@ export const Default: Story = { maxWidth: '300px', }, }, -}; +}); -export const Sizes: Story = { +export const Sizes = meta.story({ args: { - ...Default.args, + ...Default.input.args, }, render: args => ( @@ -57,79 +53,79 @@ export const Sizes: Story = { } /> ), -}; +}); -export const DefaultValue: Story = { +export const DefaultValue = meta.story({ args: { - ...Default.args, + ...Default.input.args, defaultValue: 'https://example.com', }, -}; +}); -export const WithLabel: Story = { +export const WithLabel = meta.story({ args: { - ...Default.args, + ...Default.input.args, label: 'Label', }, -}; +}); -export const WithDescription: Story = { +export const WithDescription = meta.story({ args: { - ...WithLabel.args, + ...WithLabel.input.args, description: 'Description', }, -}; +}); -export const Required: Story = { +export const Required = meta.story({ args: { - ...WithLabel.args, + ...WithLabel.input.args, isRequired: true, }, -}; +}); -export const Disabled: Story = { +export const Disabled = meta.story({ args: { - ...Default.args, + ...Default.input.args, isDisabled: true, }, -}; +}); -export const WithIcon: Story = { +export const WithIcon = meta.story({ args: { - ...Default.args, + ...Default.input.args, }, render: args => ( } /> ), -}; +}); -export const DisabledWithIcon: Story = { +export const DisabledWithIcon = meta.story({ args: { - ...WithIcon.args, + ...WithIcon.input.args, isDisabled: true, }, - render: WithIcon.render, -}; + render: WithIcon.input.render, +}); -export const ShowError: Story = { +export const ShowError = meta.story({ args: { - ...WithLabel.args, + ...WithLabel.input.args, }, render: args => (
), -}; +}); -export const Validation: Story = { +export const Validation = meta.story({ args: { - ...WithLabel.args, + ...WithLabel.input.args, validate: value => (value === 'admin' ? 'Nice try!' : null), }, -}; +}); -export const CustomField: Story = { +export const CustomField = meta.story({ render: () => ( <> ), -}; +}); diff --git a/packages/ui/src/components/RadioGroup/RadioGroup.stories.tsx b/packages/ui/src/components/RadioGroup/RadioGroup.stories.tsx index df7a826c50..4f3465dade 100644 --- a/packages/ui/src/components/RadioGroup/RadioGroup.stories.tsx +++ b/packages/ui/src/components/RadioGroup/RadioGroup.stories.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Backstage Authors + * Copyright 2025 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,19 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -import type { Meta, StoryObj } from '@storybook/react-vite'; +import preview from '../../../../../.storybook/preview'; import { RadioGroup, Radio } from './RadioGroup'; -const meta = { +const meta = preview.meta({ title: 'Backstage UI/RadioGroup', component: RadioGroup, -} satisfies Meta; +}); -export default meta; -type Story = StoryObj; - -export const Default: Story = { +export const Default = meta.story({ args: { label: 'What is your favorite pokemon?', }, @@ -36,11 +32,11 @@ export const Default: Story = { Squirtle ), -}; +}); -export const Horizontal: Story = { +export const Horizontal = meta.story({ args: { - ...Default.args, + ...Default.input.args, orientation: 'horizontal', }, render: args => ( @@ -50,11 +46,11 @@ export const Horizontal: Story = { Squirtle ), -}; +}); -export const Disabled: Story = { +export const Disabled = meta.story({ args: { - ...Default.args, + ...Default.input.args, isDisabled: true, }, render: args => ( @@ -64,11 +60,11 @@ export const Disabled: Story = { Squirtle ), -}; +}); -export const DisabledSingle: Story = { +export const DisabledSingle = meta.story({ args: { - ...Default.args, + ...Default.input.args, }, render: args => ( @@ -79,11 +75,11 @@ export const DisabledSingle: Story = { Squirtle ), -}; +}); -export const DisabledAndSelected: Story = { +export const DisabledAndSelected = meta.story({ args: { - ...Default.args, + ...Default.input.args, value: 'charmander', }, render: args => ( @@ -95,11 +91,11 @@ export const DisabledAndSelected: Story = { Squirtle ), -}; +}); -export const Invalid: Story = { +export const Invalid = meta.story({ args: { - ...Default.args, + ...Default.input.args, name: 'pokemon', isInvalid: true, }, @@ -112,11 +108,11 @@ export const Invalid: Story = { Squirtle ), -}; +}); -export const Validation: Story = { +export const Validation = meta.story({ args: { - ...Default.args, + ...Default.input.args, name: 'pokemon', defaultValue: 'charmander', validationBehavior: 'aria', @@ -129,11 +125,11 @@ export const Validation: Story = { Squirtle ), -}; +}); -export const ReadOnly: Story = { +export const ReadOnly = meta.story({ args: { - ...Default.args, + ...Default.input.args, isReadOnly: true, defaultValue: 'charmander', }, @@ -144,4 +140,4 @@ export const ReadOnly: Story = { Squirtle ), -}; +}); diff --git a/packages/ui/src/components/SearchField/SearchField.module.css b/packages/ui/src/components/SearchField/SearchField.module.css index e99c212b29..765527c8c3 100644 --- a/packages/ui/src/components/SearchField/SearchField.module.css +++ b/packages/ui/src/components/SearchField/SearchField.module.css @@ -40,24 +40,25 @@ } &[data-startCollapsed='true'] { - transition: flex-basis 0.3s ease-in-out; + transition: flex-basis 0.3s ease-in-out, width 0.3s ease-in-out, + max-width 0.3s ease-in-out; padding: 0; flex: 0 1 auto; &[data-collapsed='true'] { - flex-basis: 200px; - } - - &[data-collapsed='false'] { cursor: pointer; &[data-size='medium'] { flex-basis: 2.5rem; + width: 2.5rem; + max-width: 2.5rem; height: 2.5rem; } &[data-size='small'] { flex-basis: 2rem; + width: 2rem; + max-width: 2rem; height: 2rem; } @@ -79,6 +80,12 @@ } } } + + &[data-collapsed='false'] { + flex-basis: 200px; + width: 200px; + max-width: 200px; + } } } diff --git a/packages/ui/src/components/SearchField/SearchField.stories.tsx b/packages/ui/src/components/SearchField/SearchField.stories.tsx index 81bc090835..2e07e742ad 100644 --- a/packages/ui/src/components/SearchField/SearchField.stories.tsx +++ b/packages/ui/src/components/SearchField/SearchField.stories.tsx @@ -14,7 +14,8 @@ * limitations under the License. */ -import type { Meta, StoryObj } from '@storybook/react-vite'; +import preview from '../../../../../.storybook/preview'; +import { useState } from 'react'; import { SearchField } from './SearchField'; import { Form } from 'react-aria-components'; import { Flex } from '../Flex'; @@ -25,7 +26,7 @@ import { Button } from '../Button'; import { Header } from '../Header'; import { MemoryRouter } from 'react-router-dom'; -const meta = { +const meta = preview.meta({ title: 'Backstage UI/SearchField', component: SearchField, argTypes: { @@ -39,12 +40,9 @@ const meta = { control: 'text', }, }, -} satisfies Meta; +}); -export default meta; -type Story = StoryObj; - -export const Default: Story = { +export const Default = meta.story({ args: { name: 'url', style: { @@ -52,11 +50,11 @@ export const Default: Story = { }, 'aria-label': 'Search', }, -}; +}); -export const Sizes: Story = { +export const Sizes = meta.story({ args: { - ...Default.args, + ...Default.input.args, }, render: args => ( @@ -64,46 +62,46 @@ export const Sizes: Story = { ), -}; +}); -export const DefaultValue: Story = { +export const DefaultValue = meta.story({ args: { - ...Default.args, + ...Default.input.args, defaultValue: 'https://example.com', }, -}; +}); -export const WithLabel: Story = { +export const WithLabel = meta.story({ args: { - ...Default.args, + ...Default.input.args, label: 'Label', }, -}; +}); -export const WithDescription: Story = { +export const WithDescription = meta.story({ args: { - ...WithLabel.args, + ...WithLabel.input.args, description: 'Description', }, -}; +}); -export const Required: Story = { +export const Required = meta.story({ args: { - ...WithLabel.args, + ...WithLabel.input.args, isRequired: true, }, -}; +}); -export const Disabled: Story = { +export const Disabled = meta.story({ args: { - ...Default.args, + ...Default.input.args, isDisabled: true, }, -}; +}); -export const WithIcon: Story = { +export const WithIcon = meta.story({ args: { - ...Default.args, + ...Default.input.args, }, render: args => ( } /> ), -}; +}); -export const DisabledWithIcon: Story = { +export const DisabledWithIcon = meta.story({ args: { - ...WithIcon.args, + ...WithIcon.input.args, isDisabled: true, }, -}; +}); -export const ShowError: Story = { +export const ShowError = meta.story({ args: { - ...WithLabel.args, + ...WithLabel.input.args, }, render: args => (
), -}; +}); -export const Validation: Story = { +export const Validation = meta.story({ args: { - ...WithLabel.args, + ...WithLabel.input.args, validate: value => (value === 'admin' ? 'Nice try!' : null), }, -}; +}); -export const CustomField: Story = { +export const CustomField = meta.story({ render: () => ( <> ), -}; +}); -export const StartCollapsed: Story = { +export const StartCollapsed = meta.story({ args: { - ...Default.args, + ...Default.input.args, startCollapsed: true, }, render: args => ( - + + + + + - ), -}; +}); -export const InHeader: Story = { +export const StartCollapsedWithValue = meta.story({ + args: { + ...StartCollapsed.input.args, + defaultValue: 'https://example.com', + }, + + render: args => , +}); + +export const InHeader = meta.story({ decorators: [ Story => ( @@ -204,11 +214,11 @@ export const InHeader: Story = { /> ), -}; +}); -export const StartCollapsedInHeader: Story = { +export const StartCollapsedInHeader = meta.story({ args: { - ...StartCollapsed.args, + ...StartCollapsed.input.args, }, decorators: [ Story => ( @@ -241,11 +251,11 @@ export const StartCollapsedInHeader: Story = { /> ), -}; +}); -export const StartCollapsedWithButtons: Story = { +export const StartCollapsedWithButtons = meta.story({ args: { - ...StartCollapsed.args, + ...StartCollapsed.input.args, }, render: args => ( @@ -271,11 +281,11 @@ export const StartCollapsedWithButtons: Story = { ), -}; +}); -export const StartCollapsedWithOnChange: Story = { +export const StartCollapsedWithOnChange = meta.story({ args: { - ...StartCollapsed.args, + ...StartCollapsed.input.args, }, render: args => { const handleChange = (value: string) => { @@ -292,4 +302,42 @@ export const StartCollapsedWithOnChange: Story = { ); }, -}; +}); + +export const StartCollapsedControlledEmpty = meta.story({ + args: { + ...StartCollapsed.input.args, + }, + render: function Render(args) { + const [value, setValue] = useState(''); + + return ( + + + + ); + }, +}); + +export const StartCollapsedControlledWithValue = meta.story({ + args: { + ...StartCollapsed.input.args, + }, + render: function Render(args) { + const [value, setValue] = useState('Component'); + + return ( + + + + ); + }, +}); diff --git a/packages/ui/src/components/SearchField/SearchField.tsx b/packages/ui/src/components/SearchField/SearchField.tsx index 775b7accc6..eea749e46f 100644 --- a/packages/ui/src/components/SearchField/SearchField.tsx +++ b/packages/ui/src/components/SearchField/SearchField.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { forwardRef, useEffect, useState } from 'react'; +import { forwardRef, useEffect, useState, useRef } from 'react'; import { Input, SearchField as AriaSearchField, @@ -39,9 +39,6 @@ export const SearchField = forwardRef( 'aria-labelledby': ariaLabelledBy, } = props; - const [isCollapsed, setIsCollapsed] = useState(false); - const [shouldCollapse, setShouldCollapse] = useState(true); - useEffect(() => { if (!label && !ariaLabel && !ariaLabelledBy) { console.warn( @@ -71,30 +68,29 @@ export const SearchField = forwardRef( ...rest } = cleanedProps; + const [isFocused, setIsFocused] = useState(false); + const inputRef = useRef(null); + // If a secondary label is provided, use it. Otherwise, use 'Required' if the field is required. const secondaryLabelText = secondaryLabel || (isRequired ? 'Required' : null); - const handleClick = (isFocused: boolean) => { + const handleFocusChange = (isFocused: boolean) => { props.onFocusChange?.(isFocused); - if (shouldCollapse) { - if (isFocused) { - setIsCollapsed(true); - } else { - setIsCollapsed(false); - } - } + setIsFocused(isFocused); }; - const handleChange = (value: string) => { - props.onChange?.(value); - if (value.length > 0) { - setShouldCollapse(false); - } else { - setShouldCollapse(true); - } + const handleContainerClick = () => { + inputRef.current?.focus(); }; + const hasInputRef = !!inputRef.current; + const hasValue = !!inputRef.current?.value; + + const isCollapsed = hasInputRef + ? startCollapsed && !hasValue && !isFocused + : startCollapsed && !rest.value && !rest.defaultValue && !isFocused; + return ( ( aria-label={ariaLabel} aria-labelledby={ariaLabelledBy} data-collapsed={isCollapsed} - onFocusChange={handleClick} - onChange={handleChange} style={style} {...rest} + onFocusChange={handleFocusChange} ref={ref} > ( styles[classNames.inputWrapper], )} data-size={dataAttributes['data-size']} + onClick={handleContainerClick} > {icon !== false && (
(
)} ; - -export default meta; -type Story = StoryObj; +}); const fontOptions = [ { value: 'sans', label: 'Sans-serif' }, @@ -66,23 +64,23 @@ const skills = [ { value: 'swift', label: 'Swift' }, ]; -export const Default: Story = { +export const Default = meta.story({ args: { options: fontOptions, name: 'font', }, -}; +}); -export const Searchable: Story = { +export const Searchable = meta.story({ args: { label: 'Country', searchable: true, searchPlaceholder: 'Search countries...', options: countries, }, -}; +}); -export const MultipleSelection: Story = { +export const MultipleSelection = meta.story({ args: { label: 'Select multiple options', selectionMode: 'multiple', @@ -93,9 +91,9 @@ export const MultipleSelection: Story = { { value: 'option4', label: 'Option 4' }, ], }, -}; +}); -export const SearchableMultiple: Story = { +export const SearchableMultiple = meta.story({ args: { label: 'Skills', searchable: true, @@ -103,9 +101,9 @@ export const SearchableMultiple: Story = { searchPlaceholder: 'Filter skills...', options: skills, }, -}; +}); -export const Preview: Story = { +export const Preview = meta.story({ args: { label: 'Font Family', options: fontOptions, @@ -113,40 +111,40 @@ export const Preview: Story = { name: 'font', style: { maxWidth: 260 }, }, -}; +}); -export const WithLabel: Story = { +export const WithLabel = meta.story({ args: { - ...Default.args, + ...Default.input.args, label: 'Font Family', }, -}; +}); -export const WithFullWidth: Story = { +export const WithFullWidth = meta.story({ args: { - ...Default.args, + ...Default.input.args, label: 'Font Family', style: { width: '100%' }, }, -}; +}); -export const WithLabelAndDescription: Story = { +export const WithLabelAndDescription = meta.story({ args: { - ...WithLabel.args, + ...WithLabel.input.args, description: 'Choose a font family for your document', }, -}; +}); -export const WithIcon: Story = { +export const WithIcon = meta.story({ args: { - ...WithLabel.args, + ...WithLabel.input.args, }, render: args => } /> ), -}; +}); -export const Required: Story = { +export const Required = meta.story({ args: { - ...Preview.args, + ...Preview.input.args, isRequired: true, }, -}; +}); -export const Disabled: Story = { +export const Disabled = meta.story({ args: { - ...Preview.args, + ...Preview.input.args, isDisabled: true, }, -}; +}); -export const DisabledOption: Story = { +export const DisabledOption = meta.story({ args: { - ...Preview.args, + ...Preview.input.args, disabledKeys: ['cursive', 'serif'], }, -}; +}); -export const NoOptions: Story = { +export const NoOptions = meta.story({ args: { - ...Preview.args, + ...Preview.input.args, options: undefined, }, -}; +}); -export const WithValue: Story = { +export const WithValue = meta.story({ args: { - ...Preview.args, + ...Preview.input.args, selectedKey: 'mono', defaultSelectedKey: 'serif', }, -}; +}); -export const WithDefaultValue: Story = { +export const WithDefaultValue = meta.story({ args: { - ...Preview.args, + ...Preview.input.args, defaultSelectedKey: 'serif', options: fontOptions, name: 'font', }, -}; +}); const generateOptions = (count = 100) => { const firstWords = [ @@ -323,17 +321,17 @@ const generateOptions = (count = 100) => { })); }; -export const WithManyOptions: Story = { +export const WithManyOptions = meta.story({ args: { label: 'Font Family', options: generateOptions(), name: 'font', }, -}; +}); -export const WithError: Story = { +export const WithError = meta.story({ args: { - ...WithLabel.args, + ...WithLabel.input.args, name: 'font', }, render: args => ( @@ -341,9 +339,9 @@ export const WithError: Story = {
@@ -88,9 +86,9 @@ export const TableOnly: Story = {
); }, -}; +}); -export const WithPaginationUncontrolled: Story = { +export const WithPaginationUncontrolled = meta.story({ render: () => { const { data, paginationProps } = useTable({ data: data1 }); @@ -122,9 +120,9 @@ export const WithPaginationUncontrolled: Story = { ); }, -}; +}); -export const WithPaginationControlled: Story = { +export const WithPaginationControlled = meta.story({ render: () => { const [offset, setOffset] = useState(0); const [pageSize, setPageSize] = useState(5); @@ -172,9 +170,9 @@ export const WithPaginationControlled: Story = { ); }, -}; +}); -export const Sorting: Story = { +export const Sorting = meta.story({ render: () => { return ( @@ -207,9 +205,9 @@ export const Sorting: Story = {
); }, -}; +}); -export const TableRockBand: Story = { +export const TableRockBand = meta.story({ render: () => { const { data, paginationProps } = useTable({ data: data4, @@ -246,9 +244,9 @@ export const TableRockBand: Story = { ); }, -}; +}); -export const RowClick: Story = { +export const RowClick = meta.story({ render: () => { const { data, paginationProps } = useTable({ data: data4, @@ -285,9 +283,9 @@ export const RowClick: Story = { ); }, -}; +}); -export const RowLink: Story = { +export const RowLink = meta.story({ render: () => { const { data, paginationProps } = useTable({ data: data4, @@ -324,9 +322,9 @@ export const RowLink: Story = { ); }, -}; +}); -export const CellComponent: Story = { +export const CellComponent = meta.story({ name: 'Cell', render: () => { return ( @@ -354,9 +352,9 @@ export const CellComponent: Story = { ); }, -}; +}); -export const CellTextComponent: Story = { +export const CellTextComponent = meta.story({ name: 'CellText', render: () => { return ( @@ -379,9 +377,9 @@ export const CellTextComponent: Story = { ); }, -}; +}); -export const CellProfileComponent: Story = { +export const CellProfileComponent = meta.story({ name: 'CellProfile', render: () => { return ( @@ -404,9 +402,9 @@ export const CellProfileComponent: Story = { ); }, -}; +}); -export const SelectionSingleToggle: Story = { +export const SelectionSingleToggle = meta.story({ render: () => { const [selectedKeys, setSelectedKeys] = useState(new Set([])); @@ -442,9 +440,9 @@ export const SelectionSingleToggle: Story = { ); }, -}; +}); -export const SelectionMultiToggle: Story = { +export const SelectionMultiToggle = meta.story({ render: () => { const [selectedKeys, setSelectedKeys] = useState(new Set([])); @@ -480,9 +478,9 @@ export const SelectionMultiToggle: Story = { ); }, -}; +}); -export const SelectionSingleReplace: Story = { +export const SelectionSingleReplace = meta.story({ render: () => { const [selectedKeys, setSelectedKeys] = useState(new Set([])); @@ -518,9 +516,9 @@ export const SelectionSingleReplace: Story = { ); }, -}; +}); -export const SelectionMultiReplace: Story = { +export const SelectionMultiReplace = meta.story({ render: () => { const [selectedKeys, setSelectedKeys] = useState(new Set([])); @@ -556,9 +554,9 @@ export const SelectionMultiReplace: Story = { ); }, -}; +}); -export const SelectionToggleWithActions: Story = { +export const SelectionToggleWithActions = meta.story({ render: () => { const [selectedKeys, setSelectedKeys] = useState(new Set([])); @@ -595,9 +593,9 @@ export const SelectionToggleWithActions: Story = { ); }, -}; +}); -export const SelectionReplaceWithActions: Story = { +export const SelectionReplaceWithActions = meta.story({ render: () => { const [selectedKeys, setSelectedKeys] = useState(new Set([])); @@ -634,9 +632,9 @@ export const SelectionReplaceWithActions: Story = { ); }, -}; +}); -export const SelectionToggleWithLinks: Story = { +export const SelectionToggleWithLinks = meta.story({ render: () => { const [selectedKeys, setSelectedKeys] = useState(new Set([])); @@ -672,9 +670,9 @@ export const SelectionToggleWithLinks: Story = { ); }, -}; +}); -export const SelectionReplaceWithLinks: Story = { +export const SelectionReplaceWithLinks = meta.story({ render: () => { const [selectedKeys, setSelectedKeys] = useState(new Set([])); @@ -710,9 +708,9 @@ export const SelectionReplaceWithLinks: Story = { ); }, -}; +}); -export const SelectionWithDisabledRows: Story = { +export const SelectionWithDisabledRows = meta.story({ render: () => { const [selectedKeys, setSelectedKeys] = useState(new Set([])); @@ -749,9 +747,9 @@ export const SelectionWithDisabledRows: Story = { ); }, -}; +}); -export const SelectionWithPagination: Story = { +export const SelectionWithPagination = meta.story({ render: () => { const [selectedKeys, setSelectedKeys] = useState(new Set([])); @@ -789,9 +787,9 @@ export const SelectionWithPagination: Story = { ); }, -}; +}); -export const SelectionModePlayground: Story = { +export const SelectionModePlayground = meta.story({ render: () => { const [selectionMode, setSelectionMode] = useState<'single' | 'multiple'>( 'multiple', @@ -849,9 +847,9 @@ export const SelectionModePlayground: Story = { ); }, -}; +}); -export const SelectionBehaviorPlayground: Story = { +export const SelectionBehaviorPlayground = meta.story({ render: () => { const [selectionBehavior, setSelectionBehavior] = useState< 'toggle' | 'replace' @@ -909,4 +907,4 @@ export const SelectionBehaviorPlayground: Story = { ); }, -}; +}); diff --git a/packages/ui/src/components/TablePagination/TablePagination.stories.tsx b/packages/ui/src/components/TablePagination/TablePagination.stories.tsx index 4550d00abb..a7d949a31d 100644 --- a/packages/ui/src/components/TablePagination/TablePagination.stories.tsx +++ b/packages/ui/src/components/TablePagination/TablePagination.stories.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Backstage Authors + * Copyright 2025 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,13 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -// TODO: Bring useArgs() back when we update Storybook to 9 -// import { useArgs } from 'storybook/preview-api'; -import type { Meta, StoryObj } from '@storybook/react-vite'; +import preview from '../../../../../.storybook/preview'; import { TablePagination } from './TablePagination'; -const meta = { +const meta = preview.meta({ title: 'Backstage UI/TablePagination', component: TablePagination, argTypes: { @@ -30,12 +27,9 @@ const meta = { setOffset: { action: 'setOffset' }, setPageSize: { action: 'setPageSize' }, }, -} satisfies Meta; +}); -export default meta; -type Story = StoryObj; - -export const Default: Story = { +export const Default = meta.story({ args: { offset: 0, pageSize: 10, @@ -56,4 +50,4 @@ export const Default: Story = { /> ); }, -}; +}); diff --git a/packages/ui/src/components/Tabs/Tabs.stories.tsx b/packages/ui/src/components/Tabs/Tabs.stories.tsx index c818d0fe4b..2a02bedc8c 100644 --- a/packages/ui/src/components/Tabs/Tabs.stories.tsx +++ b/packages/ui/src/components/Tabs/Tabs.stories.tsx @@ -14,19 +14,17 @@ * limitations under the License. */ -import type { Meta, StoryFn, StoryObj } from '@storybook/react-vite'; +import preview from '../../../../../.storybook/preview'; +import type { StoryFn } from '@storybook/react-vite'; import { Tabs, TabList, Tab, TabPanel } from './Tabs'; import { MemoryRouter } from 'react-router-dom'; import { Box } from '../Box'; import { Text } from '../Text'; -const meta = { +const meta = preview.meta({ title: 'Backstage UI/Tabs', component: Tabs, -} satisfies Meta; - -export default meta; -type Story = StoryObj; +}); const withRouter = (Story: StoryFn) => ( @@ -34,7 +32,7 @@ const withRouter = (Story: StoryFn) => ( ); -export const Default: Story = { +export const Default = meta.story({ args: { children: '', }, @@ -48,9 +46,9 @@ export const Default: Story = { ), -}; +}); -export const WithTabPanels: Story = { +export const WithTabPanels = meta.story({ args: { children: '', }, @@ -73,9 +71,9 @@ export const WithTabPanels: Story = { ), -}; +}); -export const WithMockedURLTab2: Story = { +export const WithMockedURLTab2 = meta.story({ args: { children: '', }, @@ -105,9 +103,9 @@ export const WithMockedURLTab2: Story = { ), -}; +}); -export const WithMockedURLTab3: Story = { +export const WithMockedURLTab3 = meta.story({ args: { children: '', }, @@ -137,9 +135,9 @@ export const WithMockedURLTab3: Story = { ), -}; +}); -export const WithMockedURLNoMatch: Story = { +export const WithMockedURLNoMatch = meta.story({ args: { children: '', }, @@ -173,11 +171,11 @@ export const WithMockedURLNoMatch: Story = { ), -}; +}); // New stories for testing match strategies -export const ExactMatchingDefault: Story = { +export const ExactMatchingDefault = meta.story({ args: { children: '', }, @@ -211,9 +209,9 @@ export const ExactMatchingDefault: Story = { ), -}; +}); -export const PrefixMatchingForNestedRoutes: Story = { +export const PrefixMatchingForNestedRoutes = meta.story({ args: { children: '', }, @@ -251,9 +249,9 @@ export const PrefixMatchingForNestedRoutes: Story = { ), -}; +}); -export const PrefixMatchingDeepNesting: Story = { +export const PrefixMatchingDeepNesting = meta.story({ args: { children: '', }, @@ -286,9 +284,9 @@ export const PrefixMatchingDeepNesting: Story = { ), -}; +}); -export const MixedMatchingStrategies: Story = { +export const MixedMatchingStrategies = meta.story({ args: { children: '', }, @@ -337,9 +335,9 @@ export const MixedMatchingStrategies: Story = { ), -}; +}); -export const PrefixMatchingEdgeCases: Story = { +export const PrefixMatchingEdgeCases = meta.story({ args: { children: '', }, @@ -379,9 +377,9 @@ export const PrefixMatchingEdgeCases: Story = { ), -}; +}); -export const PrefixMatchingWithSlash: Story = { +export const PrefixMatchingWithSlash = meta.story({ args: { children: '', }, @@ -420,9 +418,9 @@ export const PrefixMatchingWithSlash: Story = { ), -}; +}); -export const RootPathMatching: Story = { +export const RootPathMatching = meta.story({ args: { children: '', }, @@ -454,9 +452,9 @@ export const RootPathMatching: Story = { ), -}; +}); -export const AutoSelectionOfTabs: Story = { +export const AutoSelectionOfTabs = meta.story({ args: { children: '', }, @@ -511,4 +509,4 @@ export const AutoSelectionOfTabs: Story = { ), -}; +}); diff --git a/packages/ui/src/components/TagGroup/TagGroup.stories.tsx b/packages/ui/src/components/TagGroup/TagGroup.stories.tsx index 7cc8d3c824..d33eed8bf1 100644 --- a/packages/ui/src/components/TagGroup/TagGroup.stories.tsx +++ b/packages/ui/src/components/TagGroup/TagGroup.stories.tsx @@ -14,8 +14,8 @@ * limitations under the License. */ +import preview from '../../../../../.storybook/preview'; import { useState } from 'react'; -import type { Meta, StoryObj } from '@storybook/react-vite'; import { TagGroup, Tag } from '.'; import type { Selection } from 'react-aria-components'; import { Flex } from '../../'; @@ -35,7 +35,7 @@ export interface ListItem { isDisabled?: boolean; } -const meta = { +const meta = preview.meta({ title: 'Backstage UI/TagGroup', component: TagGroup, argTypes: { @@ -54,10 +54,7 @@ const meta = { ), ], -} satisfies Meta>; - -export default meta; -type Story = StoryObj; +}); const initialList: ListItem[] = [ { id: 'banana', name: 'Banana', icon: }, @@ -74,7 +71,7 @@ const initialList: ListItem[] = [ { id: 'strawberry', name: 'Strawberry', icon: }, ]; -export const Default: Story = { +export const Default = meta.story({ args: { 'aria-label': 'Tag Group', }, @@ -85,11 +82,11 @@ export const Default: Story = { ))} ), -}; +}); -export const Sizes: Story = { +export const Sizes = meta.story({ args: { - ...Default.args, + ...Default.input.args, }, render: args => ( @@ -109,9 +106,9 @@ export const Sizes: Story = { ), -}; +}); -export const SelectionModeSingle: Story = { +export const SelectionModeSingle = meta.story({ args: { selectionMode: 'single', 'aria-label': 'Tag Group', @@ -130,9 +127,9 @@ export const SelectionModeSingle: Story = { ); }, -}; +}); -export const SelectionModeMultiple: Story = { +export const SelectionModeMultiple = meta.story({ args: { selectionMode: 'multiple', 'aria-label': 'Tag Group', @@ -153,11 +150,11 @@ export const SelectionModeMultiple: Story = { ); }, -}; +}); -export const WithIcon: Story = { +export const WithIcon = meta.story({ args: { - ...Default.args, + ...Default.input.args, }, render: args => ( @@ -168,9 +165,9 @@ export const WithIcon: Story = { ))} ), -}; +}); -export const WithLink: Story = { +export const WithLink = meta.story({ render: args => ( {initialList.map(item => ( @@ -180,9 +177,9 @@ export const WithLink: Story = { ))} ), -}; +}); -export const Disabled: Story = { +export const Disabled = meta.story({ render: args => ( {initialList.map(item => ( @@ -192,11 +189,11 @@ export const Disabled: Story = { ))} ), -}; +}); -export const RemovingTags: Story = { +export const RemovingTags = meta.story({ args: { - ...Default.args, + ...Default.input.args, }, render: args => { const [selected, setSelected] = useState(new Set(['travel'])); @@ -217,11 +214,11 @@ export const RemovingTags: Story = { ); }, -}; +}); -export const WithIconAndRemoveButton: Story = { +export const WithIconAndRemoveButton = meta.story({ args: { - ...Default.args, + ...Default.input.args, }, render: args => { const [selected, setSelected] = useState(new Set(['travel'])); @@ -244,4 +241,4 @@ export const WithIconAndRemoveButton: Story = { ); }, -}; +}); diff --git a/packages/ui/src/components/Text/Text.stories.tsx b/packages/ui/src/components/Text/Text.stories.tsx index 7f95f4d5a1..09a317716a 100644 --- a/packages/ui/src/components/Text/Text.stories.tsx +++ b/packages/ui/src/components/Text/Text.stories.tsx @@ -14,31 +14,28 @@ * limitations under the License. */ -import type { Meta, StoryObj } from '@storybook/react-vite'; +import preview from '../../../../../.storybook/preview'; import { Text } from './Text'; import { Flex } from '../Flex'; -const meta = { +const meta = preview.meta({ title: 'Backstage UI/Text', component: Text, args: { children: 'Text', }, -} satisfies Meta; +}); -export default meta; -type Story = StoryObj; - -export const Default: Story = { +export const Default = meta.story({ args: { children: "A man looks at a painting in a museum and says, “Brothers and sisters I have none, but that man's father is my father's son.” Who is in the painting?", }, -}; +}); -export const AllVariants: Story = { +export const AllVariants = meta.story({ args: { - ...Default.args, + ...Default.input.args, }, render: args => ( @@ -52,9 +49,9 @@ export const AllVariants: Story = { ), -}; +}); -export const AllWeights: Story = { +export const AllWeights = meta.story({ render: () => ( @@ -91,11 +88,11 @@ export const AllWeights: Story = { ), -}; +}); -export const AllColors: Story = { +export const AllColors = meta.story({ args: { - ...Default.args, + ...Default.input.args, }, render: args => ( @@ -106,30 +103,30 @@ export const AllColors: Story = { ), -}; +}); -export const Truncate: Story = { +export const Truncate = meta.story({ args: { - ...Default.args, + ...Default.input.args, truncate: true, as: 'p', style: { width: '480px' }, }, -}; +}); -export const Responsive: Story = { +export const Responsive = meta.story({ args: { - ...Default.args, + ...Default.input.args, variant: { xs: 'title-x-small', md: 'body-large', }, }, -}; +}); -export const WrappedInLink: Story = { +export const WrappedInLink = meta.story({ args: { - ...Default.args, + ...Default.input.args, }, decorators: [ Story => ( @@ -138,16 +135,16 @@ export const WrappedInLink: Story = {
), ], -}; +}); -export const CustomRender: Story = { +export const CustomRender = meta.story({ args: { - ...Default.args, + ...Default.input.args, as: 'label', }, -}; +}); -export const Playground: Story = { +export const Playground = meta.story({ render: () => ( Subtitle @@ -176,4 +173,4 @@ export const Playground: Story = { ), -}; +}); diff --git a/packages/ui/src/components/TextField/TextField.stories.tsx b/packages/ui/src/components/TextField/TextField.stories.tsx index 38115996ae..54457f351b 100644 --- a/packages/ui/src/components/TextField/TextField.stories.tsx +++ b/packages/ui/src/components/TextField/TextField.stories.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Backstage Authors + * Copyright 2025 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,15 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -import type { Meta, StoryObj } from '@storybook/react-vite'; +import preview from '../../../../../.storybook/preview'; import { TextField } from './TextField'; import { Form } from 'react-aria-components'; import { Flex } from '../Flex'; import { FieldLabel } from '../FieldLabel'; import { RiEyeLine, RiSparklingLine } from '@remixicon/react'; -const meta = { +const meta = preview.meta({ title: 'Backstage UI/TextField', component: TextField, argTypes: { @@ -32,12 +31,9 @@ const meta = { control: 'object', }, }, -} satisfies Meta; +}); -export default meta; -type Story = StoryObj; - -export const Default: Story = { +export const Default = meta.story({ args: { name: 'url', placeholder: 'Enter a URL', @@ -45,11 +41,11 @@ export const Default: Story = { maxWidth: '300px', }, }, -}; +}); -export const Sizes: Story = { +export const Sizes = meta.story({ args: { - ...Default.args, + ...Default.input.args, }, render: args => ( @@ -57,46 +53,46 @@ export const Sizes: Story = { } /> ), -}; +}); -export const DefaultValue: Story = { +export const DefaultValue = meta.story({ args: { - ...Default.args, + ...Default.input.args, defaultValue: 'https://example.com', }, -}; +}); -export const WithLabel: Story = { +export const WithLabel = meta.story({ args: { - ...Default.args, + ...Default.input.args, label: 'Label', }, -}; +}); -export const WithDescription: Story = { +export const WithDescription = meta.story({ args: { - ...WithLabel.args, + ...WithLabel.input.args, description: 'Description', }, -}; +}); -export const Required: Story = { +export const Required = meta.story({ args: { - ...WithLabel.args, + ...WithLabel.input.args, isRequired: true, }, -}; +}); -export const Disabled: Story = { +export const Disabled = meta.story({ args: { - ...Default.args, + ...Default.input.args, isDisabled: true, }, -}; +}); -export const WithIcon: Story = { +export const WithIcon = meta.story({ args: { - ...Default.args, + ...Default.input.args, }, render: args => ( } /> ), -}; +}); -export const DisabledWithIcon: Story = { +export const DisabledWithIcon = meta.story({ args: { - ...WithIcon.args, + ...WithIcon.input.args, isDisabled: true, }, - render: WithIcon.render, -}; + render: WithIcon.input.render, +}); -export const ShowError: Story = { +export const ShowError = meta.story({ args: { - ...WithLabel.args, + ...WithLabel.input.args, }, render: args => (
), -}; +}); -export const Validation: Story = { +export const Validation = meta.story({ args: { - ...WithLabel.args, + ...WithLabel.input.args, validate: value => (value === 'admin' ? 'Nice try!' : null), }, -}; +}); -export const CustomField: Story = { +export const CustomField = meta.story({ render: () => ( <> ), -}; +}); diff --git a/packages/ui/src/components/Tooltip/Tooltip.stories.tsx b/packages/ui/src/components/Tooltip/Tooltip.stories.tsx index cc6b513ed4..a636a356ef 100644 --- a/packages/ui/src/components/Tooltip/Tooltip.stories.tsx +++ b/packages/ui/src/components/Tooltip/Tooltip.stories.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Backstage Authors + * Copyright 2025 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,13 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -import type { Meta, StoryObj } from '@storybook/react-vite'; -import { Placement } from '@react-types/overlays'; +import preview from '../../../../../.storybook/preview'; import { TooltipTrigger, Tooltip } from './Tooltip'; import { Button } from '../Button/Button'; -const meta = { +const meta = preview.meta({ title: 'Backstage UI/Tooltip', component: TooltipTrigger, parameters: { layout: 'centered' }, @@ -30,10 +28,6 @@ const meta = { isDisabled: { control: { type: 'boolean' }, }, - placement: { - options: ['top', 'right', 'bottom', 'left'], - control: { type: 'inline-radio' }, - }, delay: { control: { type: 'number' }, }, @@ -41,7 +35,7 @@ const meta = { control: { type: 'number' }, }, }, - render: ({ children, isOpen, isDisabled, placement, delay, closeDelay }) => ( + render: ({ children, isOpen, isDisabled, delay, closeDelay }) => ( - {children ?? 'I am a tooltip'} + {children ?? 'I am a tooltip'} ), -} as Meta<{ - children?: string; - isOpen?: boolean; - isDisabled?: boolean; - placement?: Placement; - delay?: number; - closeDelay?: number; -}>; +}); -export default meta; -type Story = StoryObj; - -export const Default: Story = { +export const Default = meta.story({ args: { children: 'I am a tooltip', }, -}; +}); -export const IsOpen: Story = { +export const IsOpen = meta.story({ args: { - ...Default.args, + ...Default.input.args, isOpen: true, }, -}; +}); -export const IsDisabled: Story = { +export const IsDisabled = meta.story({ args: { - ...Default.args, + ...Default.input.args, isDisabled: true, }, -}; +}); -export const NoDelays: Story = { +export const NoDelays = meta.story({ args: { - ...Default.args, + ...Default.input.args, delay: 0, closeDelay: 0, }, -}; +}); -export const OrthogonalPlacements: Story = { +export const OrthogonalPlacements = meta.story({ parameters: { controls: { exclude: ['placement'], }, }, args: { - ...Default.args, + ...Default.input.args, isOpen: true, }, render: ({ isOpen, children }) => { @@ -113,13 +97,13 @@ export const OrthogonalPlacements: Story = { ); }, -}; +}); -export const WithLongText: Story = { +export const WithLongText = meta.story({ args: { - ...Default.args, + ...Default.input.args, isOpen: true, children: 'I am a tooltip with a very long text. orem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', }, -}; +}); diff --git a/packages/ui/src/components/VisuallyHidden/VisuallyHidden.stories.tsx b/packages/ui/src/components/VisuallyHidden/VisuallyHidden.stories.tsx index 9706edfc9b..cc75adbd5e 100644 --- a/packages/ui/src/components/VisuallyHidden/VisuallyHidden.stories.tsx +++ b/packages/ui/src/components/VisuallyHidden/VisuallyHidden.stories.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Backstage Authors + * Copyright 2025 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,13 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -import type { Meta, StoryObj } from '@storybook/react-vite'; +import preview from '../../../../../.storybook/preview'; import { VisuallyHidden } from './VisuallyHidden'; import { Text } from '../Text'; import { Flex } from '../Flex'; -const meta = { +const meta = preview.meta({ title: 'Backstage UI/VisuallyHidden', component: VisuallyHidden, parameters: { @@ -30,12 +29,9 @@ const meta = { }, }, }, -} satisfies Meta; +}); -export default meta; -type Story = StoryObj; - -export const Default: Story = { +export const Default = meta.story({ render: () => ( @@ -48,9 +44,9 @@ export const Default: Story = { ), -}; +}); -export const ExampleUsage: Story = { +export const ExampleUsage = meta.story({ render: () => ( @@ -70,4 +66,4 @@ export const ExampleUsage: Story = { ), -}; +}); diff --git a/packages/ui/src/css/core.css b/packages/ui/src/css/core.css index 5be23e7a1b..321ca07eff 100644 --- a/packages/ui/src/css/core.css +++ b/packages/ui/src/css/core.css @@ -27,7 +27,7 @@ } body { - background-color: var(--bui-bg); + background-color: var(--bui-bg-surface-0); /* Text defaults */ color: var(--bui-fg-primary); diff --git a/packages/ui/src/css/tokens.css b/packages/ui/src/css/tokens.css index 028c60311d..459d98d48f 100644 --- a/packages/ui/src/css/tokens.css +++ b/packages/ui/src/css/tokens.css @@ -81,9 +81,10 @@ --bui-gray-8: #595959; /* Background Colors */ - --bui-bg: var(--bui-gray-1); + --bui-bg-surface-0: var(--bui-gray-1); --bui-bg-surface-1: var(--bui-white); - --bui-bg-surface-2: var(--bui-gray-2); + --bui-bg-surface-2: var(--bui-gray-1); + --bui-bg-surface-3: var(--bui-gray-2); --bui-bg-solid: #1f5493; --bui-bg-solid-hover: #163a66; --bui-bg-solid-pressed: #0f2b4e; @@ -140,9 +141,10 @@ --bui-gray-8: #b4b4b4; /* Background Colors */ - --bui-bg: #333333; - --bui-bg-surface-1: #424242; + --bui-bg-surface-0: #333333; + --bui-bg-surface-1: var(--bui-gray-1); --bui-bg-surface-2: var(--bui-gray-2); + --bui-bg-surface-3: var(--bui-gray-3); --bui-bg-solid: #9cc9ff; --bui-bg-solid-hover: #83b9fd; --bui-bg-solid-pressed: #83b9fd; diff --git a/packages/yarn-plugin/CHANGELOG.md b/packages/yarn-plugin/CHANGELOG.md index 3c1903a019..20d37cf076 100644 --- a/packages/yarn-plugin/CHANGELOG.md +++ b/packages/yarn-plugin/CHANGELOG.md @@ -1,5 +1,12 @@ # yarn-plugin-backstage +## 0.0.8 + +### Patch Changes + +- Updated dependencies + - @backstage/cli-common@0.1.16 + ## 0.0.8-next.0 ### Patch Changes diff --git a/packages/yarn-plugin/package.json b/packages/yarn-plugin/package.json index 5a7bec9bcc..de8b7955d3 100644 --- a/packages/yarn-plugin/package.json +++ b/packages/yarn-plugin/package.json @@ -1,6 +1,6 @@ { "name": "yarn-plugin-backstage", - "version": "0.0.8-next.0", + "version": "0.0.8", "description": "Yarn plugin for working with Backstage monorepos", "backstage": { "role": "node-library" diff --git a/plugins/api-docs/CHANGELOG.md b/plugins/api-docs/CHANGELOG.md index 7db04d494c..58db7fac24 100644 --- a/plugins/api-docs/CHANGELOG.md +++ b/plugins/api-docs/CHANGELOG.md @@ -1,5 +1,34 @@ # @backstage/plugin-api-docs +## 0.13.2 + +### Patch Changes + +- f3f84f1: Minor extension type updates after frontend API bump +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- Updated dependencies + - @backstage/plugin-catalog@1.32.1 + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/plugin-permission-react@0.4.39 + +## 0.13.2-next.1 + +### Patch Changes + +- f3f84f1: Minor extension type updates after frontend API bump +- Updated dependencies + - @backstage/plugin-catalog@1.32.1-next.1 + - @backstage/frontend-plugin-api@0.13.2-next.1 + - @backstage/plugin-catalog-react@1.21.4-next.2 + - @backstage/core-components@0.18.4-next.2 + - @backstage/catalog-model@1.7.6 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-permission-react@0.4.39-next.0 + ## 0.13.2-next.0 ### Patch Changes diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index e8f7392e87..fd387bdbae 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-api-docs", - "version": "0.13.2-next.0", + "version": "0.13.2", "description": "A Backstage plugin that helps represent API entities in the frontend", "backstage": { "role": "frontend-plugin", diff --git a/plugins/app-backend/CHANGELOG.md b/plugins/app-backend/CHANGELOG.md index c28c59c78c..1923dd74a3 100644 --- a/plugins/app-backend/CHANGELOG.md +++ b/plugins/app-backend/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-app-backend +## 0.5.9 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/plugin-app-node@0.1.40 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/config-loader@1.10.7 + +## 0.5.9-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-app-node@0.1.40-next.1 + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config-loader@1.10.7-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + ## 0.5.9-next.0 ### Patch Changes diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index d41dea1880..9ab956713f 100644 --- a/plugins/app-backend/package.json +++ b/plugins/app-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-app-backend", - "version": "0.5.9-next.0", + "version": "0.5.9", "description": "A Backstage backend plugin that serves the Backstage frontend app", "backstage": { "role": "backend-plugin", diff --git a/plugins/app-node/CHANGELOG.md b/plugins/app-node/CHANGELOG.md index 1f1f124d16..ceab019e5a 100644 --- a/plugins/app-node/CHANGELOG.md +++ b/plugins/app-node/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-app-node +## 0.1.40 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/config-loader@1.10.7 + +## 0.1.40-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config-loader@1.10.7-next.1 + ## 0.1.40-next.0 ### Patch Changes diff --git a/plugins/app-node/package.json b/plugins/app-node/package.json index 77049a44c4..c41733eb04 100644 --- a/plugins/app-node/package.json +++ b/plugins/app-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-app-node", - "version": "0.1.40-next.0", + "version": "0.1.40", "description": "Node.js library for the app plugin", "backstage": { "role": "node-library", diff --git a/plugins/app-visualizer/CHANGELOG.md b/plugins/app-visualizer/CHANGELOG.md index d04d2461ba..0dc550bb53 100644 --- a/plugins/app-visualizer/CHANGELOG.md +++ b/plugins/app-visualizer/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-app-visualizer +## 0.1.27-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/ui@0.11.0-next.0 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/frontend-plugin-api@0.13.2 + +## 0.1.26 + +### Patch Changes + +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- Updated dependencies + - @backstage/ui@0.10.0 + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + ## 0.1.26-next.1 ### Patch Changes diff --git a/plugins/app-visualizer/package.json b/plugins/app-visualizer/package.json index 8b580ea17b..b736b07cd6 100644 --- a/plugins/app-visualizer/package.json +++ b/plugins/app-visualizer/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-app-visualizer", - "version": "0.1.26-next.1", + "version": "0.1.27-next.0", "description": "Visualizes the Backstage app structure", "backstage": { "role": "frontend-plugin", diff --git a/plugins/app/CHANGELOG.md b/plugins/app/CHANGELOG.md index 0e84389ecd..66e1ca5b0b 100644 --- a/plugins/app/CHANGELOG.md +++ b/plugins/app/CHANGELOG.md @@ -1,5 +1,36 @@ # @backstage/plugin-app +## 0.3.3 + +### Patch Changes + +- f3f84f1: Minor extension type updates after frontend API bump +- f7bc228: Support to set `defaultLanguage` and `availableLanguages` for the app language API in the new frontend system +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/theme@0.7.1 + - @backstage/integration-react@1.2.13 + - @backstage/plugin-permission-react@0.4.39 + +## 0.3.3-next.1 + +### Patch Changes + +- f3f84f1: Minor extension type updates after frontend API bump +- f7bc228: Support to set `defaultLanguage` and `availableLanguages` for the app language API in the new frontend system +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2-next.1 + - @backstage/core-components@0.18.4-next.2 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/integration-react@1.2.13-next.0 + - @backstage/theme@0.7.1-next.0 + - @backstage/types@1.2.2 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-permission-react@0.4.39-next.0 + ## 0.3.3-next.0 ### Patch Changes diff --git a/plugins/app/package.json b/plugins/app/package.json index 8a87cae63e..a6a25d08ad 100644 --- a/plugins/app/package.json +++ b/plugins/app/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-app", - "version": "0.3.3-next.0", + "version": "0.3.3", "backstage": { "role": "frontend-plugin", "pluginId": "app", diff --git a/plugins/auth-backend-module-atlassian-provider/CHANGELOG.md b/plugins/auth-backend-module-atlassian-provider/CHANGELOG.md index 29cb492841..b78cce757e 100644 --- a/plugins/auth-backend-module-atlassian-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-atlassian-provider/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-auth-backend-module-atlassian-provider +## 0.4.10 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## 0.4.10-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + ## 0.4.10-next.0 ### Patch Changes diff --git a/plugins/auth-backend-module-atlassian-provider/package.json b/plugins/auth-backend-module-atlassian-provider/package.json index 6edf029908..28f4031eab 100644 --- a/plugins/auth-backend-module-atlassian-provider/package.json +++ b/plugins/auth-backend-module-atlassian-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-atlassian-provider", - "version": "0.4.10-next.0", + "version": "0.4.10", "description": "The atlassian-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-auth0-provider/CHANGELOG.md b/plugins/auth-backend-module-auth0-provider/CHANGELOG.md index 9e73851696..6e9806b643 100644 --- a/plugins/auth-backend-module-auth0-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-auth0-provider/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-auth-backend-module-auth0-provider +## 0.2.10 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## 0.2.10-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + ## 0.2.10-next.0 ### Patch Changes diff --git a/plugins/auth-backend-module-auth0-provider/package.json b/plugins/auth-backend-module-auth0-provider/package.json index bd1dacce32..8b749bc420 100644 --- a/plugins/auth-backend-module-auth0-provider/package.json +++ b/plugins/auth-backend-module-auth0-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-auth0-provider", - "version": "0.2.10-next.0", + "version": "0.2.10", "description": "The auth0-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-aws-alb-provider/CHANGELOG.md b/plugins/auth-backend-module-aws-alb-provider/CHANGELOG.md index afea70a08b..aff6333c3c 100644 --- a/plugins/auth-backend-module-aws-alb-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-aws-alb-provider/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-auth-backend-module-aws-alb-provider +## 0.4.10 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/plugin-auth-backend@0.25.7 + - @backstage/backend-plugin-api@1.6.0 + +## 0.4.10-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-backend@0.25.7-next.1 + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/errors@1.2.7 + ## 0.4.10-next.0 ### Patch Changes diff --git a/plugins/auth-backend-module-aws-alb-provider/package.json b/plugins/auth-backend-module-aws-alb-provider/package.json index d1776aca35..65ef39f0d5 100644 --- a/plugins/auth-backend-module-aws-alb-provider/package.json +++ b/plugins/auth-backend-module-aws-alb-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-aws-alb-provider", - "version": "0.4.10-next.0", + "version": "0.4.10", "description": "The aws-alb provider module for the Backstage auth backend.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-azure-easyauth-provider/CHANGELOG.md b/plugins/auth-backend-module-azure-easyauth-provider/CHANGELOG.md index 9464f4ce1d..4829c70373 100644 --- a/plugins/auth-backend-module-azure-easyauth-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-azure-easyauth-provider/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-auth-backend-module-azure-easyauth-provider +## 0.2.15 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## 0.2.15-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/errors@1.2.7 + ## 0.2.15-next.0 ### Patch Changes diff --git a/plugins/auth-backend-module-azure-easyauth-provider/package.json b/plugins/auth-backend-module-azure-easyauth-provider/package.json index f48ac8d234..ba0b80c93c 100644 --- a/plugins/auth-backend-module-azure-easyauth-provider/package.json +++ b/plugins/auth-backend-module-azure-easyauth-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-azure-easyauth-provider", - "version": "0.2.15-next.0", + "version": "0.2.15", "description": "The azure-easyauth-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-bitbucket-provider/CHANGELOG.md b/plugins/auth-backend-module-bitbucket-provider/CHANGELOG.md index f4cb03f95e..0870c56aff 100644 --- a/plugins/auth-backend-module-bitbucket-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-bitbucket-provider/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-auth-backend-module-bitbucket-provider +## 0.3.10 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## 0.3.10-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + ## 0.3.10-next.0 ### Patch Changes diff --git a/plugins/auth-backend-module-bitbucket-provider/package.json b/plugins/auth-backend-module-bitbucket-provider/package.json index 1131d0278c..83efe1ea70 100644 --- a/plugins/auth-backend-module-bitbucket-provider/package.json +++ b/plugins/auth-backend-module-bitbucket-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-bitbucket-provider", - "version": "0.3.10-next.0", + "version": "0.3.10", "description": "The bitbucket-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-bitbucket-server-provider/CHANGELOG.md b/plugins/auth-backend-module-bitbucket-server-provider/CHANGELOG.md index c29d1ef826..2f9860e317 100644 --- a/plugins/auth-backend-module-bitbucket-server-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-bitbucket-server-provider/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-auth-backend-module-bitbucket-server-provider +## 0.2.10 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## 0.2.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + ## 0.2.10-next.0 ### Patch Changes diff --git a/plugins/auth-backend-module-bitbucket-server-provider/package.json b/plugins/auth-backend-module-bitbucket-server-provider/package.json index 9d410e8da0..701fe9d337 100644 --- a/plugins/auth-backend-module-bitbucket-server-provider/package.json +++ b/plugins/auth-backend-module-bitbucket-server-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-bitbucket-server-provider", - "version": "0.2.10-next.0", + "version": "0.2.10", "description": "The bitbucket-server-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-cloudflare-access-provider/CHANGELOG.md b/plugins/auth-backend-module-cloudflare-access-provider/CHANGELOG.md index b7928bd822..06d2bf174c 100644 --- a/plugins/auth-backend-module-cloudflare-access-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-cloudflare-access-provider/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-auth-backend-module-cloudflare-access-provider +## 0.4.10 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## 0.4.10-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + ## 0.4.10-next.0 ### Patch Changes diff --git a/plugins/auth-backend-module-cloudflare-access-provider/package.json b/plugins/auth-backend-module-cloudflare-access-provider/package.json index 3b1a38f544..0cea95105c 100644 --- a/plugins/auth-backend-module-cloudflare-access-provider/package.json +++ b/plugins/auth-backend-module-cloudflare-access-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-cloudflare-access-provider", - "version": "0.4.10-next.0", + "version": "0.4.10", "description": "The cloudflare-access-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-gcp-iap-provider/CHANGELOG.md b/plugins/auth-backend-module-gcp-iap-provider/CHANGELOG.md index 7fc1271072..1243523582 100644 --- a/plugins/auth-backend-module-gcp-iap-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-gcp-iap-provider/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-auth-backend-module-gcp-iap-provider +## 0.4.10 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## 0.4.10-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + ## 0.4.10-next.0 ### Patch Changes diff --git a/plugins/auth-backend-module-gcp-iap-provider/package.json b/plugins/auth-backend-module-gcp-iap-provider/package.json index 99596dea0e..e045da8fc8 100644 --- a/plugins/auth-backend-module-gcp-iap-provider/package.json +++ b/plugins/auth-backend-module-gcp-iap-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-gcp-iap-provider", - "version": "0.4.10-next.0", + "version": "0.4.10", "description": "A GCP IAP auth provider module for the Backstage auth backend", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-github-provider/CHANGELOG.md b/plugins/auth-backend-module-github-provider/CHANGELOG.md index 23bb42eac1..a8458f6b1d 100644 --- a/plugins/auth-backend-module-github-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-github-provider/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-auth-backend-module-github-provider +## 0.4.0 + +### Minor Changes + +- b3286d5: Added the `github.com/user-id` annotation to store GitHub's user ID (immutable) in user entities. Also includes addition of the `userIdMatchingUserEntityAnnotation` sign-in resolver that matches users by the new ID. + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## 0.3.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + ## 0.3.10-next.0 ### Patch Changes diff --git a/plugins/auth-backend-module-github-provider/package.json b/plugins/auth-backend-module-github-provider/package.json index 28a9404ef3..ce418e2b08 100644 --- a/plugins/auth-backend-module-github-provider/package.json +++ b/plugins/auth-backend-module-github-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-github-provider", - "version": "0.3.10-next.0", + "version": "0.4.0", "description": "The github-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-github-provider/report.api.md b/plugins/auth-backend-module-github-provider/report.api.md index 6bad840d00..4581115679 100644 --- a/plugins/auth-backend-module-github-provider/report.api.md +++ b/plugins/auth-backend-module-github-provider/report.api.md @@ -17,13 +17,25 @@ export default authModuleGithubProvider; // @public (undocumented) export const githubAuthenticator: OAuthAuthenticator< PassportOAuthAuthenticatorHelper, - PassportProfile + GithubProfile >; +// @public (undocumented) +export type GithubProfile = PassportProfile & { + nodeId?: string; +}; + // @public export namespace githubSignInResolvers { const usernameMatchingUserEntityName: SignInResolverFactory< - OAuthAuthenticatorResult, + OAuthAuthenticatorResult, + | { + dangerouslyAllowSignInWithoutUserInCatalog?: boolean | undefined; + } + | undefined + >; + const userIdMatchingUserEntityAnnotation: SignInResolverFactory< + OAuthAuthenticatorResult, | { dangerouslyAllowSignInWithoutUserInCatalog?: boolean | undefined; } diff --git a/plugins/auth-backend-module-github-provider/src/authenticator.ts b/plugins/auth-backend-module-github-provider/src/authenticator.ts index e9dc29e4a6..fa3e2b0987 100644 --- a/plugins/auth-backend-module-github-provider/src/authenticator.ts +++ b/plugins/auth-backend-module-github-provider/src/authenticator.ts @@ -22,10 +22,18 @@ import { PassportProfile, } from '@backstage/plugin-auth-node'; +/** @public */ +export type GithubProfile = PassportProfile & { + nodeId?: string; +}; + const ACCESS_TOKEN_PREFIX = 'access-token-v2.'; /** @public */ -export const githubAuthenticator = createOAuthAuthenticator({ +export const githubAuthenticator = createOAuthAuthenticator< + PassportOAuthAuthenticatorHelper, + GithubProfile +>({ defaultProfileTransform: PassportOAuthAuthenticatorHelper.defaultProfileTransform, scopes: { @@ -90,7 +98,7 @@ export const githubAuthenticator = createOAuthAuthenticator({ if (!session.refreshToken && !session.expiresInSeconds) { session.refreshToken = ACCESS_TOKEN_PREFIX + session.accessToken; } - return { fullProfile, session }; + return { fullProfile: fullProfile as GithubProfile, session }; }, async refresh(input, helper) { @@ -115,7 +123,7 @@ export const githubAuthenticator = createOAuthAuthenticator({ }); return { - fullProfile, + fullProfile: fullProfile as GithubProfile, session: { accessToken, tokenType: 'bearer', diff --git a/plugins/auth-backend-module-github-provider/src/index.ts b/plugins/auth-backend-module-github-provider/src/index.ts index 646ba7c92a..678e188461 100644 --- a/plugins/auth-backend-module-github-provider/src/index.ts +++ b/plugins/auth-backend-module-github-provider/src/index.ts @@ -20,6 +20,6 @@ * @packageDocumentation */ -export { githubAuthenticator } from './authenticator'; +export { githubAuthenticator, type GithubProfile } from './authenticator'; export { authModuleGithubProvider as default } from './module'; export { githubSignInResolvers } from './resolvers'; diff --git a/plugins/auth-backend-module-github-provider/src/resolvers.ts b/plugins/auth-backend-module-github-provider/src/resolvers.ts index 5a6934439f..e065432826 100644 --- a/plugins/auth-backend-module-github-provider/src/resolvers.ts +++ b/plugins/auth-backend-module-github-provider/src/resolvers.ts @@ -17,11 +17,12 @@ import { createSignInResolverFactory, OAuthAuthenticatorResult, - PassportProfile, SignInInfo, } from '@backstage/plugin-auth-node'; import { z } from 'zod'; +import { GithubProfile } from './authenticator'; + /** * Available sign-in resolvers for the GitHub auth provider. * @@ -39,7 +40,7 @@ export namespace githubSignInResolvers { .optional(), create(options = {}) { return async ( - info: SignInInfo>, + info: SignInInfo>, ctx, ) => { const { fullProfile } = info.result; @@ -63,4 +64,44 @@ export namespace githubSignInResolvers { }; }, }); + + /** + * Looks up the user by matching their GitHub user ID to the github.com/user-id annotation. + */ + export const userIdMatchingUserEntityAnnotation = createSignInResolverFactory( + { + optionsSchema: z + .object({ + dangerouslyAllowSignInWithoutUserInCatalog: z.boolean().optional(), + }) + .optional(), + create(options = {}) { + return async ( + info: SignInInfo>, + ctx, + ) => { + const { fullProfile } = info.result; + + const userId = fullProfile.nodeId; + if (!userId) { + throw new Error(`GitHub user profile does not contain a user ID`); + } + + return ctx.signInWithCatalogUser( + { + annotations: { + 'github.com/user-id': userId, + }, + }, + { + dangerousEntityRefFallback: + options?.dangerouslyAllowSignInWithoutUserInCatalog + ? { entityRef: { name: userId } } + : undefined, + }, + ); + }; + }, + }, + ); } diff --git a/plugins/auth-backend-module-gitlab-provider/CHANGELOG.md b/plugins/auth-backend-module-gitlab-provider/CHANGELOG.md index 0cf1db7128..c31ef87722 100644 --- a/plugins/auth-backend-module-gitlab-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-gitlab-provider/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-auth-backend-module-gitlab-provider +## 0.3.10 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## 0.3.10-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + ## 0.3.10-next.0 ### Patch Changes diff --git a/plugins/auth-backend-module-gitlab-provider/package.json b/plugins/auth-backend-module-gitlab-provider/package.json index ee06982336..81b2450555 100644 --- a/plugins/auth-backend-module-gitlab-provider/package.json +++ b/plugins/auth-backend-module-gitlab-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-gitlab-provider", - "version": "0.3.10-next.0", + "version": "0.3.10", "description": "The gitlab-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-google-provider/CHANGELOG.md b/plugins/auth-backend-module-google-provider/CHANGELOG.md index 6c21b76fef..ef7f4a6506 100644 --- a/plugins/auth-backend-module-google-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-google-provider/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-auth-backend-module-google-provider +## 0.3.10 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## 0.3.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + ## 0.3.10-next.0 ### Patch Changes diff --git a/plugins/auth-backend-module-google-provider/package.json b/plugins/auth-backend-module-google-provider/package.json index c0d04e491c..bc2523dbdb 100644 --- a/plugins/auth-backend-module-google-provider/package.json +++ b/plugins/auth-backend-module-google-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-google-provider", - "version": "0.3.10-next.0", + "version": "0.3.10", "description": "A Google auth provider module for the Backstage auth backend", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-guest-provider/CHANGELOG.md b/plugins/auth-backend-module-guest-provider/CHANGELOG.md index 629e851ce9..221b83037e 100644 --- a/plugins/auth-backend-module-guest-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-guest-provider/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-auth-backend-module-guest-provider +## 0.2.15 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## 0.2.15-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/errors@1.2.7 + ## 0.2.15-next.0 ### Patch Changes diff --git a/plugins/auth-backend-module-guest-provider/package.json b/plugins/auth-backend-module-guest-provider/package.json index 5f129b83b9..726674a1ae 100644 --- a/plugins/auth-backend-module-guest-provider/package.json +++ b/plugins/auth-backend-module-guest-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-guest-provider", - "version": "0.2.15-next.0", + "version": "0.2.15", "description": "The guest-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-microsoft-provider/CHANGELOG.md b/plugins/auth-backend-module-microsoft-provider/CHANGELOG.md index 4353509f9c..7e4b112021 100644 --- a/plugins/auth-backend-module-microsoft-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-microsoft-provider/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-auth-backend-module-microsoft-provider +## 0.3.10 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## 0.3.10-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + ## 0.3.10-next.0 ### Patch Changes diff --git a/plugins/auth-backend-module-microsoft-provider/package.json b/plugins/auth-backend-module-microsoft-provider/package.json index 9b7209cc2c..10e7b2ebec 100644 --- a/plugins/auth-backend-module-microsoft-provider/package.json +++ b/plugins/auth-backend-module-microsoft-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-microsoft-provider", - "version": "0.3.10-next.0", + "version": "0.3.10", "description": "The microsoft-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-oauth2-provider/CHANGELOG.md b/plugins/auth-backend-module-oauth2-provider/CHANGELOG.md index dc10e9a4f8..8dadd4938e 100644 --- a/plugins/auth-backend-module-oauth2-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-oauth2-provider/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-auth-backend-module-oauth2-provider +## 0.4.10 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## 0.4.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + ## 0.4.10-next.0 ### Patch Changes diff --git a/plugins/auth-backend-module-oauth2-provider/package.json b/plugins/auth-backend-module-oauth2-provider/package.json index d7c1c62aea..7ec85a39a0 100644 --- a/plugins/auth-backend-module-oauth2-provider/package.json +++ b/plugins/auth-backend-module-oauth2-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-oauth2-provider", - "version": "0.4.10-next.0", + "version": "0.4.10", "description": "The oauth2-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-oauth2-proxy-provider/CHANGELOG.md b/plugins/auth-backend-module-oauth2-proxy-provider/CHANGELOG.md index c791003a0f..faa632f587 100644 --- a/plugins/auth-backend-module-oauth2-proxy-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-oauth2-proxy-provider/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-auth-backend-module-oauth2-proxy-provider +## 0.2.15 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## 0.2.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/errors@1.2.7 + ## 0.2.15-next.0 ### Patch Changes diff --git a/plugins/auth-backend-module-oauth2-proxy-provider/package.json b/plugins/auth-backend-module-oauth2-proxy-provider/package.json index c6d4fbe77d..483022a70a 100644 --- a/plugins/auth-backend-module-oauth2-proxy-provider/package.json +++ b/plugins/auth-backend-module-oauth2-proxy-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-oauth2-proxy-provider", - "version": "0.2.15-next.0", + "version": "0.2.15", "description": "The oauth2-proxy-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-oidc-provider/CHANGELOG.md b/plugins/auth-backend-module-oidc-provider/CHANGELOG.md index 50c0e98d58..591f1139e9 100644 --- a/plugins/auth-backend-module-oidc-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-oidc-provider/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/plugin-auth-backend-module-oidc-provider +## 0.4.11-next.0 + +### Patch Changes + +- e54fcb2: Added support for custom start URL search parameters (with the new `startUrlSearchParams` config property) +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/config@1.3.6 + - @backstage/types@1.2.2 + - @backstage/plugin-auth-backend@0.25.7 + - @backstage/plugin-auth-node@0.6.10 + +## 0.4.10 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/plugin-auth-backend@0.25.7 + - @backstage/backend-plugin-api@1.6.0 + +## 0.4.10-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-backend@0.25.7-next.1 + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/types@1.2.2 + ## 0.4.10-next.0 ### Patch Changes diff --git a/plugins/auth-backend-module-oidc-provider/config.d.ts b/plugins/auth-backend-module-oidc-provider/config.d.ts index c11b9319ec..f25d13ae2e 100644 --- a/plugins/auth-backend-module-oidc-provider/config.d.ts +++ b/plugins/auth-backend-module-oidc-provider/config.d.ts @@ -33,6 +33,7 @@ export interface Config { additionalScopes?: string | string[]; prompt?: string; timeout?: HumanDuration | string; + startUrlSearchParams?: [string: string]; signIn?: { resolvers: Array< | { diff --git a/plugins/auth-backend-module-oidc-provider/package.json b/plugins/auth-backend-module-oidc-provider/package.json index 5bc7a04766..933182d80d 100644 --- a/plugins/auth-backend-module-oidc-provider/package.json +++ b/plugins/auth-backend-module-oidc-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-oidc-provider", - "version": "0.4.10-next.0", + "version": "0.4.11-next.0", "description": "The oidc-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-oidc-provider/report.api.md b/plugins/auth-backend-module-oidc-provider/report.api.md index 11cde22db1..ab7d2bda49 100644 --- a/plugins/auth-backend-module-oidc-provider/report.api.md +++ b/plugins/auth-backend-module-oidc-provider/report.api.md @@ -25,6 +25,7 @@ export const oidcAuthenticator: OAuthAuthenticator< client: BaseClient; strategy: Strategy; }>; + searchParams: Record; }, OidcAuthResult >; diff --git a/plugins/auth-backend-module-oidc-provider/src/authenticator.test.ts b/plugins/auth-backend-module-oidc-provider/src/authenticator.test.ts index c327d4ecc5..1940a71082 100644 --- a/plugins/auth-backend-module-oidc-provider/src/authenticator.test.ts +++ b/plugins/auth-backend-module-oidc-provider/src/authenticator.test.ts @@ -279,6 +279,62 @@ describe('oidcAuthenticator', () => { expect(searchParams.get('response_type')).toBe('code'); }); + it('passes custom start URL search parameters', async () => { + const customImplementation = oidcAuthenticator.initialize({ + callbackUrl: 'https://backstage.test/callback', + config: new ConfigReader({ + metadataUrl: 'https://oidc.test/.well-known/openid-configuration', + clientId: 'clientId123', + clientSecret: 'clientSecret', + startUrlSearchParams: { + foo: '1', + bar: '2', + }, + }), + }); + + const startResponse = await oidcAuthenticator.start( + startRequest, + customImplementation, + ); + + const { searchParams } = new URL(startResponse.url); + + expect(searchParams.get('foo')).toBe('1'); + expect(searchParams.get('bar')).toBe('2'); + }); + + it('does not override the core start URL search parameters with custom ones', async () => { + const customImplementation = oidcAuthenticator.initialize({ + callbackUrl: 'https://backstage.test/callback', + config: new ConfigReader({ + metadataUrl: 'https://oidc.test/.well-known/openid-configuration', + clientId: 'clientId123', + clientSecret: 'clientSecret', + startUrlSearchParams: { + foo: '1', + prompt: 'customPrompt', + scope: 'customScope', + state: 'customState', + nonce: 'customNonce', + }, + }), + }); + + const startResponse = await oidcAuthenticator.start( + startRequest, + customImplementation, + ); + + const { searchParams } = new URL(startResponse.url); + + expect(searchParams.get('foo')).toBe('1'); + expect(searchParams.get('scope')).not.toBe('customScope'); + expect(searchParams.get('state')).not.toBe('customState'); + expect(searchParams.get('nonce')).not.toBe('customNonce'); + expect(searchParams.get('prompt')).not.toBe('customPrompt'); + }); + it('passes a nonce', async () => { const startResponse = await oidcAuthenticator.start( startRequest, diff --git a/plugins/auth-backend-module-oidc-provider/src/authenticator.ts b/plugins/auth-backend-module-oidc-provider/src/authenticator.ts index 6e7022f7cf..316ead3954 100644 --- a/plugins/auth-backend-module-oidc-provider/src/authenticator.ts +++ b/plugins/auth-backend-module-oidc-provider/src/authenticator.ts @@ -83,6 +83,9 @@ export const oidcAuthenticator = createOAuthAuthenticator({ ); const initializedPrompt = config.getOptionalString('prompt'); + const startUrlSearchParams: Record = + config.getOptional('startUrlSearchParams') || {}; + if (config.has('scope')) { throw new Error( 'The oidc provider no longer supports the "scope" configuration option. Please use the "additionalScopes" option instead.', @@ -143,17 +146,21 @@ export const oidcAuthenticator = createOAuthAuthenticator({ return { helper, client, strategy }; }); - return { initializedPrompt, promise }; + return { initializedPrompt, promise, searchParams: startUrlSearchParams }; }, async start(input, ctx) { - const { initializedPrompt, promise } = ctx; + const { initializedPrompt, promise, searchParams } = ctx; const { helper } = await promise; + + // Merge the custom start URL params, but do not override the standard params (scope, state etc) const options: Record = { + ...searchParams, scope: input.scope, state: input.state, nonce: crypto.randomBytes(16).toString('base64'), }; + const prompt = initializedPrompt || 'none'; if (prompt !== 'auto') { options.prompt = prompt; diff --git a/plugins/auth-backend-module-okta-provider/CHANGELOG.md b/plugins/auth-backend-module-okta-provider/CHANGELOG.md index afeb13cdff..47bcb2f140 100644 --- a/plugins/auth-backend-module-okta-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-okta-provider/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-auth-backend-module-okta-provider +## 0.2.10 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## 0.2.10-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + ## 0.2.10-next.0 ### Patch Changes diff --git a/plugins/auth-backend-module-okta-provider/package.json b/plugins/auth-backend-module-okta-provider/package.json index 048f6410e3..a4342efb03 100644 --- a/plugins/auth-backend-module-okta-provider/package.json +++ b/plugins/auth-backend-module-okta-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-okta-provider", - "version": "0.2.10-next.0", + "version": "0.2.10", "description": "The okta-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-onelogin-provider/CHANGELOG.md b/plugins/auth-backend-module-onelogin-provider/CHANGELOG.md index 2a201b6a23..9ad81ae8c4 100644 --- a/plugins/auth-backend-module-onelogin-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-onelogin-provider/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-auth-backend-module-onelogin-provider +## 0.3.10 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## 0.3.10-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + ## 0.3.10-next.0 ### Patch Changes diff --git a/plugins/auth-backend-module-onelogin-provider/package.json b/plugins/auth-backend-module-onelogin-provider/package.json index ada908ed07..aadfb3f273 100644 --- a/plugins/auth-backend-module-onelogin-provider/package.json +++ b/plugins/auth-backend-module-onelogin-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-onelogin-provider", - "version": "0.3.10-next.0", + "version": "0.3.10", "description": "The onelogin-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-openshift-provider/CHANGELOG.md b/plugins/auth-backend-module-openshift-provider/CHANGELOG.md index 88fd02d73e..9cf3f67cd9 100644 --- a/plugins/auth-backend-module-openshift-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-openshift-provider/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-auth-backend-module-openshift-provider +## 0.1.3 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## 0.1.3-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/types@1.2.2 + ## 0.1.3-next.0 ### Patch Changes diff --git a/plugins/auth-backend-module-openshift-provider/package.json b/plugins/auth-backend-module-openshift-provider/package.json index 1c1d23639b..94c21f1718 100644 --- a/plugins/auth-backend-module-openshift-provider/package.json +++ b/plugins/auth-backend-module-openshift-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-openshift-provider", - "version": "0.1.3-next.0", + "version": "0.1.3", "description": "The OpenShift backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-pinniped-provider/CHANGELOG.md b/plugins/auth-backend-module-pinniped-provider/CHANGELOG.md index 86429f1b56..5da6e92225 100644 --- a/plugins/auth-backend-module-pinniped-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-pinniped-provider/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-auth-backend-module-pinniped-provider +## 0.3.10 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## 0.3.10-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/types@1.2.2 + ## 0.3.10-next.0 ### Patch Changes diff --git a/plugins/auth-backend-module-pinniped-provider/package.json b/plugins/auth-backend-module-pinniped-provider/package.json index a855298b92..ba1e04ff76 100644 --- a/plugins/auth-backend-module-pinniped-provider/package.json +++ b/plugins/auth-backend-module-pinniped-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-pinniped-provider", - "version": "0.3.10-next.0", + "version": "0.3.10", "description": "The pinniped-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend-module-vmware-cloud-provider/CHANGELOG.md b/plugins/auth-backend-module-vmware-cloud-provider/CHANGELOG.md index 2535bd1e87..431d709b37 100644 --- a/plugins/auth-backend-module-vmware-cloud-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-vmware-cloud-provider/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-auth-backend-module-vmware-cloud-provider +## 0.5.10 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## 0.5.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + ## 0.5.10-next.0 ### Patch Changes diff --git a/plugins/auth-backend-module-vmware-cloud-provider/package.json b/plugins/auth-backend-module-vmware-cloud-provider/package.json index 36dc189e5a..0445438588 100644 --- a/plugins/auth-backend-module-vmware-cloud-provider/package.json +++ b/plugins/auth-backend-module-vmware-cloud-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-vmware-cloud-provider", - "version": "0.5.10-next.0", + "version": "0.5.10", "description": "The vmware-cloud-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/auth-backend/CHANGELOG.md b/plugins/auth-backend/CHANGELOG.md index 04752f4432..7eaef6e066 100644 --- a/plugins/auth-backend/CHANGELOG.md +++ b/plugins/auth-backend/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-auth-backend +## 0.25.7 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## 0.25.7-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-node@1.20.1-next.1 + ## 0.25.7-next.0 ### Patch Changes diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index c556f93de1..9db17b1a93 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend", - "version": "0.25.7-next.0", + "version": "0.25.7", "description": "A Backstage backend plugin that handles authentication", "backstage": { "role": "backend-plugin", diff --git a/plugins/auth-node/CHANGELOG.md b/plugins/auth-node/CHANGELOG.md index 7cf9a43e21..4ad613457b 100644 --- a/plugins/auth-node/CHANGELOG.md +++ b/plugins/auth-node/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-auth-node +## 0.6.10 + +### Patch Changes + +- 2389358: remove leading dot in auth cookie cleanup call +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- b35f8b2: Fixed chunked cookie replacing edge case in OAuthCookieManager class where some of the old chunks would not get removed if new chunked cookie would have fewer chunks. +- e9dd634: fix flawed cookie removal logic with chunked tokens +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + +## 0.6.10-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- e9dd634: fix flawed cookie removal logic with chunked tokens +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + ## 0.6.10-next.0 ### Patch Changes diff --git a/plugins/auth-node/package.json b/plugins/auth-node/package.json index a1154b7bbc..3e095caa91 100644 --- a/plugins/auth-node/package.json +++ b/plugins/auth-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-node", - "version": "0.6.10-next.0", + "version": "0.6.10", "backstage": { "role": "node-library", "pluginId": "auth", diff --git a/plugins/auth-node/src/oauth/OAuthCookieManager.ts b/plugins/auth-node/src/oauth/OAuthCookieManager.ts index afbedd4dba..fc376eae67 100644 --- a/plugins/auth-node/src/oauth/OAuthCookieManager.ts +++ b/plugins/auth-node/src/oauth/OAuthCookieManager.ts @@ -145,128 +145,154 @@ export class OAuthCookieManager { maxAge: number, origin?: string, pathSuffix: string = '', - ): Response { + ): void { const options = { maxAge, ...this.getConfig(origin, pathSuffix), }; const req = res.req; - let output = res; - const chunkedFormatExists = OAuthCookieManager.chunkedCookieExists( + const newCookieShouldBeChunked = val.length > MAX_COOKIE_SIZE_CHARACTERS; + const existingChunkCount = OAuthCookieManager.countExistingCookieChunks( req, name, ); + const chunkedFormatExists = existingChunkCount > 0; // If using the default cookieConfigurer, delete old cookie with domain // explicitly set to the callbackUrl's domain (legacy behavior) if (this.cookieConfigurer === defaultCookieConfigurer) { - const { hostname: domain } = new URL(this.options.callbackUrl); - output = output.cookie(name, '', { - ...this.getRemoveCookieOptions(), - domain: domain, - }); - - if (chunkedFormatExists) { - for (let chunkNumber = 0; ; chunkNumber++) { - const key = OAuthCookieManager.getCookieChunkName(name, chunkNumber); - const exists = !!req.cookies[key]; - if (!exists) { - break; - } - output = output.cookie(key, '', { - ...this.getRemoveCookieOptions(), - domain: domain, - }); - } - } - } - - if (val.length > MAX_COOKIE_SIZE_CHARACTERS) { - const nonChunkedFormatExists = !!req.cookies[name]; - if (nonChunkedFormatExists) { - output = output.cookie(name, '', this.getRemoveCookieOptions()); - } - - const chunked = this.splitCookieToChunks(val, MAX_COOKIE_SIZE_CHARACTERS); - chunked.forEach((value, chunkNumber) => { - output = output.cookie( - OAuthCookieManager.getCookieChunkName(name, chunkNumber), - value, - options, - ); - }); - return output; + this.removeLegacyCookieWithDomain(res, name, existingChunkCount); } if (chunkedFormatExists) { - for (let chunkNumber = 0; ; chunkNumber++) { - const key = OAuthCookieManager.getCookieChunkName(name, chunkNumber); - const exists = !!req.cookies[key]; - if (!exists) { - break; - } - output = output.cookie(key, '', this.getRemoveCookieOptions()); - } + this.removeChunkedCookie(res, name, existingChunkCount); } - return output.cookie(name, val, options); + if (newCookieShouldBeChunked) { + this.setChunkedCookie(req, res, name, val, options); + } else { + res.cookie(name, val, options); + } + } + + private removeLegacyCookieWithDomain( + res: Response, + name: string, + chunkCount: number, + ): void { + const { hostname: domain } = new URL(this.options.callbackUrl); + res.cookie(name, '', { + ...this.getRemoveCookieOptions(), + domain: domain, + }); + + this.removeChunkedCookie(res, name, chunkCount, { domain }); + } + + private setChunkedCookie( + req: Request, + res: Response, + name: string, + val: string, + options: CookieOptions, + ): void { + const nonChunkedFormatExists = !!req.cookies[name]; + if (nonChunkedFormatExists) { + res.cookie(name, '', this.getRemoveCookieOptions()); + } + const chunkedCookieArray = this.splitCookieToChunks( + val, + MAX_COOKIE_SIZE_CHARACTERS, + ); + chunkedCookieArray.forEach((chunkValue, chunkNumber) => { + res.cookie( + OAuthCookieManager.getCookieChunkName(name, chunkNumber), + chunkValue, + options, + ); + }); } private getCookie(req: Request, name: string): string | undefined { - const isChunked = OAuthCookieManager.chunkedCookieExists(req, name); + const existingChunkCount = OAuthCookieManager.countExistingCookieChunks( + req, + name, + ); + const isChunked = existingChunkCount > 0; if (isChunked) { - const chunks: string[] = []; - let chunkNumber = 0; - let chunk = - req.cookies[OAuthCookieManager.getCookieChunkName(name, chunkNumber)]; - while (chunk) { - chunks.push(chunk); - chunkNumber++; - chunk = - req.cookies[OAuthCookieManager.getCookieChunkName(name, chunkNumber)]; - } - return chunks.join(''); + return this.getChunkedCookie(req, name, existingChunkCount); } return req.cookies[name]; } - private removeCookie(res: Response, name: string, origin?: string): Response { - const req = res.req; - const options = this.getRemoveCookieOptions(origin); - const isChunked = OAuthCookieManager.chunkedCookieExists(req, name); - if (isChunked) { - const nonChunkedFormatExists = !!req.cookies[name]; - let output: Response = nonChunkedFormatExists - ? res.cookie(name, '', options) - : res; - for (let chunkNumber = 0; ; chunkNumber++) { - const key = OAuthCookieManager.getCookieChunkName(name, chunkNumber); - const exists = !!req.cookies[key]; - if (!exists) { - break; - } - output = output.cookie(key, '', options); - } - return output; + private getChunkedCookie( + req: Request, + name: string, + chunkCount: number, + ): string | undefined { + const chunkedCookieArray: string[] = []; + for (let chunkNumber = 0; chunkNumber < chunkCount; chunkNumber++) { + const chunk = + req.cookies[OAuthCookieManager.getCookieChunkName(name, chunkNumber)]; + chunkedCookieArray.push(chunk); + } + return chunkedCookieArray.join(''); + } + + private removeCookie(res: Response, name: string, origin?: string): void { + const req = res.req; + const existingChunkCount = OAuthCookieManager.countExistingCookieChunks( + req, + name, + ); + const chunkedFormatExists = existingChunkCount > 0; + const nonChunkedFormatExists = !!req.cookies[name]; + + if (nonChunkedFormatExists) { + res.cookie(name, '', this.getRemoveCookieOptions(origin)); + } + if (chunkedFormatExists) { + this.removeChunkedCookie(res, name, existingChunkCount, { + origin, + }); + } + } + + private removeChunkedCookie( + res: Response, + name: string, + chunkCount: number, + { domain, origin }: { domain?: string; origin?: string } = {}, + ): void { + for (let chunkNumber = 0; chunkNumber < chunkCount; chunkNumber++) { + const key = OAuthCookieManager.getCookieChunkName(name, chunkNumber); + const baseOptions = this.getRemoveCookieOptions(origin); + const options = domain ? { ...baseOptions, domain } : baseOptions; + res.cookie(key, '', options); } - return res.cookie(name, '', options); } private splitCookieToChunks(val: string, chunkSize: number): string[] { const numChunks = Math.ceil(val.length / chunkSize); - const chunks: string[] = Array(numChunks); + const chunkedCookieArray: string[] = Array(numChunks); let offset: number = 0; for (let i = 0; i < numChunks; i++) { - chunks[i] = val.substring(offset, offset + chunkSize); + chunkedCookieArray[i] = val.substring(offset, offset + chunkSize); offset += chunkSize; } - return chunks; + return chunkedCookieArray; } - private static chunkedCookieExists(req: Request, name: string): boolean { - return !!req.cookies[OAuthCookieManager.getCookieChunkName(name, 0)]; + private static countExistingCookieChunks(req: Request, name: string): number { + for (let chunkNumber = 0; ; chunkNumber++) { + const key = OAuthCookieManager.getCookieChunkName(name, chunkNumber); + const exists = !!req.cookies[key]; + if (!exists) { + return chunkNumber; + } + } } private static getCookieChunkName(name: string, chunkIndex: number): string { diff --git a/plugins/auth-node/src/oauth/createOAuthRouteHandlers.test.ts b/plugins/auth-node/src/oauth/createOAuthRouteHandlers.test.ts index df012bcff1..f2cb27dfa9 100644 --- a/plugins/auth-node/src/oauth/createOAuthRouteHandlers.test.ts +++ b/plugins/auth-node/src/oauth/createOAuthRouteHandlers.test.ts @@ -19,7 +19,11 @@ import express from 'express'; import request, { SuperAgentTest } from 'supertest'; import cookieParser from 'cookie-parser'; import PromiseRouter from 'express-promise-router'; -import { AuthProviderRouteHandlers, AuthResolverContext } from '../types'; +import { + AuthProviderRouteHandlers, + AuthResolverContext, + CookieConfigurer, +} from '../types'; import { createOAuthRouteHandlers } from './createOAuthRouteHandlers'; import { OAuthAuthenticator } from './types'; import { encodeOAuthState, OAuthState } from './state'; @@ -53,6 +57,9 @@ const mockSession = { const fiveKilobyteRefreshToken = 'tylmRqYlw3LrrXATyPerWfYMXrF86h3FeI5DECH8lZ6bERd3SsSFaJZ7EVYw0Rr8HMQVqJAurcSDZBtXjry3y9hXGRmugroDiZngNw8ROSPqcWzaNWDbaVuxCGf3jdjccOio7MnbrmMGpKUF8dfx8DhBH9Vogj5qCWpDajxnGpG0HEOcAHmQbsmJ0KHKVIggAtTYIefjvO2I75Us5VI0sId1GYU0E2AsRVEGedu6oexiLV6QgyJHSyKzTTRD7DqZ4ktVLDsjOBUhAAEWbAl0vxhvjSUEt4YYEFshV5T13MhRGGma8QtVC7R1NItwtojj94QGfwnnQEviIuECONwQc6b4ObeQkPn4bgbsWG9PD5UJA9kBycBV8SqBQkKvT5nsrlsnO4E8zBJBtc2Pd14MUh6CzFng3Wee7v5uPQAnyDJT4V7COwY2F2opz2ifau6c6gUT5ybkEKbp945mo2R0mu99C7z99jhUq9RRxgrtSeNQ7o7j4NksnJThZMjxvpi978bG2P2oMWIl59LgsrYyUt2bkjEB5sQ1qwngitAQDy57flLwAyHAwTobQWjGDUumAAOHe9UqjsuPd6qf23nD0b2nn1rCtnGyJ0H6luaTT0Lqet1Eq9XRLHkL52mJN4iPLWKcDrYsK6KqKhIlVkHa4zXRKHnKONOgMqYioC155yncAirYYJQl142MWamHXqW3LsIjrPwPh9xj02TsWMG4hDt2kVb8Rp3qGJTDyDM79NKbIFFSkATIwyQmQB1THo0kAkpu3V7YYoOfDSl4N5TUbPJRSbEug6Xg3dqMjaHrL729xrGsc0iWC8DAKlTzPKnoVcjaYeru6zHIXhJJcs5BIxeA6afUcataOrzTddXdBiCehqtzjS0omXdeiHKv5d73fLeC5luUo1um6eVEidr5fXEApGpSHKsEo7mv1a9xOTCZPCE1lHntIkaG2vTgEc14QmGTXAjnaxuThGROxmm2gX8xM3JD6HYAfTxQpD5Y6fcMyF5joffBjLdFvHyYC66BghXIb4M7oZ0QQNqzMKzNuJ06JYLK4e0Pi2FQHt1XcO38sknlFnQh5S0GPMiGHXStIyDTfZNwPnI7iKH0GtsRZBUPmoG2cgJWSJPTMZOnIaC5AzZ8AClMT58GAa3MiyIhVLAs1hBv4BMu5mbY1QVSZ8UETZTDnXEn6rGIES41zkr1A3FThUhUTzJAwYLaG2nYn5Dtpge5C1B4LGElcVQDLJKKV3e6foYQMHcIzlwySKWSylI2bRjGJtE9594rlB9Yz1eno7KTtxy9IrMoAd13KnOCnrKjL40kGEWwbDScT0zob04qw1uuIcldUiLYLhPD0MtdxqtZTgvKeVTCeFNo23kWRnBvwhLlguGqvPCMfwXFjLldJsei9MElZgRrPgubBb7ZjSSdGT6CKey6TaFPx5jOT7V9v88jfQJMyEoX9jMCvCQZMFZyCMQdGKU40dOaozRqsymNMhPOgvheIhlXfN0MhU6RLJGhUen0QLuRBy2MiK82z1nkKSnlhMB3REmFmAIXrVhXiOalPLDVB9kR3csn5f6bddAcTzDLrv2YH6ZGhmXwILKJ0osKm8e9aIKVWHitr0LXl5zvkDj7U9CIVtktLLRodLTVxlKRS048LmbRBpGafoxXgOlcVfDmQO8LdKbKHWJOEN4oEhxF3zEgPf9rRMWEI0oE9KoOau7R5DVJMB6Bbf6tOxbHlVwPmnXGsEIJFDt7Wb79knZihK1mfLqaOumcAznQZiFdNt5NbBSestUCytXDDJn1fm8IGxXsBQSsEEtklg9phenjmMG38ABmyLhZCDiDEQ4M6VRPseVXpPhNYuija8YePhrB1y1aW1Cab7wglIIbeGj1Z06sJ6i4HGkAXtn2M1HolRLc6oPohihPaYtrKOFCtJarwbCHMtQjaR9GnzVfGoLFKemhY0kOZvAdLmB0g1QUKsmcKtNdpQwVYwciJE9vvIlgMIpeWBrU6cDkdIbQDOM6dvLicO3BZQqBXbSNgLcXsF1JqlD5YgUzdARjxv7tagxjXVJ4DVB31UgXcBWlEmI1gGrbVZUTQ4Kaj609StfQw2XNNdal8eES46C4rqHtTGCtdUjW7QINXaqt1efjNk4WYFS9OTGKL0GcgvF5ERlHuAQh0R2R0rSQLl72ayOZDeausNRBDYyI24pie4gFb2LI1hJjRwVTJej0xllYoPtMgLxmkCnUpPhbpPjIwPYIZfSYE6CoV7oxy4BDSyK6ueE6dUak6hlEZwOnDh3aOTSVioq53vuqk6ofC2kT2ar1PfgH5SGxpXB6RpI5bYiF4NYoDX9zEOKHD7hwVHoLK4UusPJWSNdbIDuIBmGb6p83vnEZukNaY5ocPZTZyM1Ex8dDOFiOiZs4bOgOY0NsJKv8pb4I1lDzSeBqPbytFkSAQrU5pUgK45bSIFlyEG3ef59nPHblCA8GstcMSm3zZETd5yVq1NAmQvAnabHyc10T3Arp8cm9Xe1SPVGMzEP6QjXMkZMRbwn8k9nXXcFNfRe6XjE4EhifwRuAYoUJ5jQEF5yrF1nYwwbsx6nlKtxlkxWljavjxH1aP8w8t50T3THX1hx39aktWddjRSjQJtu1rZcCxBCBx1FxictyrP9y5dhVVMGIup6mJ8vHws8nudLqHaiEEQlGlRGKi6hMcF31S8l1RWG6KJRsbm8x6jvJchk5ekr9Cj2fmCkpVdE2yCianjU7pCLibtfR7HV36uGK2d0DXwbrv0sXPr9M7KGgTLmSjlUJrohDBHshfHPdT5DgIq1boeBBZjxlxNoUxN7veZ80VjFSuNbCxTg9rcZeAT35qgt06oHboySGL1ZwGPs4Ip73tN1AYRlfo3PZBHWCT4V8mF0R9DDyFEdhkZtvjJLTNqroJsUuUAQzggheYufFunJ8lrwJyche4XaJqnKkv2JktuSbLXol2NoNX31493O2F2nnwWbzgff1jh2gDvPiG9o8wvNrXY06Ar47WDF62YipcLuAY50RnPWaVOgC2vV0OmDGMxnu3niKM0rSiyOtwWzc8SbRPkdRzGwqmtmSFfJSLzNdDLFAbGyDel7WzMUtWuXfvqEZwLVco49zrlcnLPAT4OKNvSl6AcZaTulU9sA2xbEK7gKMv7r8HNJLdEze2cgHG6rXUiayefWE3o2V8YjSHyUwV4PmrW8neAv0v5zKnKBsE6QwlYX23NoaPBvSokjStkNbLxLec0ip6Rgy7vJv5AEA7nxbDM53WUz44898OKHrVjN9vqvoKPBQUXf5BHihloJQCnpk03yzcc2h6y3e9rMFPyMyLFI6Hd4jCOuwtOqTJjAJAvcJzP7gKkeAe9N5ObwtjNqkkWPOd1AJccZukWnT1Lu390xfY3eyRjdMutc5OkTo4di2u0AjVH3LtRIRfa0AHVEly3ZvBCCYo9jCZ0CV8s6PlNOJ6SkyZyZzO3VyOUYxfj09D0P8kCaQ8YcyyoeSKPKVlFvxEqALW8nXASnKCv5mvsAyZMGpYRHtoyu4mVyCIrdOjmyGIK462aO6KaGC6lfWkKisQhLmSK2PmrPeimdS5ViOHllBfwexF5AsmNi6LYrjS00uPTki9K06h6yuppMVV8ykV6HIZoLABicTm5NofudhYrqV5hWstXxunHAk2cNq5Is1mFSNU4eedYbqu2c3y8iD3QzLWO6FmxwWFu3XUK8upSJ2cK34uUl8kX1uRsWSNEMIMOils8HZwHtxZ9fZ09sT2fRJKAIKxx57h0leLsjciNT5iTrMHgsNTlpa5I1QDSbEqtlFhDvh3TYmAYBYUENhcVBZmVK62XhTPpzgmEIQX4dlZJbz9g6I85jjfJILKLsEpmErtbzglmQpyQNw2EQFzYIWu25tv2dTDoDRP7uDV4KDKl5pXKRwu5z4UQI4sXLPACK78x6EoEyVUFnBktvnT7mQe5bqAlJ7dhqUEbzC3AJIgVosnRplZqXInSlNdpTFOasW3YyQmQtDB4183vKzCe4UMdKnHkRAoA127iSIUvKe5w66Cv8cQU38AFyWp5eedMNu9NlbqepUEaYSTmas5odjQUJ23D35QCuO67zFILoDKqWYv7jVKXMIVZUnyvspAWbtUFYDij5SmP2QQCgCpExeDtmoVPdjusL1QqQjukGVc9nXHwjhZ7KwrtrC5XMeKgl9EBvNjRum0sn4B7MLhuqJPqreoTLE2unGcI34mKbWRbyHjSq5xi8uZy72MuDCXyUU4GmZrXNqMG7QAw4wAvMKI31G0uHJEaOSV5II9XGAuYSGTuUuO4y31NTQBPpa2O0JFfnFJgYveVoWL3cCcjJivvEWezutrJ3eObOFbV4ACiZ1uXwJFlI484ILeWSNkS3jaSgfIYvBK9SMVZwg6IuFtjX6D855I4U4XHMqKWla3IcaKvIKwYFlrOWPq81lflKMPLQvJnrEiUi67jZJZYF0rMKtrv2ayFEfFBDtG58hA9uIkCbvHAQOBeWpzuTNUdtZoNdAuLqxddjpxZr4moFtk1CjdQihJNQLPeZR0ZrQYVBUPMyFIV639RykPOPyhxFMSKQNo9xjNCuxnoZWBbtqHHXtFZdUBq7qkb0GzfiADZ7LaRtj9MNOLLej35Wy0L0xPu5Hy5v9N0Jslj65YZJvC7N8uMYuIR6rMuh2MhuthHOlxLLbzcBy7gicP5aFofdt4fkOBgitm8CCRdm0f9DQpETZ5hEGmkI4V59HRs2Up4CG2ajOFIZwRmbvs3B8M5NZmwf1mmek0j7qfjkOhpsp7RHMqUztEYGd1RX3S6vaHDSFEouqPiU07CjNFDV1f8x94tUq8ldicDtQN1DbR5oBTvdmQZsgG8K6oU70IKNhwX4idMFNaTcQ0ZsfJk1rQLh6cIoksmrbm6tYu97HQhVsDmavCs5CnkN2mZDEEj9HfK6O53ck273X3jRo01lFfT65KcUSH71zr3KkLPzxBbhhCRmdpXQSfyHwbN7QbKWi6NkU8G7xb8oRFFsR'; +const eightAndAHalfKilobyteRefreshToken = + 'Ad62a2Bfa5cdCdE489CaF47BDBaF9fbd8CCB6b866Bfc04bB2f8ec7D19ddc7d3189e5249e231cAd567745d4Dc83Be5ADd5BdDdC3cdDa8Cbfe2B2f2Cb01876eadF0A444eA420FEfb5EaFD918A9BbfabD8eaa512FdE7F3fC03bA134d99ebb43fe58eE8C7DaA587a563eac5B75E4bc03E31BcD9dB5DABa0a24e7A6B44C0C585Fc2dAA1dCc5ba110BBeeF7404dE5a0e416A86e23aFADd9efA19faabC74DfdbeCe70E396E054fe2dA1dcCddf5f6f36d1dEF8371FD31BbCA9D1e23a6deCfC43Db00750a2feE0fc7ff6dBdeBaC1557ccA546E8B0B2E6860cfdDC96bBf2356Adff7CFCB1AACC183Fc3DE8bEb0dcFb22D19f44B9f4a6fC0AbE9BCa64e31baaD85aEdE42C1E3b4Cd7F8FEEDDda1dC25C50E93353Df12dCACCA85cD7E6Fb99cbAB4Fb59EDAc3De414ffdC1AbBa3AA06Cd11e9c6eAA1Eb6B1dACa1BE7afd34234Ae6B1Fd2e2Aeb7e0C74cbB3F6fFc39ec6Dd805ddA1433cDfD4bCBB8b19Aa6eB2d19eDE0e57E668302b9E700a4f170967E38F0C8c664AcFbAE6f98eAB5e3EC96AcFcf862Ae90843ffdeEBB89DE2933e55a4bCEB45E07aB1AeB2e8dE4e70e7d4aDB8B3020fC48d0FD4A2A03c6Cd97cbc6A169e13b7AE73A37F25082B4aBe19EB050F0768e2Db7D3514BCA067B79687d03260bd0A4bfFe02cF38Fd31bC09D52fccFAD1D73E51BE55f11BECfFBA6F988fEE16004Be54AD6CC87741DaA40Db1f600fEffC0fa17b77F85e883E6F9BE8e92dA6C862C28DBf128de0A8d307Ad6b1ddd4a9493ee1F8731aBd8Da2f0e85Af89DEC18678bd7ffAA75FA5a79f4cF5A0AAb4f3aD1Df7E2BBDD24Dd3BB12f26cA5f0359a9462f5f5e32EBCA7346BF171ba4F1E2af7f3Ee8B3C8C776B4f0D0622EeBDdBa9Cf9314a85c9F2952aaf25bB2B79A2418ACa6f3bbA76eFB99FA0eC8e30F4e7b5853dfB8f6cdAeEb337dbeD2392e95BECF0Aef66fDbeb0803Bc950EEfed4Ff9b865C80bBBdb074facCE5614E8CC6DF0033cF223c2D5dC60Bd6Bc30141dc5120B8D5D429D4e07cAdfBD67BfdAEFEce8D32C15BA9CaDC1dCCDbf2D59CB370B57cDCa083cC9fEabc8B607c74E167cc1AAE121c6265Fee7b39eDFE10d31E8d59ad4e266a176010AC505BEd8ca057Eb224cf57DA4dfb98fd10A3Ee64F6950Ac54dbD3ffcbB35EfC84BEA9cbCa49872eEc9dAb29161d7b80475C42226914B5FaFCecC023c1AecEa9F89Da95bA4EF2Df2c3Daf14cBdBb9533E07E2E6141e76d1558dF33aeFbfe572fcAd33d3cFCC055bDDd8D8d8f1dCAe6Cff2aCCAfe653b7e845ae459563D0da4E995D35559200EF6FaDbDA59a6BBD323cE8E370fC3996Ed9ebcef1dCeABb067c2c9E96adFC22F058bDEb00bc037549CBCEAF3e6D3b0bB914Aa8CB00a4a97D34cc6D15Eecb295B0a26bD83109EF2af3C82AF55f146ffB26Ebe727eD86dDEB1BF7b714Bb0a58Ad152daAaDC7F5dAEDfAA109d6fCe2847D3b32B41E8c29DAC6499bDA10F8A7a5c3E0b2a1d0f2DE2c3e88de4DFDF85B4AD4Ddae8e8D6dF5bF2affd8dFc2185A92E81E9CEFB0cd71Bf5Ac4C09AEe012eFC79B5dFf447b9AAAFadA871AEac9be09cDa26E1c56F54DD8b8Afac765Fc452c0e11B45daC6ec766B80002C544E4e6342b0B445CE1AfEC0FE8E9d7DE5EF5Ec4921515Ddb8Ee7BEbd68d7065154252E75d922A4b8E4d0AaEcc6Dc3db498E9CfF41bb121B69Ebb774B3cf998316C80Fe73F7d688bcDec894BD3adf5c5AA6A36044C5B01D2dCCcc23BF21F91cd95E55ca1aDaA770AE0b65fE67aA95d44D0BBD3FFDa20bc6EdFcC7e2ef5B46225EFF5c767BdCE8C666Cdcae2aCf9ADb7CD3C10b59be627AbE5B0FDEA16dD9C4727FbECF6bEcAb1b8E1f5716eDEbEaf4E550B8c7CAfDd0C0BE15b6D4bBE3261f9c657aB885B8862C74ED9af0FD725CBCBd7ded2B0d6fb8eEdc802BB1EC2c7609399844a2DCaDC0DF2a0ada1fa91E7a4FFeee6C7AEB3A42DCb85eCc3fe6b31B8D857225a43C49CDBAcB9E855CF9C3ecC05cc41FCCdc9c6b10aa201D0471658aaDBB2077abc0516ee7911F8e1A435eEDBf50e0C12b5AB3e40A4DC2aD61Cdefd6CDd2d16dC9c0d5eE5C2573A6AfceB43d9E6f9e3C7BdAa5CbD2FFcB1AcFAdf52B6EC5cc5B0AC36c2c932124dc8C43cd6867fBfAc1F4DFF957E0f8F09Ea0e4C60faccc4D4E84bC0F0163aD1e2E6977ff83FAaebDd2cc1Fa8BCa821B29f34F242E3FdAb05Bde16a0C46af8CeeAC2EaC00Cf81C112e6Ee0b79b9f5Af9eD0acCc330794aeDf8aa3551C35063BF2D108E4a190cDE9055a3eFB08CFCCe7750eCec6eD4BF2dFDbec7b3A9Bb6cDa71eAb0De2CCA3F6bACFF4ce9304b7B5EAd78a5DfDef6cDbd2df49f0F806ECd85Dab8B1B9B76C2AA0d50baBCAd9db11761f572feF3D50CEFAb6Bf3e38Af8EED4cafe43E47BD68dB67fEfaDC7b3FF2eF5C285DF0850bE8b17B2AfDCDa0923b4BF1f0E02a279B0bc87c5d2Ca60ADc1ccccE07f58BeDC8a31bC9F25bF3D7C6fA4be472cfA4B1F0Ffd37d0EcACAa1Cf1dA07Ee8aE5AB9f88E54db4b6be0cEb3aBcb0DdEf5394a40d25e5138aeBBE1f3b191eCcBFcCC949AAd584BFe2Fb932797E6ABBCaB8BEBB96daBD097fedA5fE1dfce3F0E4BEc518aB25FfCBBb0aA007ffafb04d3BbCC5e0347AcBbc3006C05C41CBeeBae17A149b15Bc1533aeB44017cc5BCDfc6c5d2AcCEc4c17A44e53D42dc68C6f93eFa7D1d2f9f2D4e4Dddd90dCa0f15dD1aa40D7eBff9b0Cb7d7Da33FD2cb0d5Af8DbcbaE47Fb86Abf8bE20A7FeBBD4a390abB6abfD8C8D5E41e2BEd8E3eBFD2d1B8d41d605AdEF2BE63E22C09A55fBbAbfbeb8fed339119bf34a8d0BA3e912702b9c0DF7b476FC538eD06571EF2dE208beCDA8134BeEcb1F794BeaaDCd5619fd05EABAA82d58cB0cC9Cc3adA0D5fcF915b6E9dA9517caB500aDEAc8aAB6ad26b3E2F8Bf7cd2004f7cF74cA4b2a495CDed2a7a5CE42b6DC8e95326a7637f21EbFCbEcE8860EfDb31Df9aaF6F133674723f716a600B1c01DC98c7aA4fBe9cb81E7C50F3Bdc966D8BDa1AFcd4EBfB922f2eba045B3726d3Cec02Bdd606ae43aaeaa0EA945D4ec95d9E5E1AcF92aa75F4db4AC453Ccc51ceAdBD7b0614BfeCC303AADc40bCfDDfC76bfafFdbcD47D4B729EEF1CCED07C3dF85EEfC2eCcbbB45F8D5f1D09e9A1964fEF402E29AE024dEEeAeDEfF377E7b2ee2F621165dEB3CE9f4471DEeb396Dc3B508Bb0C2A51c4CC4Ba5Ca1aa9ca7b401D6C0421EDB83CF03EA16bA24ceE3FC4e7Ad4BFc7dAbe16e4C2A51F4e2cAeb7bC7287684268ea7FAae360A1A8aF5BFED450db3D66363284eD57B2f9D25A5c4FE424a7feE764eaA0e47F96b77Af2bd725c1c8DbE5A7FF2e0c7cE7F9eE0FCf7bdF00543a9ED1C485CDC2e82386F440D04FEa6380B9bbE48C605bF0fbDe0dc2cEAe35C2BFB84dF62185B8e6BABBE89DcCF1b1Cedf5aDadeBdd3Bd66cc76aC6badb2F1ec27C411ccd3cCD823feE8A8F9aE8C0e1cc0fE6484fBd2c58C77Fbcbdc662C7EEeb684dAaeE0489C40d8A91d6DCec15A3e506783C35acBD0Dad364AeeC295d7eD1BecdB2d1d9d1352dE4F7f52B50e272ab9E57e8AFbCC54fEEbB640F5FD37b18f6a46D70f0cBCB98aBAdd6EfcF06f5f5Aa6D61b3FD4c1aeB46Be0Da0Dfcaf5c45e2FDF46C43aFcCb952Be929adaFcFeECbCDB6Edc61472DBC37Eeeff5a5B64Bd1Fee6B5e6861EcBfff3d6103a7E3e361EC08Ecb4d81c0FdefAdA9d861c12e7aD85678a23E5E94F3dC9677d4B82Dee5A24dDbebF20B880c25C6955dCCC276ff9C3505a85bBE6aB08E6EFb3C35DC1fcFDC8F86E4bE7C1F0fBF8b1B8594F122fFAd7c6CDe8fba97af1697Ae3e5cFc485B8E0Ae66dbD485afceBAAe550cdc9E4B4CbEbC51c85D6BeCb83BF51f41DDeCAbe4bB75209eA0EaeEe6010Da909b5CBd1D1CBaE7b579F48cd5Af0d2F81c1E8ADcaA4DaCA01Ea206fee4ECBc8fddaa505b41c114EABF753F5aD02B25Be96bEa1dfF5e04EddEcEbA8881EfCe9AB957e0366DdCD9E32ecBdFC1B0Ab6f1effdcb0b1A3d2f7eFEf59EB2bddC130305d4bAe6f627e1087B3Ef5Cdd1f2A75Eadc6B4d79A5b6d55fEA7ea30d3cDd74D74F3bD2aa99b5ab3FC83Acbb9ee0fBa05D4d23DACeBb16cda8A2bF7Ca4D85eee1BAc9D06Cd899861bB5e2e4B9c30E1C887d19DbF81cFe8Ae9b777249f542faAFE3b3bd49Ba5295afbd927A475C0C3B81C1ee6eEB8c00451CFBcCFfF7Fc8aD0b7251c00D507cEfe86BeEeFe5FBded0FBe30CC447DFaB930c04c4460e9f9cbf1BBF2eBFdF06D3AAed2af2BEDBA0f296AEfAf90571F9B63e0876fFADfDf61408B6dedeBfE2dE7a8ee750Ef78B1289b6fCdfdaC58393e373a5dA35d2b149c9FF5a1fA9DFeCc37c678Ce657A172D5d990BbbFDa089288dCa5F89f6CeF7cf6b1EB2609BBD65e6fFfa815Cc59abcE387ead000Af1B1C1cC87faB990D1b9AfcEfDc3D68cCCb9b7475803829dDebA48e92df26AC70027CcEfB6F6FDd1DA25DFB9dA0aE50398998E7EbEEaE11BB68a2E03c5f8306eaca1aF15CeBCB05a6FDb8E3BdAAeFfeC21Db12762dDBABd3eDf12A438B3C37B51cCaCD1Eda73dFCCeF06BCFbECE21F95e2Ae1d0F161dEec60a17D01d1Dc425b85aCD0adeCCBdddd310581aa0eF48FfF8a6A727E95BADefF6Cd011Df1c993DB5aE2ec8c3dD42cD704a5e0AC8bCbae34F245e7ABfba828efa3adFFefb33fCa32ad0b2Bd7C4Ae56C3d932E7A1a24bE87Bd235067A73CcBC5A8Cd44B0Fa5131dacCDEA7454aAb7c0Dfb006B6EbFAd3dD1EAEee79c9Da23FA02D88CD8333BE964E7D2eBbd1AAAE06E67463CCb6eceA604Cdd2A16d834599c86914Ea9b063243C4Ebe8E6aa677fdE2b67A6eE4Cfe1801273137ec777DEfc84D4B3d0e96dFF1f7CCaB0CFD307Ba1fC16b9C4f4d1fee0ee0f05BB1102eEeA5E49e7f339BE6d9335Bf2F28d57f194D9facA9c5af5B08B08D7530c7DDe99D0Ae0D8dD5d0c13B77fDf1E3Bc0aA8e71C32EAD5AaD7Bed538F26d4deaA3A67C667201C5Fd62A5FaeDde62E6DC78E62bEeaBFaa030cFDa4E86f5B3C48bBE7bB4Be5528D3D0fd69BCCE1D8B6d04Ee6B9a1B5c49572B21FFFf1bDf06cd98fa9ED5fd9Dc3B04bD4530B8CBD5d0106799E4CBCE64c65EFcfb4f84Ba0ced14BECdcd4bb33CA38B4eea4bF7e665Eda4a8ADfBfae5C45b2B91e2C1eCD0CcBC85275d4Ca8318638eB77Eab97845c40Ccd34f7ef99385Ce275B30013f7BfC2c088a2F332DAF6Ca2CFB21d5f8EAF177B519cAF56ca42a9DAfadBAECb5E16Bf671BDB2BBb15c8eb1F4Cb9dfDbfbcFcFAEABAD3aeeCF8e84BbEECf3dDf0f7FdBCF44aa1A4ac7bFac026B8Ab6C0004a1dCc6bc2b5eb8fA7cEEe9cEeAce5d287BCE0E5f3bBffdFaED134286794D704b32DD36cF2FF80dd39FB09cAbCF1FaF07a2aFB0EA7FeA464b90f77090B846Fad58Ca0fB83eA3d6C4dDBCFd17b8c5EFCc7a6e1efDaaE8B4Ecae65C89BC80Df9bC844cE9aDCcFdaE2be0f0Bc6AdBDB6E814d2050febEB3BaFCfBCCADF749BC2Cde2BeC0e7E6e14afa92Fe5fd51A8Ef62aC53FAE304B0f4317Ab5db11fD13ecAcd8995E6F87Fe4Ff5FF89e4B7b44A754f52a7E4fDDCdfDDefEE4aD7AcAacDCa17fd3a2b43D4bc74B3Cad0aeee8eDBa25D56e3Ba0C5cd8B8E2a2c0B8f951Fd7AFC75edEAee0c28bf3cEBc3af7C60ca147fC9cF0886B066e263f36CA5B5BB36aB82f0f0A58FE3d67f1a9fc24270e6170ac34E6eE5c1bc64B1B5f416afbb8E8edD2cFA9fdcAF7Be904EBaA1abF8b0c2D5cc176C5866fcbCECa5342d7439Cc5E859dBe6a18e9c58EC2e9a5bc20a79D3E3CF073aD4c4F12409E787fFA0Dd1C6d3f01b3CeaDC7F5Cc9be3415f0DFFD5F2E2Fb0dBA6843CCB1aECbF1480E8fCFc16e2cEDB8B8e292dFFeF1bBc6F9C7DD4b873DBbbD528d0fB1E4D02ba3EDe9f1c13b4DEE0FC8BAAdc5cAB40AF2EC4eFDAAfD31104bC04CEFFCbEAae6aA1C91FAccAEed7B3dE6FF226Db01f62E239fba8BD5aE9B7C9a4DeeF746ec2F9580368FB1DDcF785e410aec4a70005a609CBBebf42f714b3c59a76cB06c3c86Ca3dfbB5EcAC'; + const baseConfig = { authenticator: mockAuthenticator, appUrl: 'http://127.0.0.1', @@ -116,6 +123,30 @@ function getRefreshTokenCookie(test: SuperAgentTest, chunkNumber?: number) { }); } +function confirmRefreshTokenCookieDeletion( + res: request.Response, + { + domain = false, + path = '/my-provider', + chunkNumber, + }: { domain?: string | false; path?: string; chunkNumber?: number } = {}, +): boolean { + const setCookieHeaders = [res.get('Set-Cookie') ?? []].flat(); + const cookieName = + chunkNumber !== undefined + ? `my-provider-refresh-token-${chunkNumber}` + : 'my-provider-refresh-token'; + return setCookieHeaders.some( + cookie => + cookie.includes(`${cookieName}=;`) && + cookie.includes('Max-Age=0') && + (domain + ? cookie.includes(`Domain=${domain}`) + : !cookie.includes('Domain=')) && + (path ? cookie.includes(`Path=${path}`) : true), + ); +} + function getGrantedScopesCookie(test: SuperAgentTest) { return test.jar.getCookie('my-provider-granted-scope', { domain: '127.0.0.1', @@ -125,6 +156,12 @@ function getGrantedScopesCookie(test: SuperAgentTest) { }); } +function extractTokenStringSlice(tokenString: string, index: number): string { + const chunkSize = 4000; + const start = index * chunkSize; + return tokenString.slice(start, start + chunkSize); +} + describe('createOAuthRouteHandlers', () => { afterEach(() => jest.clearAllMocks()); @@ -329,14 +366,137 @@ describe('createOAuthRouteHandlers', () => { }); expect(getRefreshTokenCookie(agent, 0).value).toBe( - fiveKilobyteRefreshToken.slice(0, 4000), + extractTokenStringSlice(fiveKilobyteRefreshToken, 0), ); expect(getRefreshTokenCookie(agent, 1).value).toBe( - fiveKilobyteRefreshToken.slice(4000), + extractTokenStringSlice(fiveKilobyteRefreshToken, 1), ); expect(getGrantedScopesCookie(agent)).toBeUndefined(); }); + it('should replace and clean up chunked token bigger than 4KB', async () => { + // Create and use a custom cookie configurer to make sure to circumvent legacy cookie removal mechanism logic + const customCookieConfigurer: CookieConfigurer = ({ + callbackUrl, + providerId, + }) => { + const { pathname } = new URL(callbackUrl); + const path = pathname.endsWith(`${providerId}/handler/frame`) + ? pathname.slice(0, -'/handler/frame'.length) + : `${pathname}/${providerId}`; + return { + path: path, + secure: false, + sameSite: 'lax', + }; + }; + const agent = request.agent( + wrapInApp( + createOAuthRouteHandlers({ + ...baseConfig, + cookieConfigurer: customCookieConfigurer, + }), + ), + ); + + agent.jar.setCookie( + 'my-provider-nonce=123', + '127.0.0.1', + '/my-provider/handler', + ); + + mockAuthenticator.authenticate.mockResolvedValue({ + fullProfile: { id: 'id' } as PassportProfile, + session: { + ...mockSession, + refreshToken: fiveKilobyteRefreshToken, + }, + }); + + // Simulate 8.5KB token (3-chunks) that should be replaced with 5KB token (2-chunks) + agent.jar.setCookie( + `my-provider-refresh-token-0=${extractTokenStringSlice( + eightAndAHalfKilobyteRefreshToken, + 0, + )}`, + '127.0.0.1', + '/my-provider', + ); + agent.jar.setCookie( + `my-provider-refresh-token-1=${extractTokenStringSlice( + eightAndAHalfKilobyteRefreshToken, + 1, + )}`, + '127.0.0.1', + '/my-provider', + ); + agent.jar.setCookie( + `my-provider-refresh-token-2=${extractTokenStringSlice( + eightAndAHalfKilobyteRefreshToken, + 2, + )}`, + '127.0.0.1', + '/my-provider', + ); + + const res = await agent.get('/my-provider/handler/frame').query({ + state: encodeOAuthState({ + env: 'development', + nonce: '123', + } as OAuthState), + }); + + expect(mockAuthenticator.authenticate).toHaveBeenCalledWith( + { req: expect.anything() }, + { ctx: 'authenticator' }, + ); + + expect(res.status).toBe(200); + expect(parseWebMessageResponse(res.text).response).toEqual({ + type: 'authorization_response', + response: { + profile: {}, + providerInfo: { + accessToken: 'access-token', + expiresInSeconds: 3, + idToken: 'id-token', + scope: 'my-scope', + }, + }, + }); + + expect(getRefreshTokenCookie(agent, 0).value).toBe( + extractTokenStringSlice(fiveKilobyteRefreshToken, 0), + ); + expect(getRefreshTokenCookie(agent, 1).value).toBe( + extractTokenStringSlice(fiveKilobyteRefreshToken, 1), + ); + // verify that the old chunked cookie 2 is cleaned up + expect(getRefreshTokenCookie(agent, 2)).toBeUndefined(); + + // verify that deletion was ordered for old chunked cookies + expect( + confirmRefreshTokenCookieDeletion(res, { + chunkNumber: 0, + domain: false, + }), + ).toBe(true); + expect( + confirmRefreshTokenCookieDeletion(res, { + chunkNumber: 1, + domain: false, + }), + ).toBe(true); + expect( + confirmRefreshTokenCookieDeletion(res, { + chunkNumber: 2, + domain: false, + }), + ).toBe(true); + + expect(getGrantedScopesCookie(agent)).toBeUndefined(); + }); + it('should clean up old cookies (non-chunked) with domain attribute during migration', async () => { const agent = request.agent( wrapInApp(createOAuthRouteHandlers(baseConfig)), @@ -367,15 +527,9 @@ describe('createOAuthRouteHandlers', () => { }); expect(res.status).toBe(200); - - const setCookieHeaders = [res.get('Set-Cookie') ?? []].flat(); - const hasDeleteWithDomain = setCookieHeaders.some( - cookie => - cookie.includes('my-provider-refresh-token=;') && - cookie.includes('Max-Age=0') && - cookie.includes('Domain=127.0.0.1'), - ); - expect(hasDeleteWithDomain).toBe(true); + expect( + confirmRefreshTokenCookieDeletion(res, { domain: '127.0.0.1' }), + ).toBe(true); expect(getRefreshTokenCookie(agent).value).toBe('refresh-token'); }); @@ -393,16 +547,19 @@ describe('createOAuthRouteHandlers', () => { // Simulate old chunked cookies with domain attribute (legacy format) agent.jar.setCookie( - `my-provider-refresh-token-0=${fiveKilobyteRefreshToken.slice( + `my-provider-refresh-token-0=${extractTokenStringSlice( + fiveKilobyteRefreshToken, 0, - 4000, - )}; Domain=127.0.0.1`, + )}`, + '127.0.0.1', '/my-provider', ); agent.jar.setCookie( - `my-provider-refresh-token-1=${fiveKilobyteRefreshToken.slice( - 4000, - )}; Domain=127.0.0.1`, + `my-provider-refresh-token-1=${extractTokenStringSlice( + fiveKilobyteRefreshToken, + 1, + )}`, + '127.0.0.1', '/my-provider', ); @@ -423,28 +580,24 @@ describe('createOAuthRouteHandlers', () => { expect(res.status).toBe(200); - const setCookieHeaders = [res.get('Set-Cookie') ?? []].flat(); - const hasChunk0DeleteWithDomain = setCookieHeaders.some( - cookie => - cookie.includes('my-provider-refresh-token-0=') && - cookie.includes('Max-Age=0') && - cookie.includes('Domain=127.0.0.1'), - ); - const hasChunk1DeleteWithDomain = setCookieHeaders.some( - cookie => - cookie.includes('my-provider-refresh-token-1=') && - cookie.includes('Max-Age=0') && - cookie.includes('Domain=127.0.0.1'), - ); - - expect(hasChunk0DeleteWithDomain).toBe(true); - expect(hasChunk1DeleteWithDomain).toBe(true); + expect( + confirmRefreshTokenCookieDeletion(res, { + chunkNumber: 0, + domain: '127.0.0.1', + }), + ).toBe(true); + expect( + confirmRefreshTokenCookieDeletion(res, { + chunkNumber: 1, + domain: '127.0.0.1', + }), + ).toBe(true); expect(getRefreshTokenCookie(agent, 0).value).toBe( - fiveKilobyteRefreshToken.slice(0, 4000), + extractTokenStringSlice(fiveKilobyteRefreshToken, 0), ); expect(getRefreshTokenCookie(agent, 1).value).toBe( - fiveKilobyteRefreshToken.slice(4000), + extractTokenStringSlice(fiveKilobyteRefreshToken, 1), ); }); @@ -460,16 +613,19 @@ describe('createOAuthRouteHandlers', () => { ); agent.jar.setCookie( - `my-provider-refresh-token-0=${fiveKilobyteRefreshToken.slice( + `my-provider-refresh-token-0=${extractTokenStringSlice( + fiveKilobyteRefreshToken, 0, - 4000, )}; Domain=127.0.0.1`, + '127.0.0.1', '/my-provider', ); agent.jar.setCookie( - `my-provider-refresh-token-1=${fiveKilobyteRefreshToken.slice( - 4000, + `my-provider-refresh-token-1=${extractTokenStringSlice( + fiveKilobyteRefreshToken, + 1, )}; Domain=127.0.0.1`, + '127.0.0.1', '/my-provider', ); @@ -487,22 +643,18 @@ describe('createOAuthRouteHandlers', () => { expect(res.status).toBe(200); - const setCookieHeaders = [res.get('Set-Cookie') ?? []].flat(); - const hasChunk0DeleteWithDomain = setCookieHeaders.some( - cookie => - cookie.includes('my-provider-refresh-token-0=;') && - cookie.includes('Max-Age=0') && - cookie.includes('Domain=127.0.0.1'), - ); - const hasChunk1DeleteWithDomain = setCookieHeaders.some( - cookie => - cookie.includes('my-provider-refresh-token-1=;') && - cookie.includes('Max-Age=0') && - cookie.includes('Domain=127.0.0.1'), - ); - - expect(hasChunk0DeleteWithDomain).toBe(true); - expect(hasChunk1DeleteWithDomain).toBe(true); + expect( + confirmRefreshTokenCookieDeletion(res, { + chunkNumber: 0, + domain: false, + }), + ).toBe(true); + expect( + confirmRefreshTokenCookieDeletion(res, { + chunkNumber: 1, + domain: false, + }), + ).toBe(true); expect(getRefreshTokenCookie(agent).value).toBe('refresh-token'); expect(getRefreshTokenCookie(agent, 0)).toBeUndefined(); @@ -804,15 +956,18 @@ describe('createOAuthRouteHandlers', () => { ); agent.jar.setCookie( - `my-provider-refresh-token-0=${fiveKilobyteRefreshToken.slice( + `my-provider-refresh-token-0=${extractTokenStringSlice( + fiveKilobyteRefreshToken, 0, - 4000, )}`, '127.0.0.1', '/my-provider', ); agent.jar.setCookie( - `my-provider-refresh-token-1=${fiveKilobyteRefreshToken.slice(4000)}`, + `my-provider-refresh-token-1=${extractTokenStringSlice( + fiveKilobyteRefreshToken, + 1, + )}`, '127.0.0.1', '/my-provider', ); diff --git a/plugins/auth-react/CHANGELOG.md b/plugins/auth-react/CHANGELOG.md index 6a92a82a99..8d5ee31f64 100644 --- a/plugins/auth-react/CHANGELOG.md +++ b/plugins/auth-react/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-auth-react +## 0.1.22 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + ## 0.1.22-next.0 ### Patch Changes diff --git a/plugins/auth-react/package.json b/plugins/auth-react/package.json index 7348245f87..3a11292642 100644 --- a/plugins/auth-react/package.json +++ b/plugins/auth-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-react", - "version": "0.1.22-next.0", + "version": "0.1.22", "description": "Web library for the auth plugin", "backstage": { "role": "web-library", diff --git a/plugins/auth/CHANGELOG.md b/plugins/auth/CHANGELOG.md index 7c66e1b692..f402cffbd3 100644 --- a/plugins/auth/CHANGELOG.md +++ b/plugins/auth/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-auth +## 0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/theme@0.7.1 + ## 0.1.3-next.0 ### Patch Changes diff --git a/plugins/auth/package.json b/plugins/auth/package.json index 77412a3c05..629d00efa9 100644 --- a/plugins/auth/package.json +++ b/plugins/auth/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth", - "version": "0.1.3-next.0", + "version": "0.1.3", "backstage": { "role": "frontend-plugin", "pluginId": "auth", diff --git a/plugins/bitbucket-cloud-common/CHANGELOG.md b/plugins/bitbucket-cloud-common/CHANGELOG.md index 0f6425b00b..2eb6fd31b6 100644 --- a/plugins/bitbucket-cloud-common/CHANGELOG.md +++ b/plugins/bitbucket-cloud-common/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-bitbucket-cloud-common +## 0.3.5 + +### Patch Changes + +- 37fba1d: Added support for Bitbucket Cloud OAuth. This introduces an alternative authentication method using a workspace OAuth consumer, alongside App Passwords (deprecated) and API tokens. OAuth does not require a bot or service account and avoids token expiry issues. + + **BREAKING CHANGES** + + - **@backstage/integration** (`src/bitbucketCloud/core.ts`) + + - `getBitbucketCloudRequestOptions` now returns a `Promise` and **must** be awaited. + + - **@backstage/plugin-scaffolder-backend-module-bitbucket-cloud** (`src/actions/helpers.ts`) + - `getBitbucketClient` now returns a `Promise` and **must** be awaited. + - `getAuthorizationHeader` now returns a `Promise` and **must** be awaited. + + **OAuth usage example** + + ```yaml + integrations: + bitbucketCloud: + - clientId: client-id + clientSecret: client-secret + ``` + +- Updated dependencies + - @backstage/integration@1.19.0 + ## 0.3.5-next.0 ### Patch Changes diff --git a/plugins/bitbucket-cloud-common/package.json b/plugins/bitbucket-cloud-common/package.json index 354b2ad31c..ac47687ae3 100644 --- a/plugins/bitbucket-cloud-common/package.json +++ b/plugins/bitbucket-cloud-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bitbucket-cloud-common", - "version": "0.3.5-next.0", + "version": "0.3.5", "description": "Common functionalities for bitbucket-cloud plugins", "backstage": { "role": "common-library", diff --git a/plugins/bitbucket-cloud-common/src/BitbucketCloudClient.ts b/plugins/bitbucket-cloud-common/src/BitbucketCloudClient.ts index adbf08cf40..eb40b51b5b 100644 --- a/plugins/bitbucket-cloud-common/src/BitbucketCloudClient.ts +++ b/plugins/bitbucket-cloud-common/src/BitbucketCloudClient.ts @@ -14,7 +14,10 @@ * limitations under the License. */ -import { BitbucketCloudIntegrationConfig } from '@backstage/integration'; +import { + BitbucketCloudIntegrationConfig, + getBitbucketCloudOAuthToken, +} from '@backstage/integration'; import fetch, { Request } from 'cross-fetch'; import { Models } from './models'; import { WithPagination } from './pagination'; @@ -139,22 +142,32 @@ export class BitbucketCloudClient { } private async request(req: Request): Promise { - return fetch(req, { headers: this.getAuthHeaders() }).then( - (response: Response) => { - if (!response.ok) { - throw new Error( - `Unexpected response for ${req.method} ${req.url}. Expected 200 but got ${response.status} - ${response.statusText}`, - ); - } + const headers = await this.getAuthHeaders(); + return fetch(req, { headers }).then((response: Response) => { + if (!response.ok) { + throw new Error( + `Unexpected response for ${req.method} ${req.url}. Expected 200 but got ${response.status} - ${response.statusText}`, + ); + } - return response; - }, - ); + return response; + }); } - private getAuthHeaders(): Record { + private async getAuthHeaders(): Promise> { const headers: Record = {}; + // OAuth authentication (clientId/clientSecret) + if (this.config.clientId && this.config.clientSecret) { + const token = await getBitbucketCloudOAuthToken( + this.config.clientId, + this.config.clientSecret, + ); + headers.Authorization = `Bearer ${token}`; + return headers; + } + + // Basic authentication (username/token or username/appPassword) if ( this.config.username && (this.config.token ?? this.config.appPassword) diff --git a/plugins/catalog-backend-module-aws/CHANGELOG.md b/plugins/catalog-backend-module-aws/CHANGELOG.md index b720e047e8..aae01344ed 100644 --- a/plugins/catalog-backend-module-aws/CHANGELOG.md +++ b/plugins/catalog-backend-module-aws/CHANGELOG.md @@ -1,5 +1,48 @@ # @backstage/plugin-catalog-backend-module-aws +## 0.4.19-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.14.1-next.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/integration@1.19.0 + - @backstage/integration-aws-node@0.1.19 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1 + - @backstage/plugin-kubernetes-common@0.9.9 + +## 0.4.18 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-defaults@0.14.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-kubernetes-common@0.9.9 + - @backstage/plugin-catalog-node@1.20.1 + +## 0.4.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.14.0-next.1 + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/integration-aws-node@0.1.19 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + - @backstage/plugin-kubernetes-common@0.9.9-next.0 + ## 0.4.18-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-aws/package.json b/plugins/catalog-backend-module-aws/package.json index 61ce045f5a..fe0ce05994 100644 --- a/plugins/catalog-backend-module-aws/package.json +++ b/plugins/catalog-backend-module-aws/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-aws", - "version": "0.4.18-next.1", + "version": "0.4.19-next.0", "description": "A Backstage catalog backend module that helps integrate towards AWS", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-azure/CHANGELOG.md b/plugins/catalog-backend-module-azure/CHANGELOG.md index 88e6e91ca1..aa61bd3b04 100644 --- a/plugins/catalog-backend-module-azure/CHANGELOG.md +++ b/plugins/catalog-backend-module-azure/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-catalog-backend-module-azure +## 0.3.12 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## 0.3.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + ## 0.3.12-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-azure/package.json b/plugins/catalog-backend-module-azure/package.json index bea8d358d7..802d80077b 100644 --- a/plugins/catalog-backend-module-azure/package.json +++ b/plugins/catalog-backend-module-azure/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-azure", - "version": "0.3.12-next.0", + "version": "0.3.12", "description": "A Backstage catalog backend module that helps integrate towards Azure", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-backstage-openapi/CHANGELOG.md b/plugins/catalog-backend-module-backstage-openapi/CHANGELOG.md index 001bb8c816..718dde0ce6 100644 --- a/plugins/catalog-backend-module-backstage-openapi/CHANGELOG.md +++ b/plugins/catalog-backend-module-backstage-openapi/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-catalog-backend-module-backstage-openapi +## 0.5.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-openapi-utils@0.6.5-next.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-node@1.20.1 + +## 0.5.9 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-openapi-utils@0.6.4 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## 0.5.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-openapi-utils@0.6.4-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + ## 0.5.9-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-backstage-openapi/package.json b/plugins/catalog-backend-module-backstage-openapi/package.json index 5045026df4..9eb50da0bf 100644 --- a/plugins/catalog-backend-module-backstage-openapi/package.json +++ b/plugins/catalog-backend-module-backstage-openapi/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-backstage-openapi", - "version": "0.5.9-next.0", + "version": "0.5.10-next.0", "backstage": { "role": "backend-plugin-module", "pluginId": "catalog", diff --git a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md index e34fb75316..52b988de1c 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-catalog-backend-module-bitbucket-cloud +## 0.5.6 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/plugin-bitbucket-cloud-common@0.3.5 + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## 0.5.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/plugin-bitbucket-cloud-common@0.3.5-next.0 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + ## 0.5.6-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-cloud/package.json b/plugins/catalog-backend-module-bitbucket-cloud/package.json index 02b677cffb..acc69c594e 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/package.json +++ b/plugins/catalog-backend-module-bitbucket-cloud/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket-cloud", - "version": "0.5.6-next.0", + "version": "0.5.6", "description": "A Backstage catalog backend module that helps integrate towards Bitbucket Cloud", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md index 96c75fb09d..8e3144e659 100644 --- a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-catalog-backend-module-bitbucket-server +## 0.5.6 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## 0.5.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + ## 0.5.6-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-server/package.json b/plugins/catalog-backend-module-bitbucket-server/package.json index c026aaa869..ea4601e9c0 100644 --- a/plugins/catalog-backend-module-bitbucket-server/package.json +++ b/plugins/catalog-backend-module-bitbucket-server/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket-server", - "version": "0.5.6-next.0", + "version": "0.5.6", "backstage": { "role": "backend-plugin-module", "pluginId": "catalog", diff --git a/plugins/catalog-backend-module-gcp/CHANGELOG.md b/plugins/catalog-backend-module-gcp/CHANGELOG.md index f660d65434..5102f3266f 100644 --- a/plugins/catalog-backend-module-gcp/CHANGELOG.md +++ b/plugins/catalog-backend-module-gcp/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-catalog-backend-module-gcp +## 0.3.15 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-kubernetes-common@0.9.9 + - @backstage/plugin-catalog-node@1.20.1 + +## 0.3.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/plugin-catalog-node@1.20.1-next.1 + - @backstage/plugin-kubernetes-common@0.9.9-next.0 + ## 0.3.15-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-gcp/package.json b/plugins/catalog-backend-module-gcp/package.json index d50fa3baeb..620c35c84f 100644 --- a/plugins/catalog-backend-module-gcp/package.json +++ b/plugins/catalog-backend-module-gcp/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-gcp", - "version": "0.3.15-next.1", + "version": "0.3.15", "description": "A Backstage catalog backend module that helps integrate towards GCP", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-gcp/src/providers/__snapshots__/GkeEntityProvider.test.ts.snap b/plugins/catalog-backend-module-gcp/src/providers/__snapshots__/GkeEntityProvider.test.ts.snap index c903bcd192..18fd9b58ce 100644 --- a/plugins/catalog-backend-module-gcp/src/providers/__snapshots__/GkeEntityProvider.test.ts.snap +++ b/plugins/catalog-backend-module-gcp/src/providers/__snapshots__/GkeEntityProvider.test.ts.snap @@ -1,4 +1,4 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`GkeEntityProvider should return clusters as Resources 1`] = ` [MockFunction] { diff --git a/plugins/catalog-backend-module-gerrit/CHANGELOG.md b/plugins/catalog-backend-module-gerrit/CHANGELOG.md index d1493a5d34..ff8c27cbab 100644 --- a/plugins/catalog-backend-module-gerrit/CHANGELOG.md +++ b/plugins/catalog-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-catalog-backend-module-gerrit +## 0.3.9 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## 0.3.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + ## 0.3.9-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-gerrit/package.json b/plugins/catalog-backend-module-gerrit/package.json index dbf1929bc8..4a336802e8 100644 --- a/plugins/catalog-backend-module-gerrit/package.json +++ b/plugins/catalog-backend-module-gerrit/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-gerrit", - "version": "0.3.9-next.0", + "version": "0.3.9", "backstage": { "role": "backend-plugin-module", "pluginId": "catalog", diff --git a/plugins/catalog-backend-module-gitea/CHANGELOG.md b/plugins/catalog-backend-module-gitea/CHANGELOG.md index 0e3ec28314..fa4ed4f98e 100644 --- a/plugins/catalog-backend-module-gitea/CHANGELOG.md +++ b/plugins/catalog-backend-module-gitea/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-catalog-backend-module-gitea +## 0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## 0.1.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + ## 0.1.7-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-gitea/package.json b/plugins/catalog-backend-module-gitea/package.json index f4dacc1e06..1077d3d050 100644 --- a/plugins/catalog-backend-module-gitea/package.json +++ b/plugins/catalog-backend-module-gitea/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-gitea", - "version": "0.1.7-next.0", + "version": "0.1.7", "license": "Apache-2.0", "description": "The gitea backend module for the catalog plugin.", "main": "src/index.ts", diff --git a/plugins/catalog-backend-module-github-org/CHANGELOG.md b/plugins/catalog-backend-module-github-org/CHANGELOG.md index bcd7ad1a94..5d084a5159 100644 --- a/plugins/catalog-backend-module-github-org/CHANGELOG.md +++ b/plugins/catalog-backend-module-github-org/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-catalog-backend-module-github-org +## 0.3.17 + +### Patch Changes + +- ed5a7a3: Introduce new configuration option to exclude suspended users from GitHub Enterprise instances. + + When it’s set to true, suspended users won’t be returned when querying the organization users for GitHub Enterprise instances. + Note that this option should be used only against GitHub Enterprise instances, the property does not exist in the github.com GraphQL schema, setting it will cause a schema validation error and the syncing of users will fail. + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18 + - @backstage/plugin-catalog-backend-module-github@0.12.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## 0.3.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/plugin-catalog-backend-module-github@0.11.3-next.2 + - @backstage/plugin-catalog-node@1.20.1-next.1 + ## 0.3.17-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-github-org/package.json b/plugins/catalog-backend-module-github-org/package.json index 1f9f085dcb..d37a8c7a6e 100644 --- a/plugins/catalog-backend-module-github-org/package.json +++ b/plugins/catalog-backend-module-github-org/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-github-org", - "version": "0.3.17-next.1", + "version": "0.3.17", "description": "The github-org backend module for the catalog plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-github/CHANGELOG.md b/plugins/catalog-backend-module-github/CHANGELOG.md index 8362bf651c..4be66e6d20 100644 --- a/plugins/catalog-backend-module-github/CHANGELOG.md +++ b/plugins/catalog-backend-module-github/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-catalog-backend-module-github +## 0.12.0 + +### Minor Changes + +- b3286d5: Added the `github.com/user-id` annotation to store GitHub's user ID (immutable) in user entities. Also includes addition of the `userIdMatchingUserEntityAnnotation` sign-in resolver that matches users by the new ID. + +### Patch Changes + +- ed5a7a3: Introduce new configuration option to exclude suspended users from GitHub Enterprise instances. + + When it’s set to true, suspended users won’t be returned when querying the organization users for GitHub Enterprise instances. + Note that this option should be used only against GitHub Enterprise instances, the property does not exist in the github.com GraphQL schema, setting it will cause a schema validation error and the syncing of users will fail. + +- a413977: Added configurable `pageSizes` option to `GithubOrgEntityProvider` for GitHub GraphQL API queries to prevent `RESOURCE_LIMITS_EXCEEDED` errors with organizations with large number of teams and members. This aligns the configuration options with `GithubMultiOrgEntityProvider`. +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## 0.11.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + ## 0.11.3-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-github/package.json b/plugins/catalog-backend-module-github/package.json index 8fc3f9f919..b37546ca00 100644 --- a/plugins/catalog-backend-module-github/package.json +++ b/plugins/catalog-backend-module-github/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-github", - "version": "0.11.3-next.1", + "version": "0.12.0", "description": "A Backstage catalog backend module that helps integrate towards GitHub", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-github/report.api.md b/plugins/catalog-backend-module-github/report.api.md index 5f140a0d5e..25fc58be79 100644 --- a/plugins/catalog-backend-module-github/report.api.md +++ b/plugins/catalog-backend-module-github/report.api.md @@ -229,6 +229,7 @@ export class GithubOrgEntityProvider implements EntityProvider { githubCredentialsProvider?: GithubCredentialsProvider; userTransformer?: UserTransformer; teamTransformer?: TeamTransformer; + pageSizes?: Partial; excludeSuspendedUsers?: boolean; }); connect(connection: EntityProviderConnection): Promise; @@ -252,6 +253,7 @@ export interface GithubOrgEntityProviderOptions { id: string; logger: LoggerService; orgUrl: string; + pageSizes?: Partial; schedule?: 'manual' | SchedulerServiceTaskRunner; teamTransformer?: TeamTransformer; userTransformer?: UserTransformer; @@ -305,6 +307,7 @@ export type GithubTeam = { // @public export type GithubUser = { login: string; + id?: string; bio?: string; avatarUrl?: string; email?: string; diff --git a/plugins/catalog-backend-module-github/src/lib/annotation.ts b/plugins/catalog-backend-module-github/src/lib/annotation.ts index 4db6ffb975..2d06388d65 100644 --- a/plugins/catalog-backend-module-github/src/lib/annotation.ts +++ b/plugins/catalog-backend-module-github/src/lib/annotation.ts @@ -35,3 +35,13 @@ export const ANNOTATION_GITHUB_USER_LOGIN = 'github.com/user-login'; * @public */ export const ANNOTATION_GITHUB_TEAM_SLUG = 'github.com/team-slug'; + +/** + * The value of this annotation is the unique identifier for a user on + * [GitHub](https://github.com) (either the public one, or a private GitHub + * Enterprise installation) that is related to this entity. This is a stable + * identifier that persists even if the user changes their login name. + * + * @public + */ +export const ANNOTATION_GITHUB_USER_ID = 'github.com/user-id'; diff --git a/plugins/catalog-backend-module-github/src/lib/defaultTransformers.ts b/plugins/catalog-backend-module-github/src/lib/defaultTransformers.ts index 6befd32056..4de9af89c8 100644 --- a/plugins/catalog-backend-module-github/src/lib/defaultTransformers.ts +++ b/plugins/catalog-backend-module-github/src/lib/defaultTransformers.ts @@ -19,6 +19,7 @@ import { graphql } from '@octokit/graphql'; import { ANNOTATION_GITHUB_TEAM_SLUG, ANNOTATION_GITHUB_USER_LOGIN, + ANNOTATION_GITHUB_USER_ID, } from './annotation'; import { GithubTeam, GithubUser } from './github'; @@ -69,6 +70,7 @@ export const defaultUserTransformer = async ( name: item.login, annotations: { [ANNOTATION_GITHUB_USER_LOGIN]: item.login, + ...(item.id && { [ANNOTATION_GITHUB_USER_ID]: item.id }), }, }, spec: { diff --git a/plugins/catalog-backend-module-github/src/lib/github.ts b/plugins/catalog-backend-module-github/src/lib/github.ts index bd77df4da7..0690ca125b 100644 --- a/plugins/catalog-backend-module-github/src/lib/github.ts +++ b/plugins/catalog-backend-module-github/src/lib/github.ts @@ -112,6 +112,7 @@ export type GithubOrg = { */ export type GithubUser = { login: string; + id?: string; bio?: string; avatarUrl?: string; email?: string; @@ -202,6 +203,7 @@ export async function getOrganizationUsers( avatarUrl, bio, email @include(if: $email), + id, login, name, ${suspendedAtField} @@ -268,6 +270,7 @@ export async function getOrganizationTeams( avatarUrl, bio, email, + id, login, name, organizationVerifiedDomainEmails(login: $org) @@ -362,6 +365,7 @@ export async function getOrganizationTeamsFromUsers( avatarUrl, bio, email, + id, login, name, organizationVerifiedDomainEmails(login: $org) diff --git a/plugins/catalog-backend-module-github/src/lib/index.ts b/plugins/catalog-backend-module-github/src/lib/index.ts index ac73430d33..48050e96bb 100644 --- a/plugins/catalog-backend-module-github/src/lib/index.ts +++ b/plugins/catalog-backend-module-github/src/lib/index.ts @@ -38,3 +38,8 @@ export { buildOrgHierarchy, } from './org'; export { parseGithubOrgUrl } from './util'; +export { + ANNOTATION_GITHUB_USER_LOGIN, + ANNOTATION_GITHUB_TEAM_SLUG, + ANNOTATION_GITHUB_USER_ID, +} from './annotation'; diff --git a/plugins/catalog-backend-module-github/src/providers/GithubMultiOrgEntityProvider.test.ts b/plugins/catalog-backend-module-github/src/providers/GithubMultiOrgEntityProvider.test.ts index 1aa1af46d7..e80579ee36 100644 --- a/plugins/catalog-backend-module-github/src/providers/GithubMultiOrgEntityProvider.test.ts +++ b/plugins/catalog-backend-module-github/src/providers/GithubMultiOrgEntityProvider.test.ts @@ -94,6 +94,7 @@ describe('GithubMultiOrgEntityProvider', () => { nodes: [ { login: 'a', + id: 'f', name: 'b', bio: 'c', email: 'd', @@ -101,6 +102,7 @@ describe('GithubMultiOrgEntityProvider', () => { }, { login: 'x', + id: 'g', name: 'y', bio: 'z', email: 'w', @@ -128,7 +130,10 @@ describe('GithubMultiOrgEntityProvider', () => { }, members: { pageInfo: { hasNextPage: false }, - nodes: [{ login: 'a' }, { login: 'x' }], + nodes: [ + { login: 'a', id: 'f' }, + { login: 'x', id: 'g' }, + ], }, }, ], @@ -156,6 +161,7 @@ describe('GithubMultiOrgEntityProvider', () => { }, { login: 'q', + id: 'h', name: 'r', bio: 's', email: 't', @@ -183,7 +189,10 @@ describe('GithubMultiOrgEntityProvider', () => { }, members: { pageInfo: { hasNextPage: false }, - nodes: [{ login: 'a' }, { login: 'q' }], + nodes: [ + { login: 'a', id: 'f' }, + { login: 'q', id: 'h' }, + ], }, }, ], @@ -215,6 +224,7 @@ describe('GithubMultiOrgEntityProvider', () => { 'backstage.io/managed-by-origin-location': 'url:https://github.com/a', 'github.com/user-login': 'a', + 'github.com/user-id': 'f', }, description: 'c', name: 'a', @@ -241,6 +251,7 @@ describe('GithubMultiOrgEntityProvider', () => { 'backstage.io/managed-by-origin-location': 'url:https://github.com/x', 'github.com/user-login': 'x', + 'github.com/user-id': 'g', }, description: 'z', name: 'x', @@ -267,6 +278,7 @@ describe('GithubMultiOrgEntityProvider', () => { 'backstage.io/managed-by-origin-location': 'url:https://github.com/q', 'github.com/user-login': 'q', + 'github.com/user-id': 'h', }, description: 's', name: 'q', @@ -382,6 +394,7 @@ describe('GithubMultiOrgEntityProvider', () => { nodes: [ { login: 'a', + id: 'f', name: 'b', bio: 'c', email: 'd', @@ -389,6 +402,7 @@ describe('GithubMultiOrgEntityProvider', () => { }, { login: 'x', + id: 'g', name: 'y', bio: 'z', email: 'w', @@ -416,7 +430,10 @@ describe('GithubMultiOrgEntityProvider', () => { }, members: { pageInfo: { hasNextPage: false }, - nodes: [{ login: 'a' }, { login: 'x' }], + nodes: [ + { login: 'a', id: 'f' }, + { login: 'x', id: 'g' }, + ], }, }, ], @@ -444,6 +461,7 @@ describe('GithubMultiOrgEntityProvider', () => { }, { login: 'q', + id: 'h', name: 'r', bio: 's', email: 't', @@ -471,7 +489,10 @@ describe('GithubMultiOrgEntityProvider', () => { }, members: { pageInfo: { hasNextPage: false }, - nodes: [{ login: 'a' }, { login: 'q' }], + nodes: [ + { login: 'a', id: 'f' }, + { login: 'q', id: 'h' }, + ], }, }, ], @@ -517,6 +538,7 @@ describe('GithubMultiOrgEntityProvider', () => { 'backstage.io/managed-by-origin-location': 'url:https://github.com/a', 'github.com/user-login': 'a', + 'github.com/user-id': 'f', }, description: 'c', name: 'a', @@ -543,6 +565,7 @@ describe('GithubMultiOrgEntityProvider', () => { 'backstage.io/managed-by-origin-location': 'url:https://github.com/x', 'github.com/user-login': 'x', + 'github.com/user-id': 'g', }, description: 'z', name: 'x', @@ -569,6 +592,7 @@ describe('GithubMultiOrgEntityProvider', () => { 'backstage.io/managed-by-origin-location': 'url:https://github.com/q', 'github.com/user-login': 'q', + 'github.com/user-id': 'h', }, description: 's', name: 'q', @@ -656,6 +680,7 @@ describe('GithubMultiOrgEntityProvider', () => { nodes: [ { login: 'a', + id: 'f', name: 'b', bio: 'c', email: 'd', @@ -663,6 +688,7 @@ describe('GithubMultiOrgEntityProvider', () => { }, { login: 'x', + id: 'g', name: 'y', bio: 'z', email: 'w', @@ -690,7 +716,10 @@ describe('GithubMultiOrgEntityProvider', () => { }, members: { pageInfo: { hasNextPage: false }, - nodes: [{ login: 'a' }, { login: 'x' }], + nodes: [ + { login: 'a', id: 'f' }, + { login: 'x', id: 'g' }, + ], }, }, ], @@ -718,6 +747,7 @@ describe('GithubMultiOrgEntityProvider', () => { }, { login: 'q', + id: 'h', name: 'r', bio: 's', email: 't', @@ -745,7 +775,10 @@ describe('GithubMultiOrgEntityProvider', () => { }, members: { pageInfo: { hasNextPage: false }, - nodes: [{ login: 'a' }, { login: 'q' }], + nodes: [ + { login: 'a', id: 'f' }, + { login: 'q', id: 'h' }, + ], }, }, ], @@ -783,6 +816,7 @@ describe('GithubMultiOrgEntityProvider', () => { 'backstage.io/managed-by-origin-location': 'url:https://github.com/a', 'github.com/user-login': 'a', + 'github.com/user-id': 'f', }, description: 'c', name: 'a', @@ -809,6 +843,7 @@ describe('GithubMultiOrgEntityProvider', () => { 'backstage.io/managed-by-origin-location': 'url:https://github.com/x', 'github.com/user-login': 'x', + 'github.com/user-id': 'g', }, description: 'z', name: 'x', @@ -835,6 +870,7 @@ describe('GithubMultiOrgEntityProvider', () => { 'backstage.io/managed-by-origin-location': 'url:https://github.com/q', 'github.com/user-login': 'q', + 'github.com/user-id': 'h', }, description: 's', name: 'q', @@ -1099,6 +1135,7 @@ describe('GithubMultiOrgEntityProvider', () => { nodes: [ { login: 'a', + id: 'f', name: 'b', bio: 'c', email: 'd', @@ -1126,7 +1163,7 @@ describe('GithubMultiOrgEntityProvider', () => { }, members: { pageInfo: { hasNextPage: false }, - nodes: [{ login: 'a' }], + nodes: [{ login: 'a', id: 'f' }], }, }, ], @@ -1151,7 +1188,7 @@ describe('GithubMultiOrgEntityProvider', () => { }, members: { pageInfo: { hasNextPage: false }, - nodes: [{ login: 'a' }], + nodes: [{ login: 'a', id: 'f' }], }, }, ], @@ -1176,7 +1213,7 @@ describe('GithubMultiOrgEntityProvider', () => { }, members: { pageInfo: { hasNextPage: false }, - nodes: [{ login: 'a' }], + nodes: [{ login: 'a', id: 'f' }], }, }, ], @@ -1213,6 +1250,7 @@ describe('GithubMultiOrgEntityProvider', () => { 'backstage.io/managed-by-origin-location': 'url:https://github.com/a', 'github.com/user-login': 'a', + 'github.com/user-id': 'f', }, description: 'c', name: 'a', @@ -1300,7 +1338,7 @@ describe('GithubMultiOrgEntityProvider', () => { }, members: { pageInfo: { hasNextPage: false }, - nodes: [{ login: 'a', name: 'a' }], + nodes: [{ login: 'a', id: 'f', name: 'a' }], }, }, ], @@ -1328,6 +1366,7 @@ describe('GithubMultiOrgEntityProvider', () => { membership: { user: { name: 'a', + node_id: 'f', avatar_url: 'https://avatars.githubusercontent.com/u/83820368', email: 'user1@test.com', login: 'a', @@ -1351,6 +1390,7 @@ describe('GithubMultiOrgEntityProvider', () => { 'backstage.io/managed-by-origin-location': 'url:https://github.com/a', 'github.com/user-login': 'a', + 'github.com/user-id': 'f', }, name: 'a', }, @@ -1398,6 +1438,7 @@ describe('GithubMultiOrgEntityProvider', () => { membership: { user: { name: 'a', + node_id: 'f', avatar_url: 'https://avatars.githubusercontent.com/u/83820368', email: 'user1@test.com', login: 'a', @@ -1422,6 +1463,7 @@ describe('GithubMultiOrgEntityProvider', () => { 'backstage.io/managed-by-origin-location': 'url:https://github.com/a', 'github.com/user-login': 'a', + 'github.com/user-id': 'f', }, name: 'a', }, @@ -1473,7 +1515,7 @@ describe('GithubMultiOrgEntityProvider', () => { }, members: { pageInfo: { hasNextPage: false }, - nodes: [{ login: 'a', name: 'a' }], + nodes: [{ login: 'a', id: 'f', name: 'a' }], }, }, ], @@ -1493,6 +1535,7 @@ describe('GithubMultiOrgEntityProvider', () => { membership: { user: { name: 'a', + node_id: 'f', avatar_url: 'https://avatars.githubusercontent.com/u/83820368', email: 'user1@test.com', login: 'a', @@ -1516,6 +1559,7 @@ describe('GithubMultiOrgEntityProvider', () => { 'backstage.io/managed-by-origin-location': 'url:https://github.com/a', 'github.com/user-login': 'a', + 'github.com/user-id': 'f', }, name: 'a', }, @@ -1729,7 +1773,7 @@ describe('GithubMultiOrgEntityProvider', () => { }, members: { pageInfo: { hasNextPage: false }, - nodes: [{ login: 'a', name: 'a' }], + nodes: [{ login: 'a', id: 'f', name: 'a' }], }, }, }, @@ -1741,6 +1785,7 @@ describe('GithubMultiOrgEntityProvider', () => { nodes: [ { login: 'a', + id: 'f', name: 'b', bio: 'c', email: 'd', @@ -1748,6 +1793,7 @@ describe('GithubMultiOrgEntityProvider', () => { }, { login: 'w', + id: 'i', name: 'x', bio: 'y', email: 'z', @@ -1774,7 +1820,7 @@ describe('GithubMultiOrgEntityProvider', () => { }, members: { pageInfo: { hasNextPage: false }, - nodes: [{ login: 'a', name: 'a' }], + nodes: [{ login: 'a', id: 'f', name: 'a' }], }, }, ], @@ -1798,7 +1844,7 @@ describe('GithubMultiOrgEntityProvider', () => { }, members: { pageInfo: { hasNextPage: false }, - nodes: [{ login: 'a', name: 'a' }], + nodes: [{ login: 'a', id: 'f', name: 'a' }], }, }, ], @@ -1847,6 +1893,7 @@ describe('GithubMultiOrgEntityProvider', () => { 'backstage.io/managed-by-origin-location': 'url:https://github.com/a', 'github.com/user-login': 'a', + 'github.com/user-id': 'f', }, name: 'a', description: 'c', @@ -2110,7 +2157,7 @@ describe('GithubMultiOrgEntityProvider', () => { }, members: { pageInfo: { hasNextPage: false }, - nodes: [{ login: 'a', name: 'a' }], + nodes: [{ login: 'a', id: 'f', name: 'a' }], }, }, }, @@ -2147,7 +2194,7 @@ describe('GithubMultiOrgEntityProvider', () => { }, members: { pageInfo: { hasNextPage: false }, - nodes: [{ login: 'a', name: 'a' }], + nodes: [{ login: 'a', id: 'f', name: 'a' }], }, }, ], @@ -2171,7 +2218,7 @@ describe('GithubMultiOrgEntityProvider', () => { }, members: { pageInfo: { hasNextPage: false }, - nodes: [{ login: 'a', name: 'a' }], + nodes: [{ login: 'a', id: 'f', name: 'a' }], }, }, ], @@ -2194,6 +2241,7 @@ describe('GithubMultiOrgEntityProvider', () => { member: { name: 'a', login: 'a', + node_id: 'f', avatar_url: 'https://avatars.githubusercontent.com/u/83820368', email: 'user1@test.com', }, @@ -2245,6 +2293,7 @@ describe('GithubMultiOrgEntityProvider', () => { 'backstage.io/managed-by-origin-location': 'url:https://github.com/a', 'github.com/user-login': 'a', + 'github.com/user-id': 'f', }, name: 'a', }, @@ -2327,7 +2376,7 @@ describe('GithubMultiOrgEntityProvider', () => { }, members: { pageInfo: { hasNextPage: false }, - nodes: [{ login: 'a', name: 'a' }], + nodes: [{ login: 'a', id: 'f', name: 'a' }], }, }, ], @@ -2350,6 +2399,7 @@ describe('GithubMultiOrgEntityProvider', () => { member: { name: 'a', login: 'a', + node_id: 'f', avatar_url: 'https://avatars.githubusercontent.com/u/83820368', email: 'user1@test.com', }, @@ -2401,6 +2451,7 @@ describe('GithubMultiOrgEntityProvider', () => { 'backstage.io/managed-by-origin-location': 'url:https://github.com/a', 'github.com/user-login': 'a', + 'github.com/user-id': 'f', }, name: 'a', }, diff --git a/plugins/catalog-backend-module-github/src/providers/GithubMultiOrgEntityProvider.ts b/plugins/catalog-backend-module-github/src/providers/GithubMultiOrgEntityProvider.ts index 173da84f58..28d598b5b1 100644 --- a/plugins/catalog-backend-module-github/src/providers/GithubMultiOrgEntityProvider.ts +++ b/plugins/catalog-backend-module-github/src/providers/GithubMultiOrgEntityProvider.ts @@ -531,7 +531,13 @@ export class GithubMultiOrgEntityProvider implements EntityProvider { const userTransformer = this.options.userTransformer || defaultUserTransformer; - const { name, avatar_url: avatarUrl, email, login } = event.membership.user; + const { + name, + avatar_url: avatarUrl, + email, + login, + node_id, + } = event.membership.user; const org = event.organization.login; const { headers } = await this.options.githubCredentialsProvider.getCredentials({ @@ -573,6 +579,7 @@ export class GithubMultiOrgEntityProvider implements EntityProvider { avatarUrl, login, email: email ?? undefined, + id: node_id, }, { org, @@ -818,13 +825,14 @@ export class GithubMultiOrgEntityProvider implements EntityProvider { const userTransformer = this.options.userTransformer || defaultUserTransformer; - const { name, avatar_url: avatarUrl, email, login } = event.member; + const { name, avatar_url: avatarUrl, email, login, node_id } = event.member; const user = await userTransformer( { name, avatarUrl, login, email: email ?? undefined, + id: node_id, }, { org, diff --git a/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.test.ts b/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.test.ts index 17fa00b137..9be5a3e161 100644 --- a/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.test.ts +++ b/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.test.ts @@ -89,6 +89,7 @@ describe('GithubOrgEntityProvider', () => { nodes: [ { login: 'a', + id: 'f', name: 'b', bio: 'c', email: 'd', @@ -136,6 +137,7 @@ describe('GithubOrgEntityProvider', () => { 'backstage.io/managed-by-origin-location': 'url:https://https://github.com/a', 'github.com/user-login': 'a', + 'github.com/user-id': 'f', }, description: 'c', name: 'a', @@ -311,6 +313,7 @@ describe('GithubOrgEntityProvider', () => { 'backstage.io/managed-by-origin-location': 'url:https://github.com/githubuser', 'github.com/user-login': 'githubuser', + 'github.com/user-id': 'githubuserId', }, }, spec: { @@ -331,6 +334,7 @@ describe('GithubOrgEntityProvider', () => { user: { name: 'githubuser', login: 'githubuser', + node_id: 'githubuserId', avatar_url: 'https://avatars.githubusercontent.com/u/83820368', email: 'user1@test.com', }, @@ -398,6 +402,7 @@ describe('GithubOrgEntityProvider', () => { 'backstage.io/managed-by-origin-location': 'url:https://github.com/githubuser', 'github.com/user-login': 'githubuser', + 'github.com/user-id': 'githubuserId', }, }, spec: { @@ -418,6 +423,7 @@ describe('GithubOrgEntityProvider', () => { user: { name: 'githubuser', login: 'githubuser', + node_id: 'githubuserId', avatar_url: 'https://avatars.githubusercontent.com/u/83820368', email: 'user1@test.com', }, @@ -778,6 +784,7 @@ describe('GithubOrgEntityProvider', () => { nodes: [ { login: 'a', + id: 'f', name: 'b', bio: 'c', email: 'd', @@ -785,6 +792,7 @@ describe('GithubOrgEntityProvider', () => { }, { login: 'githubuser', + id: 'githubuserId', name: 'githubuser', bio: 'githubuser', email: 'd', @@ -865,6 +873,7 @@ describe('GithubOrgEntityProvider', () => { 'backstage.io/managed-by-origin-location': 'url:https://github.com/a', 'github.com/user-login': 'a', + 'github.com/user-id': 'f', }, name: 'a', description: 'c', @@ -891,6 +900,7 @@ describe('GithubOrgEntityProvider', () => { 'backstage.io/managed-by-origin-location': 'url:https://github.com/githubuser', 'github.com/user-login': 'githubuser', + 'github.com/user-id': 'githubuserId', }, name: 'githubuser', description: 'githubuser', @@ -1029,6 +1039,7 @@ describe('GithubOrgEntityProvider', () => { nodes: [ { login: 'a', + id: 'f', name: 'b', bio: 'c', email: 'd', @@ -1036,6 +1047,7 @@ describe('GithubOrgEntityProvider', () => { }, { login: 'githubuser', + id: 'githubuserId', name: 'githubuser', bio: 'githubuser', email: 'd', @@ -1112,6 +1124,7 @@ describe('GithubOrgEntityProvider', () => { 'backstage.io/managed-by-origin-location': 'url:https://github.com/githubuser', 'github.com/user-login': 'githubuser', + 'github.com/user-id': 'githubuserId', }, name: 'githubuser', description: 'githubuser', @@ -1168,6 +1181,7 @@ describe('GithubOrgEntityProvider', () => { 'backstage.io/managed-by-origin-location': 'url:https://github.com/githubuser', 'github.com/user-login': 'githubuser', + 'github.com/user-id': 'githubuserId', }, name: 'githubuser', description: 'githubuser', @@ -1277,6 +1291,7 @@ describe('GithubOrgEntityProvider', () => { nodes: [ { login: 'githubuser', + id: 'githubuserId', name: 'githubuser', bio: 'githubuser', email: 'd', @@ -1336,6 +1351,7 @@ describe('GithubOrgEntityProvider', () => { 'backstage.io/managed-by-origin-location': 'url:https://github.com/githubuser', 'github.com/user-login': 'githubuser', + 'github.com/user-id': 'githubuserId', }, name: 'githubuser', description: 'githubuser', @@ -1392,6 +1408,7 @@ describe('GithubOrgEntityProvider', () => { 'backstage.io/managed-by-origin-location': 'url:https://github.com/githubuser', 'github.com/user-login': 'githubuser', + 'github.com/user-id': 'githubuserId', }, name: 'githubuser', description: 'githubuser', diff --git a/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.ts b/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.ts index 4758311e83..bb4b268e62 100644 --- a/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.ts +++ b/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.ts @@ -59,6 +59,7 @@ import { getOrganizationTeams, getOrganizationTeamsFromUsers, getOrganizationUsers, + GithubPageSizes, GithubTeam, } from '../lib/github'; import { areGroupEntities, areUserEntities } from '../lib/guards'; @@ -132,6 +133,12 @@ export interface GithubOrgEntityProviderOptions { */ teamTransformer?: TeamTransformer; + /** + * Optionally configure page sizes for GitHub GraphQL API queries. + * Reduce these values if hitting RESOURCE_LIMITS_EXCEEDED errors. + */ + pageSizes?: Partial; + /** * Optionally exclude suspended users when querying organization users. * @defaultValue false @@ -176,6 +183,7 @@ export class GithubOrgEntityProvider implements EntityProvider { userTransformer: options.userTransformer, teamTransformer: options.teamTransformer, events: options.events, + pageSizes: options.pageSizes, excludeSuspendedUsers: options.excludeSuspendedUsers, }); @@ -194,6 +202,7 @@ export class GithubOrgEntityProvider implements EntityProvider { githubCredentialsProvider?: GithubCredentialsProvider; userTransformer?: UserTransformer; teamTransformer?: TeamTransformer; + pageSizes?: Partial; excludeSuspendedUsers?: boolean; }, ) { @@ -207,6 +216,13 @@ export class GithubOrgEntityProvider implements EntityProvider { return `GithubOrgEntityProvider:${this.options.id}`; } + private getPageSizes(): GithubPageSizes { + return { + ...DEFAULT_PAGE_SIZES, + ...this.options.pageSizes, + }; + } + /** {@inheritdoc @backstage/plugin-catalog-node#EntityProvider.connect} */ async connect(connection: EntityProviderConnection) { this.connection = connection; @@ -242,18 +258,20 @@ export class GithubOrgEntityProvider implements EntityProvider { }); const { org } = parseGithubOrgUrl(this.options.orgUrl); + const pageSizes = this.getPageSizes(); const { users } = await getOrganizationUsers( client, org, tokenType, this.options.userTransformer, - DEFAULT_PAGE_SIZES, + pageSizes, this.options.excludeSuspendedUsers, ); const { teams } = await getOrganizationTeams( client, org, this.options.teamTransformer, + pageSizes, ); if (areGroupEntities(teams)) { @@ -365,6 +383,7 @@ export class GithubOrgEntityProvider implements EntityProvider { }); const { org } = parseGithubOrgUrl(this.options.orgUrl); + const pageSizes = this.getPageSizes(); const { team } = await getOrganizationTeam( client, org, @@ -377,7 +396,7 @@ export class GithubOrgEntityProvider implements EntityProvider { org, tokenType, this.options.userTransformer, - DEFAULT_PAGE_SIZES, + pageSizes, this.options.excludeSuspendedUsers, ); @@ -395,6 +414,7 @@ export class GithubOrgEntityProvider implements EntityProvider { org, usersToRebuild.map(u => u.metadata.name), this.options.teamTransformer, + pageSizes, ); if (areGroupEntities(teams)) { @@ -458,6 +478,7 @@ export class GithubOrgEntityProvider implements EntityProvider { }); const { org } = parseGithubOrgUrl(this.options.orgUrl); + const pageSizes = this.getPageSizes(); const { team } = await getOrganizationTeam( client, org, @@ -470,7 +491,7 @@ export class GithubOrgEntityProvider implements EntityProvider { org, tokenType, this.options.userTransformer, - DEFAULT_PAGE_SIZES, + pageSizes, this.options.excludeSuspendedUsers, ); @@ -481,6 +502,7 @@ export class GithubOrgEntityProvider implements EntityProvider { org, [userLogin], this.options.teamTransformer, + pageSizes, ); // we include group because the removed event need to update the old group too @@ -565,7 +587,13 @@ export class GithubOrgEntityProvider implements EntityProvider { const userTransformer = this.options.userTransformer || defaultUserTransformer; - const { name, avatar_url: avatarUrl, email, login } = event.membership.user; + const { + name, + avatar_url: avatarUrl, + email, + login, + node_id, + } = event.membership.user; const org = event.organization.login; const { headers } = await this.credentialsProvider.getCredentials({ url: this.options.orgUrl, @@ -581,6 +609,7 @@ export class GithubOrgEntityProvider implements EntityProvider { avatarUrl, login, email: email || undefined, + id: node_id, // we don't have this information in the event, so the refresh will handle that for us organizationVerifiedDomainEmails: [], }, diff --git a/plugins/catalog-backend-module-gitlab-org/CHANGELOG.md b/plugins/catalog-backend-module-gitlab-org/CHANGELOG.md index c7cb44a75f..e781626038 100644 --- a/plugins/catalog-backend-module-gitlab-org/CHANGELOG.md +++ b/plugins/catalog-backend-module-gitlab-org/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-catalog-backend-module-gitlab-org +## 0.2.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-backend-module-gitlab@0.7.7-next.0 + - @backstage/plugin-catalog-node@1.20.1 + - @backstage/plugin-events-node@0.4.18 + +## 0.2.16 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-backend-module-gitlab@0.7.6 + - @backstage/plugin-catalog-node@1.20.1 + +## 0.2.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/plugin-catalog-backend-module-gitlab@0.7.6-next.1 + - @backstage/plugin-catalog-node@1.20.1-next.1 + ## 0.2.16-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-gitlab-org/package.json b/plugins/catalog-backend-module-gitlab-org/package.json index 1ecdd6b91d..3587dd5e5e 100644 --- a/plugins/catalog-backend-module-gitlab-org/package.json +++ b/plugins/catalog-backend-module-gitlab-org/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-gitlab-org", - "version": "0.2.16-next.0", + "version": "0.2.17-next.0", "description": "The gitlab-org backend module for the catalog plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-gitlab/CHANGELOG.md b/plugins/catalog-backend-module-gitlab/CHANGELOG.md index e4a8799928..d3e9b20730 100644 --- a/plugins/catalog-backend-module-gitlab/CHANGELOG.md +++ b/plugins/catalog-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,44 @@ # @backstage/plugin-catalog-backend-module-gitlab +## 0.7.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.14.1-next.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/integration@1.19.0 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1 + - @backstage/plugin-events-node@0.4.18 + +## 0.7.6 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-defaults@0.14.0 + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## 0.7.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.14.0-next.1 + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + ## 0.7.6-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-gitlab/package.json b/plugins/catalog-backend-module-gitlab/package.json index 28838904cd..6f9770a568 100644 --- a/plugins/catalog-backend-module-gitlab/package.json +++ b/plugins/catalog-backend-module-gitlab/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-gitlab", - "version": "0.7.6-next.0", + "version": "0.7.7-next.0", "description": "A Backstage catalog backend module that helps integrate towards GitLab", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md b/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md index 3d29535081..f1e8c36d89 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md +++ b/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md @@ -1,5 +1,52 @@ # @backstage/plugin-catalog-backend-module-incremental-ingestion +## 0.7.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.14.1-next.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-backend@3.3.1-next.0 + - @backstage/plugin-catalog-node@1.20.1 + - @backstage/plugin-events-node@0.4.18 + - @backstage/plugin-permission-common@0.9.3 + +## 0.7.7 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- fb029b6: Updated luxon types +- Updated dependencies + - @backstage/backend-defaults@0.14.0 + - @backstage/plugin-catalog-backend@3.3.0 + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## 0.7.7-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- fb029b6: Updated luxon types +- Updated dependencies + - @backstage/backend-defaults@0.14.0-next.1 + - @backstage/plugin-catalog-backend@3.2.1-next.1 + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-node@1.20.1-next.1 + - @backstage/plugin-permission-common@0.9.3 + ## 0.7.7-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-incremental-ingestion/package.json b/plugins/catalog-backend-module-incremental-ingestion/package.json index 07559d6d01..133cae849e 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/package.json +++ b/plugins/catalog-backend-module-incremental-ingestion/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-incremental-ingestion", - "version": "0.7.7-next.0", + "version": "0.7.8-next.0", "description": "An entity provider for streaming large asset sources into the catalog", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-ldap/CHANGELOG.md b/plugins/catalog-backend-module-ldap/CHANGELOG.md index 2dbc7cdfa1..6bcb9ea561 100644 --- a/plugins/catalog-backend-module-ldap/CHANGELOG.md +++ b/plugins/catalog-backend-module-ldap/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-catalog-backend-module-ldap +## 0.12.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## 0.12.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + ## 0.12.1-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-ldap/package.json b/plugins/catalog-backend-module-ldap/package.json index 4ed1c23ed5..52bce2aae7 100644 --- a/plugins/catalog-backend-module-ldap/package.json +++ b/plugins/catalog-backend-module-ldap/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-ldap", - "version": "0.12.1-next.0", + "version": "0.12.1", "description": "A Backstage catalog backend module that helps integrate towards LDAP", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-logs/CHANGELOG.md b/plugins/catalog-backend-module-logs/CHANGELOG.md index 213138f4de..633be5a127 100644 --- a/plugins/catalog-backend-module-logs/CHANGELOG.md +++ b/plugins/catalog-backend-module-logs/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-catalog-backend-module-logs +## 0.1.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-backend@3.3.1-next.0 + - @backstage/plugin-events-node@0.4.18 + +## 0.1.17 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@3.3.0 + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + +## 0.1.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@3.2.1-next.1 + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + ## 0.1.17-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-logs/package.json b/plugins/catalog-backend-module-logs/package.json index 581467311a..12224abd8a 100644 --- a/plugins/catalog-backend-module-logs/package.json +++ b/plugins/catalog-backend-module-logs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-logs", - "version": "0.1.17-next.0", + "version": "0.1.18-next.0", "description": "A module that subscribes to catalog related events and logs them.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-msgraph/CHANGELOG.md b/plugins/catalog-backend-module-msgraph/CHANGELOG.md index 51433c91c1..6577c69166 100644 --- a/plugins/catalog-backend-module-msgraph/CHANGELOG.md +++ b/plugins/catalog-backend-module-msgraph/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-catalog-backend-module-msgraph +## 0.8.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## 0.8.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + ## 0.8.3-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index 5a4161ae1f..0dddba19f7 100644 --- a/plugins/catalog-backend-module-msgraph/package.json +++ b/plugins/catalog-backend-module-msgraph/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-msgraph", - "version": "0.8.3-next.0", + "version": "0.8.3", "description": "A Backstage catalog backend module that helps integrate towards Microsoft Graph", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-openapi/CHANGELOG.md b/plugins/catalog-backend-module-openapi/CHANGELOG.md index 3fd5040a18..031087fe0e 100644 --- a/plugins/catalog-backend-module-openapi/CHANGELOG.md +++ b/plugins/catalog-backend-module-openapi/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-catalog-backend-module-openapi +## 0.2.17 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## 0.2.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + ## 0.2.17-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-openapi/package.json b/plugins/catalog-backend-module-openapi/package.json index a32778dfe4..fa9eddcf3a 100644 --- a/plugins/catalog-backend-module-openapi/package.json +++ b/plugins/catalog-backend-module-openapi/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-openapi", - "version": "0.2.17-next.0", + "version": "0.2.17", "description": "A Backstage catalog backend module that helps with OpenAPI specifications", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-puppetdb/CHANGELOG.md b/plugins/catalog-backend-module-puppetdb/CHANGELOG.md index ef31a1fa75..c270f87cb5 100644 --- a/plugins/catalog-backend-module-puppetdb/CHANGELOG.md +++ b/plugins/catalog-backend-module-puppetdb/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-catalog-backend-module-puppetdb +## 0.2.17 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## 0.2.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-node@1.20.1-next.1 + ## 0.2.17-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-puppetdb/package.json b/plugins/catalog-backend-module-puppetdb/package.json index 218d037800..f2cd6115d1 100644 --- a/plugins/catalog-backend-module-puppetdb/package.json +++ b/plugins/catalog-backend-module-puppetdb/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-puppetdb", - "version": "0.2.17-next.0", + "version": "0.2.17", "description": "A Backstage catalog backend module that helps integrate towards PuppetDB", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md b/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md index fd98e743c2..f1e46d21fc 100644 --- a/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md +++ b/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-catalog-backend-module-scaffolder-entity-model +## 0.2.15 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + - @backstage/plugin-scaffolder-common@1.7.4 + +## 0.2.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + - @backstage/plugin-scaffolder-common@1.7.4-next.0 + ## 0.2.15-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-scaffolder-entity-model/package.json b/plugins/catalog-backend-module-scaffolder-entity-model/package.json index bec61b7a20..49d98fd6fc 100644 --- a/plugins/catalog-backend-module-scaffolder-entity-model/package.json +++ b/plugins/catalog-backend-module-scaffolder-entity-model/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-scaffolder-entity-model", - "version": "0.2.15-next.0", + "version": "0.2.15", "description": "Adds support for the scaffolder specific entity model (e.g. the Template kind) to the catalog backend plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-unprocessed/CHANGELOG.md b/plugins/catalog-backend-module-unprocessed/CHANGELOG.md index bb501f7c31..32dde9548a 100644 --- a/plugins/catalog-backend-module-unprocessed/CHANGELOG.md +++ b/plugins/catalog-backend-module-unprocessed/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-catalog-backend-module-unprocessed +## 0.6.7 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-unprocessed-entities-common@0.0.12 + - @backstage/plugin-catalog-node@1.20.1 + +## 0.6.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + - @backstage/plugin-catalog-unprocessed-entities-common@0.0.12-next.0 + - @backstage/plugin-permission-common@0.9.3 + ## 0.6.7-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-unprocessed/package.json b/plugins/catalog-backend-module-unprocessed/package.json index fcb5d57809..b735e7a13a 100644 --- a/plugins/catalog-backend-module-unprocessed/package.json +++ b/plugins/catalog-backend-module-unprocessed/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-unprocessed", - "version": "0.6.7-next.1", + "version": "0.6.7", "description": "Backstage Catalog module to view unprocessed entities", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend/CHANGELOG.md b/plugins/catalog-backend/CHANGELOG.md index 2ab123b03f..69d43dc35b 100644 --- a/plugins/catalog-backend/CHANGELOG.md +++ b/plugins/catalog-backend/CHANGELOG.md @@ -1,5 +1,62 @@ # @backstage/plugin-catalog-backend +## 3.3.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-openapi-utils@0.6.5-next.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/integration@1.19.0 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1 + - @backstage/plugin-events-node@0.4.18 + - @backstage/plugin-permission-common@0.9.3 + - @backstage/plugin-permission-node@0.10.7 + +## 3.3.0 + +### Minor Changes + +- dce1824: Added `ActionsRegistry` actions for `register-entity` and `unregister-entity` + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- 8101ec1: Fixed default refresh service to go through the whole ancestry of the entity. +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-openapi-utils@0.6.4 + - @backstage/plugin-events-node@0.4.18 + - @backstage/plugin-permission-node@0.10.7 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## 3.2.1-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-openapi-utils@0.6.4-next.1 + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/plugin-permission-node@0.10.7-next.1 + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-catalog-node@1.20.1-next.1 + - @backstage/plugin-permission-common@0.9.3 + ## 3.2.1-next.0 ### Patch Changes diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 508299734f..8128df6616 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend", - "version": "3.2.1-next.0", + "version": "3.3.1-next.0", "description": "The Backstage backend plugin that provides the Backstage catalog", "backstage": { "role": "backend-plugin", diff --git a/plugins/catalog-backend/src/actions/createRegisterCatalogEntitiesAction.test.ts b/plugins/catalog-backend/src/actions/createRegisterCatalogEntitiesAction.test.ts new file mode 100644 index 0000000000..31a89a31f3 --- /dev/null +++ b/plugins/catalog-backend/src/actions/createRegisterCatalogEntitiesAction.test.ts @@ -0,0 +1,105 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { createRegisterCatalogEntitiesAction } from './createRegisterCatalogEntitiesAction'; +import { catalogServiceMock } from '@backstage/plugin-catalog-node/testUtils'; +import { actionsRegistryServiceMock } from '@backstage/backend-test-utils/alpha'; +import { ForwardedError } from '@backstage/errors'; + +describe('createRegisterCatalogEntitiesAction', () => { + it('should successfully register a catalog location with a valid URL', async () => { + const mockActionsRegistry = actionsRegistryServiceMock(); + const mockCatalog = catalogServiceMock(); + + const mockLocationId = 'test-location-id-1234'; + mockCatalog.addLocation = jest.fn().mockResolvedValue({ + location: { + id: mockLocationId, + type: 'url', + target: 'https://github.com/example/repo/blob/main/catalog-info.yaml', + }, + entities: [], + exists: false, + }); + + createRegisterCatalogEntitiesAction({ + catalog: mockCatalog, + actionsRegistry: mockActionsRegistry, + }); + + const result = await mockActionsRegistry.invoke({ + id: 'test:register-entity', + input: { + locationUrl: + 'https://github.com/example/repo/blob/main/catalog-info.yaml', + }, + }); + + expect(result.output).toEqual({ + locationId: mockLocationId, + }); + expect(mockCatalog.addLocation).toHaveBeenCalledWith( + { + type: 'url', + target: 'https://github.com/example/repo/blob/main/catalog-info.yaml', + }, + expect.objectContaining({ + credentials: expect.any(Object), + }), + ); + }); + + it('should throw an error if locationUrl is not a valid URL', async () => { + const mockActionsRegistry = actionsRegistryServiceMock(); + const mockCatalog = catalogServiceMock(); + + createRegisterCatalogEntitiesAction({ + catalog: mockCatalog, + actionsRegistry: mockActionsRegistry, + }); + + await expect( + mockActionsRegistry.invoke({ + id: 'test:register-entity', + input: { locationUrl: 'not-a-valid-url' }, + }), + ).rejects.toThrow('not-a-valid-url is an invalid URL'); + }); + + it('should throw a ForwardedError if catalog.addLocation throws an error', async () => { + const mockActionsRegistry = actionsRegistryServiceMock(); + const mockCatalog = catalogServiceMock(); + + const errorMessage = 'Failed to add location'; + mockCatalog.addLocation = jest + .fn() + .mockRejectedValue(new Error(errorMessage)); + + createRegisterCatalogEntitiesAction({ + catalog: mockCatalog, + actionsRegistry: mockActionsRegistry, + }); + + await expect( + mockActionsRegistry.invoke({ + id: 'test:register-entity', + input: { + locationUrl: + 'https://github.com/example/repo/blob/main/catalog-info.yaml', + }, + }), + ).rejects.toThrow(ForwardedError); + }); +}); diff --git a/plugins/catalog-backend/src/actions/createRegisterCatalogEntitiesAction.ts b/plugins/catalog-backend/src/actions/createRegisterCatalogEntitiesAction.ts new file mode 100644 index 0000000000..c521672ae1 --- /dev/null +++ b/plugins/catalog-backend/src/actions/createRegisterCatalogEntitiesAction.ts @@ -0,0 +1,89 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { ActionsRegistryService } from '@backstage/backend-plugin-api/alpha'; +import { InputError } from '@backstage/errors'; +import { CatalogService } from '@backstage/plugin-catalog-node'; + +const isValidUrl = (url: string) => { + try { + // eslint-disable-next-line no-new + new URL(url); + return true; + } catch (error) { + return false; + } +}; + +export const createRegisterCatalogEntitiesAction = ({ + catalog, + actionsRegistry, +}: { + catalog: CatalogService; + actionsRegistry: ActionsRegistryService; +}) => { + actionsRegistry.register({ + name: 'register-entity', + title: 'Register entity in the Catalog', + attributes: { + destructive: false, + readOnly: false, + idempotent: false, + }, + description: `Registers one or more entities in the Backstage catalog by creating a Location entity that points to a remote catalog-info.yaml file. + +This action is similar to the "Register existing component" flow in the Backstage UI, where you provide a URL to a catalog-info.yaml file describing catalog entities such as Components, Systems, Resources, APIs, Users, and Groups. The action will create a new Location entity that references the provided file; all entities defined within that file will be imported into the catalog. + +A unique identifier (locationId) will be returned for the newly created Location. You can use this identifier in the future to unregister or delete the Location and all entities it owns. +`, + schema: { + input: z => + z.object({ + locationUrl: z + .string() + .describe( + `URL reference to the catalog-info.yaml file that describes the entity to register. For example: https://github.com/backstage/demo/blob/master/catalog-info.yaml`, + ), + }), + output: z => + z.object({ + locationId: z + .string() + .describe('The ID of the entity that was registered'), + }), + }, + action: async ({ input, credentials }) => { + if (!isValidUrl(input.locationUrl)) { + throw new InputError(`${input.locationUrl} is an invalid URL`); + } + + const result = await catalog.addLocation( + { + type: 'url', + target: input.locationUrl, + }, + { + credentials, + }, + ); + + return { + output: { + locationId: result.location.id, + }, + }; + }, + }); +}; diff --git a/plugins/catalog-backend/src/actions/createUnregisterCatalogEntitiesAction.test.ts b/plugins/catalog-backend/src/actions/createUnregisterCatalogEntitiesAction.test.ts new file mode 100644 index 0000000000..492a427630 --- /dev/null +++ b/plugins/catalog-backend/src/actions/createUnregisterCatalogEntitiesAction.test.ts @@ -0,0 +1,274 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { createUnregisterCatalogEntitiesAction } from './createUnregisterCatalogEntitiesAction'; +import { catalogServiceMock } from '@backstage/plugin-catalog-node/testUtils'; +import { actionsRegistryServiceMock } from '@backstage/backend-test-utils/alpha'; + +describe('createUnregisterCatalogEntitiesAction', () => { + describe('with locationId', () => { + it('should successfully unregister a catalog location with a valid locationId', async () => { + const mockActionsRegistry = actionsRegistryServiceMock(); + const mockCatalog = catalogServiceMock(); + + mockCatalog.removeLocationById = jest.fn().mockResolvedValue(undefined); + + createUnregisterCatalogEntitiesAction({ + catalog: mockCatalog, + actionsRegistry: mockActionsRegistry, + }); + + const result = await mockActionsRegistry.invoke({ + id: 'test:unregister-entity', + input: { type: { locationId: 'test-location-id-1234' } }, + }); + + expect(result.output).toEqual({}); + expect(mockCatalog.removeLocationById).toHaveBeenCalledWith( + 'test-location-id-1234', + expect.objectContaining({ + credentials: expect.any(Object), + }), + ); + }); + + it('should throw an error if catalog.removeLocationById throws an error', async () => { + const mockActionsRegistry = actionsRegistryServiceMock(); + const mockCatalog = catalogServiceMock(); + + const errorMessage = 'Failed to remove location'; + mockCatalog.removeLocationById = jest + .fn() + .mockRejectedValue(new Error(errorMessage)); + + createUnregisterCatalogEntitiesAction({ + catalog: mockCatalog, + actionsRegistry: mockActionsRegistry, + }); + + await expect( + mockActionsRegistry.invoke({ + id: 'test:unregister-entity', + input: { type: { locationId: 'test-location-id-1234' } }, + }), + ).rejects.toThrow(errorMessage); + }); + }); + + describe('with locationUrl', () => { + it('should successfully unregister a catalog location with a valid locationUrl', async () => { + const mockActionsRegistry = actionsRegistryServiceMock(); + const mockCatalog = catalogServiceMock(); + + const locationUrl = + 'https://github.com/backstage/demo/blob/master/catalog-info.yaml'; + + mockCatalog.getLocations = jest.fn().mockResolvedValue({ + items: [ + { id: 'location-id-1', target: locationUrl }, + { id: 'location-id-2', target: 'https://other-url.com/catalog.yaml' }, + ], + }); + mockCatalog.removeLocationById = jest.fn().mockResolvedValue(undefined); + + createUnregisterCatalogEntitiesAction({ + catalog: mockCatalog, + actionsRegistry: mockActionsRegistry, + }); + + const result = await mockActionsRegistry.invoke({ + id: 'test:unregister-entity', + input: { type: { locationUrl } }, + }); + + expect(result.output).toEqual({}); + expect(mockCatalog.getLocations).toHaveBeenCalledWith( + {}, + expect.objectContaining({ + credentials: expect.any(Object), + }), + ); + expect(mockCatalog.removeLocationById).toHaveBeenCalledTimes(1); + expect(mockCatalog.removeLocationById).toHaveBeenCalledWith( + 'location-id-1', + expect.objectContaining({ + credentials: expect.any(Object), + }), + ); + }); + + it('should match locationUrl case-insensitively', async () => { + const mockActionsRegistry = actionsRegistryServiceMock(); + const mockCatalog = catalogServiceMock(); + + mockCatalog.getLocations = jest.fn().mockResolvedValue({ + items: [ + { + id: 'location-id-1', + target: + 'https://github.com/Backstage/Demo/blob/master/catalog-info.yaml', + }, + ], + }); + mockCatalog.removeLocationById = jest.fn().mockResolvedValue(undefined); + + createUnregisterCatalogEntitiesAction({ + catalog: mockCatalog, + actionsRegistry: mockActionsRegistry, + }); + + const result = await mockActionsRegistry.invoke({ + id: 'test:unregister-entity', + input: { + type: { + locationUrl: + 'https://github.com/backstage/demo/blob/master/catalog-info.yaml', + }, + }, + }); + + expect(result.output).toEqual({}); + expect(mockCatalog.removeLocationById).toHaveBeenCalledTimes(1); + expect(mockCatalog.removeLocationById).toHaveBeenCalledWith( + 'location-id-1', + expect.objectContaining({ + credentials: expect.any(Object), + }), + ); + }); + + it('should unregister multiple locations with the same URL', async () => { + const mockActionsRegistry = actionsRegistryServiceMock(); + const mockCatalog = catalogServiceMock(); + + const locationUrl = + 'https://github.com/backstage/demo/blob/master/catalog-info.yaml'; + + mockCatalog.getLocations = jest.fn().mockResolvedValue({ + items: [ + { id: 'location-id-1', target: locationUrl }, + { id: 'location-id-2', target: locationUrl }, + ], + }); + mockCatalog.removeLocationById = jest.fn().mockResolvedValue(undefined); + + createUnregisterCatalogEntitiesAction({ + catalog: mockCatalog, + actionsRegistry: mockActionsRegistry, + }); + + const result = await mockActionsRegistry.invoke({ + id: 'test:unregister-entity', + input: { type: { locationUrl } }, + }); + + expect(result.output).toEqual({}); + expect(mockCatalog.removeLocationById).toHaveBeenCalledTimes(2); + expect(mockCatalog.removeLocationById).toHaveBeenNthCalledWith( + 1, + 'location-id-1', + expect.objectContaining({ + credentials: expect.any(Object), + }), + ); + expect(mockCatalog.removeLocationById).toHaveBeenNthCalledWith( + 2, + 'location-id-2', + expect.objectContaining({ + credentials: expect.any(Object), + }), + ); + }); + + it('should throw NotFoundError if no location matches the URL', async () => { + const mockActionsRegistry = actionsRegistryServiceMock(); + const mockCatalog = catalogServiceMock(); + + mockCatalog.getLocations = jest.fn().mockResolvedValue({ + items: [ + { id: 'location-id-1', target: 'https://other-url.com/catalog.yaml' }, + ], + }); + + createUnregisterCatalogEntitiesAction({ + catalog: mockCatalog, + actionsRegistry: mockActionsRegistry, + }); + + await expect( + mockActionsRegistry.invoke({ + id: 'test:unregister-entity', + input: { + type: { + locationUrl: + 'https://github.com/backstage/demo/blob/master/catalog-info.yaml', + }, + }, + }), + ).rejects.toThrow(/NotFoundError/); + }); + + it('should throw NotFoundError with descriptive message when location not found', async () => { + const mockActionsRegistry = actionsRegistryServiceMock(); + const mockCatalog = catalogServiceMock(); + + const locationUrl = + 'https://github.com/backstage/demo/blob/master/catalog-info.yaml'; + + mockCatalog.getLocations = jest.fn().mockResolvedValue({ + items: [], + }); + + createUnregisterCatalogEntitiesAction({ + catalog: mockCatalog, + actionsRegistry: mockActionsRegistry, + }); + + await expect( + mockActionsRegistry.invoke({ + id: 'test:unregister-entity', + input: { type: { locationUrl } }, + }), + ).rejects.toThrow(`Location with URL ${locationUrl} not found`); + }); + + it('should throw an error if catalog.getLocations throws an error', async () => { + const mockActionsRegistry = actionsRegistryServiceMock(); + const mockCatalog = catalogServiceMock(); + + const errorMessage = 'Failed to get locations'; + mockCatalog.getLocations = jest + .fn() + .mockRejectedValue(new Error(errorMessage)); + + createUnregisterCatalogEntitiesAction({ + catalog: mockCatalog, + actionsRegistry: mockActionsRegistry, + }); + + await expect( + mockActionsRegistry.invoke({ + id: 'test:unregister-entity', + input: { + type: { + locationUrl: + 'https://github.com/backstage/demo/blob/master/catalog-info.yaml', + }, + }, + }), + ).rejects.toThrow(errorMessage); + }); + }); +}); diff --git a/plugins/catalog-backend/src/actions/createUnregisterCatalogEntitiesAction.ts b/plugins/catalog-backend/src/actions/createUnregisterCatalogEntitiesAction.ts new file mode 100644 index 0000000000..542fc79ac5 --- /dev/null +++ b/plugins/catalog-backend/src/actions/createUnregisterCatalogEntitiesAction.ts @@ -0,0 +1,102 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { ActionsRegistryService } from '@backstage/backend-plugin-api/alpha'; +import { NotFoundError } from '@backstage/errors'; +import { CatalogService } from '@backstage/plugin-catalog-node'; + +export const createUnregisterCatalogEntitiesAction = ({ + catalog, + actionsRegistry, +}: { + catalog: CatalogService; + actionsRegistry: ActionsRegistryService; +}) => { + actionsRegistry.register({ + name: 'unregister-entity', + title: 'Unregister entity from the Catalog', + attributes: { + destructive: true, + readOnly: false, + idempotent: true, + }, + description: `Unregisters a Location entity and all entities it owns from the Backstage catalog. + +This action is similar to the "Unregister location" function in the Backstage UI, where you provide the unique identifier (locationId) of a Location entity. Alternatively, you can provide the URL used to register the location. The action will remove the specified Location from the catalog as well as all entities that were created when the Location was imported. + +Once completed, all entities associated with the Location will be deleted from the catalog. +`, + schema: { + input: z => + z + .object({ + type: z.union([ + z.object({ + locationId: z + .string() + .describe(`Location ID of the Entity to unregister`), + }), + z.object({ + locationUrl: z + .string() + .describe( + `URL of the catalog-info.yaml file to unregister for example: https://github.com/backstage/demo/blob/master/catalog-info.yaml`, + ), + }), + ]), + }) + .describe( + 'The type to the unregister-entity action. Either locationId or locationUrl must be provided.', + ), + output: z => z.object({}), + }, + action: async ({ input: { type }, credentials }) => { + if ('locationId' in type) { + await catalog.removeLocationById(type.locationId, { + credentials, + }); + } else { + const locations = await catalog + .getLocations( + {}, + { + credentials, + }, + ) + .then(response => + response.items.filter( + location => + location.target.toLowerCase() === + type.locationUrl.toLowerCase(), + ), + ); + + if (locations.length === 0) { + throw new NotFoundError( + `Location with URL ${type.locationUrl} not found`, + ); + } + + for (const location of locations) { + await catalog.removeLocationById(location.id, { + credentials, + }); + } + } + + return { output: {} }; + }, + }); +}; diff --git a/plugins/catalog-backend/src/actions/index.ts b/plugins/catalog-backend/src/actions/index.ts index c53f956f62..5940bc32f1 100644 --- a/plugins/catalog-backend/src/actions/index.ts +++ b/plugins/catalog-backend/src/actions/index.ts @@ -17,6 +17,8 @@ import { ActionsRegistryService } from '@backstage/backend-plugin-api/alpha'; import { CatalogService } from '@backstage/plugin-catalog-node'; import { createGetCatalogEntityAction } from './createGetCatalogEntityAction.ts'; import { createValidateEntityAction } from './createValidateEntityAction.ts'; +import { createRegisterCatalogEntitiesAction } from './createRegisterCatalogEntitiesAction.ts'; +import { createUnregisterCatalogEntitiesAction } from './createUnregisterCatalogEntitiesAction.ts'; export const createCatalogActions = (options: { actionsRegistry: ActionsRegistryService; @@ -24,4 +26,6 @@ export const createCatalogActions = (options: { }) => { createGetCatalogEntityAction(options); createValidateEntityAction(options); + createRegisterCatalogEntitiesAction(options); + createUnregisterCatalogEntitiesAction(options); }; diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts index e9d00f3451..7012c2e505 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts @@ -1577,10 +1577,11 @@ describe('DefaultEntitiesCatalog', () => { totalItems: 0, items: { type: 'raw', - entities: expect.objectContaining({ length: 10 }), + entities: expect.any(Array), }, pageInfo: { nextCursor: expect.anything() }, }); + expect(response.items.entities).toHaveLength(10); response = await catalog.queryEntities({ ...request, cursor: response.pageInfo.nextCursor!, @@ -1589,10 +1590,11 @@ describe('DefaultEntitiesCatalog', () => { totalItems: 0, items: { type: 'raw', - entities: expect.objectContaining({ length: 5 }), + entities: expect.any(Array), }, pageInfo: { prevCursor: expect.anything() }, }); + expect(response.items.entities).toHaveLength(5); }, ); diff --git a/plugins/catalog-backend/src/service/DefaultRefreshService.ts b/plugins/catalog-backend/src/service/DefaultRefreshService.ts index 99b78f900b..45a8f27c6e 100644 --- a/plugins/catalog-backend/src/service/DefaultRefreshService.ts +++ b/plugins/catalog-backend/src/service/DefaultRefreshService.ts @@ -29,20 +29,17 @@ export class DefaultRefreshService implements RefreshService { const { entityRefs } = await this.database.listAncestors(tx, { entityRef: options.entityRef, }); - const locationAncestor = entityRefs.find(ref => + + const locationAncestors = entityRefs.filter(ref => ref.startsWith('location:'), ); // TODO: Refreshes are currently scheduled(as soon as possible) for execution and will therefore happen in the future. // There's room for improvements here where the refresh could potentially hang or return an ID so that the user can check progress. - if (locationAncestor) { - await this.database.refresh(tx, { - entityRef: locationAncestor, - }); + for (const locationAncestor of locationAncestors) { + await this.database.refresh(tx, { entityRef: locationAncestor }); } - await this.database.refresh(tx, { - entityRef: options.entityRef, - }); + await this.database.refresh(tx, { entityRef: options.entityRef }); }); } } diff --git a/plugins/catalog-backend/src/service/response/write.test.ts b/plugins/catalog-backend/src/service/response/write.test.ts index d60d1c3526..25aaa33aa1 100644 --- a/plugins/catalog-backend/src/service/response/write.test.ts +++ b/plugins/catalog-backend/src/service/response/write.test.ts @@ -327,9 +327,10 @@ describe('writeEntitiesResponse', () => { expect(res.header['content-length']).not.toBeDefined(); expect(res.body).toEqual({ page: 1, - items: expect.objectContaining({ length: 300 }), + items: expect.any(Array), totalItems: 1337, }); + expect(res.body.items).toHaveLength(300); }); }); @@ -438,9 +439,10 @@ describe('writeEntitiesResponse', () => { expect(res.header['content-length']).toBeDefined(); expect(res.body).toEqual({ page: 1, - items: expect.objectContaining({ length: 300 }), + items: expect.any(Array), totalItems: 1337, }); + expect(res.body.items).toHaveLength(300); }); }); }); diff --git a/plugins/catalog-graph/CHANGELOG.md b/plugins/catalog-graph/CHANGELOG.md index 759f4fbb7c..b97ea7d6a2 100644 --- a/plugins/catalog-graph/CHANGELOG.md +++ b/plugins/catalog-graph/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-catalog-graph +## 0.5.4 + +### Patch Changes + +- a67c144: Fixed zoom out description (replace `&` with &) +- f3f84f1: Minor extension type updates after frontend API bump +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/core-plugin-api@1.12.1 + +## 0.5.4-next.1 + +### Patch Changes + +- f3f84f1: Minor extension type updates after frontend API bump +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2-next.1 + - @backstage/plugin-catalog-react@1.21.4-next.2 + - @backstage/core-components@0.18.4-next.2 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/types@1.2.2 + ## 0.5.4-next.0 ### Patch Changes diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index fb28ba1a27..64b4331356 100644 --- a/plugins/catalog-graph/package.json +++ b/plugins/catalog-graph/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-graph", - "version": "0.5.4-next.0", + "version": "0.5.4", "backstage": { "role": "frontend-plugin", "pluginId": "catalog-graph", diff --git a/plugins/catalog-import/CHANGELOG.md b/plugins/catalog-import/CHANGELOG.md index b549bb0b85..9e25364a9c 100644 --- a/plugins/catalog-import/CHANGELOG.md +++ b/plugins/catalog-import/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-catalog-import +## 0.13.8 + +### Patch Changes + +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/integration-react@1.2.13 + - @backstage/plugin-permission-react@0.4.39 + ## 0.13.8-next.0 ### Patch Changes diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index f18c00afa2..e9d25876af 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-import", - "version": "0.13.8-next.0", + "version": "0.13.8", "description": "A Backstage plugin the helps you import entities into your catalog", "backstage": { "role": "frontend-plugin", diff --git a/plugins/catalog-node/CHANGELOG.md b/plugins/catalog-node/CHANGELOG.md index 018df720cd..112e1cfca2 100644 --- a/plugins/catalog-node/CHANGELOG.md +++ b/plugins/catalog-node/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-catalog-node +## 1.20.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-node@0.10.7 + - @backstage/backend-plugin-api@1.6.0 + +## 1.20.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-node@0.10.7-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-permission-common@0.9.3 + ## 1.20.1-next.0 ### Patch Changes diff --git a/plugins/catalog-node/package.json b/plugins/catalog-node/package.json index d083c08d34..befa4e9b7f 100644 --- a/plugins/catalog-node/package.json +++ b/plugins/catalog-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-node", - "version": "1.20.1-next.0", + "version": "1.20.1", "description": "The plugin-catalog-node module for @backstage/plugin-catalog-backend", "backstage": { "role": "node-library", diff --git a/plugins/catalog-react/CHANGELOG.md b/plugins/catalog-react/CHANGELOG.md index 8d0b154915..c66c5767ae 100644 --- a/plugins/catalog-react/CHANGELOG.md +++ b/plugins/catalog-react/CHANGELOG.md @@ -1,5 +1,43 @@ # @backstage/plugin-catalog-react +## 1.21.4 + +### Patch Changes + +- 6d39141: Fixed an issue where `EntityOwnerPicker` failed to filter options when the input text contained uppercase characters. +- b3c0594: Use a versioned context for `useEntityList`, to better work with mixed `@backstage/plugin-catalog-react` versions. +- c51c901: $contains may have string value in an entity filter. Typescript type and Zod parser were not the same. +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/core-compat-api@0.5.5 + - @backstage/frontend-test-utils@0.4.2 + - @backstage/integration-react@1.2.13 + - @backstage/plugin-permission-react@0.4.39 + +## 1.21.4-next.2 + +### Patch Changes + +- b3c0594: Use a versioned context for `useEntityList`, to better work with mixed `@backstage/plugin-catalog-react` versions. +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2-next.1 + - @backstage/core-components@0.18.4-next.2 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/core-compat-api@0.5.5-next.0 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/errors@1.2.7 + - @backstage/frontend-test-utils@0.4.2-next.0 + - @backstage/integration-react@1.2.13-next.0 + - @backstage/types@1.2.2 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-permission-common@0.9.3 + - @backstage/plugin-permission-react@0.4.39-next.0 + ## 1.21.4-next.1 ### Patch Changes diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index 013d1e7629..bfd4e11738 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-react", - "version": "1.21.4-next.1", + "version": "1.21.4", "description": "A frontend library that helps other Backstage plugins interact with the catalog", "backstage": { "role": "web-library", diff --git a/plugins/catalog-react/report-alpha.api.md b/plugins/catalog-react/report-alpha.api.md index 3f2ed575b4..22ac105eeb 100644 --- a/plugins/catalog-react/report-alpha.api.md +++ b/plugins/catalog-react/report-alpha.api.md @@ -549,7 +549,7 @@ export type EntityPredicateValue = $in: EntityPredicatePrimitive[]; } | { - $contains: EntityPredicateExpression; + $contains: EntityPredicate; }; // @alpha (undocumented) diff --git a/plugins/catalog-react/src/alpha/blueprints/EntityCardBlueprint.test.tsx b/plugins/catalog-react/src/alpha/blueprints/EntityCardBlueprint.test.tsx index 3c9a020c93..af04673ad1 100644 --- a/plugins/catalog-react/src/alpha/blueprints/EntityCardBlueprint.test.tsx +++ b/plugins/catalog-react/src/alpha/blueprints/EntityCardBlueprint.test.tsx @@ -60,20 +60,75 @@ describe('EntityCardBlueprint', () => { { "anyOf": [ { - "type": [ - "string", - "number", - "boolean", - ], + "additionalProperties": { + "anyOf": [ + { + "type": [ + "string", + "number", + "boolean", + ], + }, + { + "additionalProperties": false, + "properties": { + "$exists": { + "type": "boolean", + }, + }, + "required": [ + "$exists", + ], + "type": "object", + }, + { + "additionalProperties": false, + "properties": { + "$in": { + "items": { + "$ref": "#/properties/filter/anyOf/1/anyOf/0/anyOf/0/additionalProperties/anyOf/0", + }, + "type": "array", + }, + }, + "required": [ + "$in", + ], + "type": "object", + }, + { + "additionalProperties": false, + "properties": { + "$contains": { + "$ref": "#/properties/filter/anyOf/1", + }, + }, + "required": [ + "$contains", + ], + "type": "object", + }, + ], + }, + "propertyNames": { + "pattern": "^(?!\\$).*$", + }, + "type": "object", }, { - "items": { - "$ref": "#/properties/filter/anyOf/1/anyOf/0/anyOf/0", + "additionalProperties": { + "not": {}, }, - "type": "array", + "propertyNames": { + "pattern": "^\\$", + }, + "type": "object", }, ], }, + { + "$ref": "#/properties/filter/anyOf/1/anyOf/0/anyOf/0/additionalProperties/anyOf/0", + }, { "additionalProperties": false, "properties": { @@ -116,58 +171,6 @@ describe('EntityCardBlueprint', () => { ], "type": "object", }, - { - "additionalProperties": { - "anyOf": [ - { - "$ref": "#/properties/filter/anyOf/1/anyOf/0", - }, - { - "additionalProperties": false, - "properties": { - "$exists": { - "type": "boolean", - }, - }, - "required": [ - "$exists", - ], - "type": "object", - }, - { - "additionalProperties": false, - "properties": { - "$in": { - "items": { - "$ref": "#/properties/filter/anyOf/1/anyOf/0/anyOf/0", - }, - "type": "array", - }, - }, - "required": [ - "$in", - ], - "type": "object", - }, - { - "additionalProperties": false, - "properties": { - "$contains": { - "$ref": "#/properties/filter/anyOf/1", - }, - }, - "required": [ - "$contains", - ], - "type": "object", - }, - ], - }, - "propertyNames": { - "pattern": "^(?!\\$).*$", - }, - "type": "object", - }, ], }, ], diff --git a/plugins/catalog-react/src/alpha/blueprints/EntityContentBlueprint.test.tsx b/plugins/catalog-react/src/alpha/blueprints/EntityContentBlueprint.test.tsx index 729f15079f..e80834be92 100644 --- a/plugins/catalog-react/src/alpha/blueprints/EntityContentBlueprint.test.tsx +++ b/plugins/catalog-react/src/alpha/blueprints/EntityContentBlueprint.test.tsx @@ -62,20 +62,75 @@ describe('EntityContentBlueprint', () => { { "anyOf": [ { - "type": [ - "string", - "number", - "boolean", - ], + "additionalProperties": { + "anyOf": [ + { + "type": [ + "string", + "number", + "boolean", + ], + }, + { + "additionalProperties": false, + "properties": { + "$exists": { + "type": "boolean", + }, + }, + "required": [ + "$exists", + ], + "type": "object", + }, + { + "additionalProperties": false, + "properties": { + "$in": { + "items": { + "$ref": "#/properties/filter/anyOf/1/anyOf/0/anyOf/0/additionalProperties/anyOf/0", + }, + "type": "array", + }, + }, + "required": [ + "$in", + ], + "type": "object", + }, + { + "additionalProperties": false, + "properties": { + "$contains": { + "$ref": "#/properties/filter/anyOf/1", + }, + }, + "required": [ + "$contains", + ], + "type": "object", + }, + ], + }, + "propertyNames": { + "pattern": "^(?!\\$).*$", + }, + "type": "object", }, { - "items": { - "$ref": "#/properties/filter/anyOf/1/anyOf/0/anyOf/0", + "additionalProperties": { + "not": {}, }, - "type": "array", + "propertyNames": { + "pattern": "^\\$", + }, + "type": "object", }, ], }, + { + "$ref": "#/properties/filter/anyOf/1/anyOf/0/anyOf/0/additionalProperties/anyOf/0", + }, { "additionalProperties": false, "properties": { @@ -118,58 +173,6 @@ describe('EntityContentBlueprint', () => { ], "type": "object", }, - { - "additionalProperties": { - "anyOf": [ - { - "$ref": "#/properties/filter/anyOf/1/anyOf/0", - }, - { - "additionalProperties": false, - "properties": { - "$exists": { - "type": "boolean", - }, - }, - "required": [ - "$exists", - ], - "type": "object", - }, - { - "additionalProperties": false, - "properties": { - "$in": { - "items": { - "$ref": "#/properties/filter/anyOf/1/anyOf/0/anyOf/0", - }, - "type": "array", - }, - }, - "required": [ - "$in", - ], - "type": "object", - }, - { - "additionalProperties": false, - "properties": { - "$contains": { - "$ref": "#/properties/filter/anyOf/1", - }, - }, - "required": [ - "$contains", - ], - "type": "object", - }, - ], - }, - "propertyNames": { - "pattern": "^(?!\\$).*$", - }, - "type": "object", - }, ], }, ], diff --git a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx index 55598f5de1..d92fcc1863 100644 --- a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx +++ b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx @@ -73,20 +73,75 @@ describe('EntityContextMenuItemBlueprint', () => { { "anyOf": [ { - "type": [ - "string", - "number", - "boolean", - ], + "additionalProperties": { + "anyOf": [ + { + "type": [ + "string", + "number", + "boolean", + ], + }, + { + "additionalProperties": false, + "properties": { + "$exists": { + "type": "boolean", + }, + }, + "required": [ + "$exists", + ], + "type": "object", + }, + { + "additionalProperties": false, + "properties": { + "$in": { + "items": { + "$ref": "#/properties/filter/anyOf/0/anyOf/0/additionalProperties/anyOf/0", + }, + "type": "array", + }, + }, + "required": [ + "$in", + ], + "type": "object", + }, + { + "additionalProperties": false, + "properties": { + "$contains": { + "$ref": "#/properties/filter", + }, + }, + "required": [ + "$contains", + ], + "type": "object", + }, + ], + }, + "propertyNames": { + "pattern": "^(?!\\$).*$", + }, + "type": "object", }, { - "items": { - "$ref": "#/properties/filter/anyOf/0/anyOf/0", + "additionalProperties": { + "not": {}, }, - "type": "array", + "propertyNames": { + "pattern": "^\\$", + }, + "type": "object", }, ], }, + { + "$ref": "#/properties/filter/anyOf/0/anyOf/0/additionalProperties/anyOf/0", + }, { "additionalProperties": false, "properties": { @@ -129,58 +184,6 @@ describe('EntityContextMenuItemBlueprint', () => { ], "type": "object", }, - { - "additionalProperties": { - "anyOf": [ - { - "$ref": "#/properties/filter/anyOf/0", - }, - { - "additionalProperties": false, - "properties": { - "$exists": { - "type": "boolean", - }, - }, - "required": [ - "$exists", - ], - "type": "object", - }, - { - "additionalProperties": false, - "properties": { - "$in": { - "items": { - "$ref": "#/properties/filter/anyOf/0/anyOf/0", - }, - "type": "array", - }, - }, - "required": [ - "$in", - ], - "type": "object", - }, - { - "additionalProperties": false, - "properties": { - "$contains": { - "$ref": "#/properties/filter", - }, - }, - "required": [ - "$contains", - ], - "type": "object", - }, - ], - }, - "propertyNames": { - "pattern": "^(?!\\$).*$", - }, - "type": "object", - }, ], }, }, diff --git a/plugins/catalog-react/src/alpha/predicates/createEntityPredicateSchema.test.ts b/plugins/catalog-react/src/alpha/predicates/createEntityPredicateSchema.test.ts index 4fdf921c1a..3553fa932b 100644 --- a/plugins/catalog-react/src/alpha/predicates/createEntityPredicateSchema.test.ts +++ b/plugins/catalog-react/src/alpha/predicates/createEntityPredicateSchema.test.ts @@ -16,84 +16,100 @@ import { z } from 'zod'; import { createEntityPredicateSchema } from './createEntityPredicateSchema'; +import { EntityPredicate } from './types'; describe('createEntityPredicateSchema', () => { const schema = createEntityPredicateSchema(z); - it.each([ - 'string', - '', - [], - 1, - { kind: 'component', 'spec.type': 'service' }, - { 'metadata.tags': { $in: ['java'] } }, - { - $all: [ - { 'metadata.tags': { $contains: 'java' } }, - { 'metadata.tags': { $contains: 'spring' } }, - ], - }, - { 'metadata.tags': ['java', 'spring'] }, - { 'metadata.tags': { $in: ['go'] } }, - { 'metadata.tags.0': 'java' }, - { $not: { 'metadata.tags': { $in: ['java'] } } }, - { - $any: [{ kind: 'component', 'spec.type': 'service' }, { kind: 'group' }], - }, - { - relations: { - $contains: { type: 'ownedBy', targetRef: 'group:default/g' }, + describe('valid predicates', () => { + const predicates: EntityPredicate[] = [ + 'string', + '', + 1, + { kind: 'component', 'spec.type': 'service' }, + { 'metadata.tags': { $in: ['java'] } }, + { 'metadata.tags': { $contains: 'java' } }, + { + $all: [ + { 'metadata.tags': { $contains: 'java' } }, + { 'metadata.tags': { $contains: 'spring' } }, + ], }, - }, - { - metadata: { $contains: { name: 'a' } }, - }, - { kind: 'component', 'spec.type': { $in: ['service', 'website'] } }, - { - $any: [ - { - $all: [ - { - kind: 'component', - 'spec.type': { $in: ['service', 'website'] }, - }, - ], + { 'metadata.tags': { $in: ['go'] } }, + { 'metadata.tags.0': 'java' }, + { $not: { 'metadata.tags': { $in: ['java'] } } }, + { + $any: [ + { kind: 'component', 'spec.type': 'service' }, + { kind: 'group' }, + ], + }, + { + relations: { + $contains: { type: 'ownedBy', targetRef: 'group:default/g' }, }, - { $all: [{ kind: 'api', 'spec.type': 'grpc' }] }, - ], - }, - { kind: 'component', 'spec.type': { $in: ['service'] } }, - { 'spec.owner': { $exists: true } }, - { 'spec.owner': { $exists: false } }, - { 'spec.type': 'service' }, - { $not: { 'spec.type': 'service' } }, - { - kind: 'component', - 'metadata.annotations.github.com/repo': { $exists: true }, - }, - { $all: [{ x: { $exists: true } }] }, - { $any: [{ x: { $exists: true } }] }, - { $not: { x: { $exists: true } } }, - { $not: { $all: [{ x: { $exists: true } }] } }, - ])('should accept valid predicate %j', predicate => { - expect(schema.parse(predicate)).toEqual(predicate); + }, + { + metadata: { $contains: { name: 'a' } }, + }, + { kind: 'component', 'spec.type': { $in: ['service', 'website'] } }, + { + $any: [ + { + $all: [ + { + kind: 'component', + 'spec.type': { $in: ['service', 'website'] }, + }, + ], + }, + { $all: [{ kind: 'api', 'spec.type': 'grpc' }] }, + ], + }, + { kind: 'component', 'spec.type': { $in: ['service'] } }, + { 'spec.owner': { $exists: true } }, + { 'spec.owner': { $exists: false } }, + { 'spec.type': 'service' }, + { $not: { 'spec.type': 'service' } }, + { + kind: 'component', + 'metadata.annotations.github.com/repo': { $exists: true }, + }, + { $all: [{ x: { $exists: true } }] }, + { $any: [{ x: { $exists: true } }] }, + { $not: { x: { $exists: true } } }, + { $not: { $all: [{ x: { $exists: true } }] } }, + ]; + + it.each(predicates)('should accept valid predicate %j', predicate => { + expect(schema.parse(predicate)).toEqual(predicate); + }); }); - it.each([ - { kind: { 1: 'foo' } }, - { kind: { foo: 'bar' } }, - { kind: { $unknown: 'foo' } }, - { kind: { $in: 'foo' } }, - { kind: { $in: [{ x: 'foo' }] } }, - { kind: { $in: [{ x: 'foo' }] } }, - { 'spec.type': null }, - { $all: [{ x: { $unknown: true } }] }, - { $any: [{ x: { $unknown: true } }] }, - { $not: { x: { $unknown: true } } }, - { $not: { $all: [{ x: { $unknown: true } }] } }, - { $unknown: 'foo' }, - ])('should reject invalid predicate %j', predicate => { - const result = schema.safeParse(predicate); - expect(result.success).toBe(false); + describe('invalid predicates', () => { + const predicates: Array< + Exclude + > = [ + [], + ['foo', 'bar'], + { kind: { 1: 'foo' } }, + { kind: { foo: 'bar' } }, + { kind: { $unknown: 'foo' } }, + { kind: { $in: 'foo' } }, + { kind: { $in: [{ x: 'foo' }] } }, + { kind: { $in: [{ x: 'foo' }] } }, + { 'spec.type': null }, + { $all: [{ x: { $unknown: true } }] }, + { $any: [{ x: { $unknown: true } }] }, + { $not: { x: { $unknown: true } } }, + { $not: { $all: [{ x: { $unknown: true } }] } }, + { $unknown: 'foo' }, + { 'metadata.tags': ['foo', 'bar'] }, + ]; + + it.each(predicates)('should reject invalid predicate %j', predicate => { + const result = schema.safeParse(predicate); + expect(result.success).toBe(false); + }); }); }); diff --git a/plugins/catalog-react/src/alpha/predicates/createEntityPredicateSchema.ts b/plugins/catalog-react/src/alpha/predicates/createEntityPredicateSchema.ts index cfd2e451df..3e31ec4d35 100644 --- a/plugins/catalog-react/src/alpha/predicates/createEntityPredicateSchema.ts +++ b/plugins/catalog-react/src/alpha/predicates/createEntityPredicateSchema.ts @@ -14,33 +14,44 @@ * limitations under the License. */ -import { EntityPredicate, EntityPredicateValue } from './types'; +import { + EntityPredicate, + EntityPredicateExpression, + EntityPredicatePrimitive, + EntityPredicateValue, +} from './types'; import type { z as zImpl, ZodType } from 'zod'; /** @internal */ export function createEntityPredicateSchema(z: typeof zImpl) { - const primitiveSchema = z.union([z.string(), z.number(), z.boolean()]); - - const comparableValueSchema = z.union([ - primitiveSchema, - z.array(primitiveSchema), - ]); + const primitiveSchema = z.union([ + z.string(), + z.number(), + z.boolean(), + ]) as ZodType; // eslint-disable-next-line prefer-const let valuePredicateSchema: ZodType; + const expressionSchema = z.lazy(() => + z.union([ + z.record(z.string().regex(/^(?!\$).*$/), valuePredicateSchema), + z.record(z.string().regex(/^\$/), z.never()), + ]), + ) as ZodType; + const predicateSchema = z.lazy(() => z.union([ - comparableValueSchema, + expressionSchema, + primitiveSchema, z.object({ $all: z.array(predicateSchema) }), z.object({ $any: z.array(predicateSchema) }), z.object({ $not: predicateSchema }), - z.record(z.string().regex(/^(?!\$).*$/), valuePredicateSchema), ]), ) as ZodType; valuePredicateSchema = z.union([ - comparableValueSchema, + primitiveSchema, z.object({ $exists: z.boolean() }), z.object({ $in: z.array(primitiveSchema) }), z.object({ $contains: predicateSchema }), diff --git a/plugins/catalog-react/src/alpha/predicates/types.ts b/plugins/catalog-react/src/alpha/predicates/types.ts index a4a2e9199f..f19026c01b 100644 --- a/plugins/catalog-react/src/alpha/predicates/types.ts +++ b/plugins/catalog-react/src/alpha/predicates/types.ts @@ -34,7 +34,7 @@ export type EntityPredicateValue = | EntityPredicatePrimitive | { $exists: boolean } | { $in: EntityPredicatePrimitive[] } - | { $contains: EntityPredicateExpression }; + | { $contains: EntityPredicate }; /** @alpha */ export type EntityPredicatePrimitive = string | number | boolean; diff --git a/plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.test.tsx b/plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.test.tsx index 0ba231b72a..07eaa479fd 100644 --- a/plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.test.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.test.tsx @@ -68,15 +68,15 @@ describe('useAllEntitiesCount', () => { ), }); - await waitFor(() => + await waitFor(() => { expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ filter: { 'relations.ownedBy': ['user:default/owner'], }, limit: 0, - }), - ); - expect(result.current).toEqual({ count: 10, loading: false }); + }); + expect(result.current).toEqual({ count: 10, loading: false }); + }); }); it(`shouldn't invoke the endpoint at startup, when filters are missing`, async () => { diff --git a/plugins/catalog-unprocessed-entities-common/CHANGELOG.md b/plugins/catalog-unprocessed-entities-common/CHANGELOG.md index 67dfa74dae..2a9cca8511 100644 --- a/plugins/catalog-unprocessed-entities-common/CHANGELOG.md +++ b/plugins/catalog-unprocessed-entities-common/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-catalog-unprocessed-entities-common +## 0.0.12 + +### Patch Changes + +- df4d646: Moved types, API and client to the common package, allowing both frontend and + backend plugins to use the `CatalogUnprocessedEntitiesClient`. + + The following types, clients and interfaces have been deprecated and should be + imported from the `@backstage/plugin-catalog-unprocessed-entities-common` instead: + `CatalogUnprocessedEntitiesApi`, `CatalogUnprocessedEntitiesApiResponse`, `UnprocessedEntity`, + `UnprocessedEntityCache`, `UnprocessedEntityError`, `CatalogUnprocessedEntitiesClient`. + + All those types, clients and interfaces are re-exported temporarily in the + `@backstage/plugin-catalog-unprocessed-entities` package until cleaned up. + ## 0.0.12-next.0 ### Patch Changes diff --git a/plugins/catalog-unprocessed-entities-common/package.json b/plugins/catalog-unprocessed-entities-common/package.json index c20e1c142a..58423cad91 100644 --- a/plugins/catalog-unprocessed-entities-common/package.json +++ b/plugins/catalog-unprocessed-entities-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-unprocessed-entities-common", - "version": "0.0.12-next.0", + "version": "0.0.12", "description": "Common functionalities for the catalog-unprocessed-entities plugin", "backstage": { "role": "common-library", diff --git a/plugins/catalog-unprocessed-entities/CHANGELOG.md b/plugins/catalog-unprocessed-entities/CHANGELOG.md index b48f12b4dd..47be6beb8b 100644 --- a/plugins/catalog-unprocessed-entities/CHANGELOG.md +++ b/plugins/catalog-unprocessed-entities/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-catalog-unprocessed-entities +## 0.2.24 + +### Patch Changes + +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- df4d646: Moved types, API and client to the common package, allowing both frontend and + backend plugins to use the `CatalogUnprocessedEntitiesClient`. + + The following types, clients and interfaces have been deprecated and should be + imported from the `@backstage/plugin-catalog-unprocessed-entities-common` instead: + `CatalogUnprocessedEntitiesApi`, `CatalogUnprocessedEntitiesApiResponse`, `UnprocessedEntity`, + `UnprocessedEntityCache`, `UnprocessedEntityError`, `CatalogUnprocessedEntitiesClient`. + + All those types, clients and interfaces are re-exported temporarily in the + `@backstage/plugin-catalog-unprocessed-entities` package until cleaned up. + +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/plugin-catalog-unprocessed-entities-common@0.0.12 + ## 0.2.24-next.1 ### Patch Changes diff --git a/plugins/catalog-unprocessed-entities/package.json b/plugins/catalog-unprocessed-entities/package.json index 0e8620df80..79dc840a03 100644 --- a/plugins/catalog-unprocessed-entities/package.json +++ b/plugins/catalog-unprocessed-entities/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-unprocessed-entities", - "version": "0.2.24-next.1", + "version": "0.2.24", "backstage": { "role": "frontend-plugin", "pluginId": "catalog-unprocessed-entities", @@ -50,6 +50,7 @@ "test": "backstage-cli package test" }, "dependencies": { + "@backstage/core-compat-api": "workspace:^", "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", "@backstage/errors": "workspace:^", diff --git a/plugins/catalog/CHANGELOG.md b/plugins/catalog/CHANGELOG.md index 32dd520819..89f9bcdefe 100644 --- a/plugins/catalog/CHANGELOG.md +++ b/plugins/catalog/CHANGELOG.md @@ -1,5 +1,50 @@ # @backstage/plugin-catalog +## 1.32.1 + +### Patch Changes + +- f3f84f1: Minor extension type updates after frontend API bump +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- 91f5ed8: Fixed `catalogAboutEntityCard` to filter icon links before calling useProps(), preventing side effects from hooks in filtered-out links +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/plugin-search-react@1.10.1 + - @backstage/core-plugin-api@1.12.1 + - @backstage/core-compat-api@0.5.5 + - @backstage/integration-react@1.2.13 + - @backstage/plugin-permission-react@0.4.39 + - @backstage/plugin-scaffolder-common@1.7.4 + - @backstage/plugin-techdocs-react@1.3.6 + +## 1.32.1-next.1 + +### Patch Changes + +- f3f84f1: Minor extension type updates after frontend API bump +- 91f5ed8: Fixed `catalogAboutEntityCard` to filter icon links before calling useProps(), preventing side effects from hooks in filtered-out links +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2-next.1 + - @backstage/plugin-catalog-react@1.21.4-next.2 + - @backstage/core-components@0.18.4-next.2 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/core-compat-api@0.5.5-next.0 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/errors@1.2.7 + - @backstage/integration-react@1.2.13-next.0 + - @backstage/types@1.2.2 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-permission-react@0.4.39-next.0 + - @backstage/plugin-scaffolder-common@1.7.4-next.0 + - @backstage/plugin-search-common@1.2.21 + - @backstage/plugin-search-react@1.10.1-next.0 + - @backstage/plugin-techdocs-common@0.1.1 + - @backstage/plugin-techdocs-react@1.3.6-next.0 + ## 1.32.1-next.0 ### Patch Changes diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 3901b11b29..f2e4e1f610 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog", - "version": "1.32.1-next.0", + "version": "1.32.1", "description": "The Backstage plugin for browsing the Backstage catalog", "backstage": { "role": "frontend-plugin", diff --git a/plugins/catalog/src/alpha/pages.test.tsx b/plugins/catalog/src/alpha/pages.test.tsx index cc83b9168b..0b35e63979 100644 --- a/plugins/catalog/src/alpha/pages.test.tsx +++ b/plugins/catalog/src/alpha/pages.test.tsx @@ -721,18 +721,27 @@ describe('Entity page', () => { ); const { disabled } = params.useProps(); - await waitFor(async () => { - await userEvent.click(screen.getByTestId('menu-button')); - expect(screen.getByText('Test Title')).toBeInTheDocument(); - expect(screen.getByText('Test Icon')).toBeInTheDocument(); - const listItem = screen.getByText('Test Title').closest('li'); - expect(listItem).toHaveAttribute('aria-disabled', disabled.toString()); - if (!disabled) { - await userEvent.click(screen.getByText('Test Title')); - } - expect(onClickMock).toHaveBeenCalledTimes(disabled ? 0 : 1); - }); + // Wait for entity to load first + await waitFor(() => + expect(screen.getByText(/artist-lookup/)).toBeInTheDocument(), + ); + + await userEvent.click(screen.getByTestId('menu-button')); + + // Wait for menu to open + await waitFor(() => + expect(screen.getByText('Test Title')).toBeInTheDocument(), + ); + + expect(screen.getByText('Test Icon')).toBeInTheDocument(); + const listItem = screen.getByText('Test Title').closest('li'); + expect(listItem).toHaveAttribute('aria-disabled', disabled.toString()); + if (!disabled) { + await userEvent.click(screen.getByText('Test Title')); + } + + expect(onClickMock).toHaveBeenCalledTimes(disabled ? 0 : 1); }); it.each([ diff --git a/plugins/config-schema/CHANGELOG.md b/plugins/config-schema/CHANGELOG.md index 2dba805a25..1329d91732 100644 --- a/plugins/config-schema/CHANGELOG.md +++ b/plugins/config-schema/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-config-schema +## 0.1.75 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + ## 0.1.75-next.0 ### Patch Changes diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index 1018d9baab..46b051aca6 100644 --- a/plugins/config-schema/package.json +++ b/plugins/config-schema/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-config-schema", - "version": "0.1.75-next.0", + "version": "0.1.75", "description": "A Backstage plugin that lets you browse the configuration schema of your app", "backstage": { "role": "frontend-plugin", diff --git a/plugins/devtools-backend/CHANGELOG.md b/plugins/devtools-backend/CHANGELOG.md index d1ae56ddac..0dc5503884 100644 --- a/plugins/devtools-backend/CHANGELOG.md +++ b/plugins/devtools-backend/CHANGELOG.md @@ -1,5 +1,52 @@ # @backstage/plugin-devtools-backend +## 0.5.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.14.1-next.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/cli-common@0.1.16 + - @backstage/config@1.3.6 + - @backstage/config-loader@1.10.7 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-devtools-common@0.1.20 + - @backstage/plugin-permission-common@0.9.3 + - @backstage/plugin-permission-node@0.10.7 + +## 0.5.12 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- 291bf9d: Added scheduled tasks UI feature for the DevTools plugin +- Updated dependencies + - @backstage/backend-defaults@0.14.0 + - @backstage/plugin-permission-node@0.10.7 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/cli-common@0.1.16 + - @backstage/config-loader@1.10.7 + - @backstage/plugin-devtools-common@0.1.20 + +## 0.5.12-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-defaults@0.14.0-next.1 + - @backstage/plugin-permission-node@0.10.7-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config-loader@1.10.7-next.1 + - @backstage/cli-common@0.1.16-next.2 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-devtools-common@0.1.19 + - @backstage/plugin-permission-common@0.9.3 + ## 0.5.12-next.0 ### Patch Changes diff --git a/plugins/devtools-backend/package.json b/plugins/devtools-backend/package.json index f420652580..3f9baf249f 100644 --- a/plugins/devtools-backend/package.json +++ b/plugins/devtools-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-devtools-backend", - "version": "0.5.12-next.0", + "version": "0.5.13-next.0", "backstage": { "role": "backend-plugin", "pluginId": "devtools", diff --git a/plugins/devtools-backend/src/plugin.ts b/plugins/devtools-backend/src/plugin.ts index d3fefda343..d7ac3ff6d9 100644 --- a/plugins/devtools-backend/src/plugin.ts +++ b/plugins/devtools-backend/src/plugin.ts @@ -20,6 +20,10 @@ import { } from '@backstage/backend-plugin-api'; import { createRouter } from './service/router'; import { devToolsPermissions } from '@backstage/plugin-devtools-common'; +import { + devToolsTaskSchedulerReadPermission, + devToolsTaskSchedulerCreatePermission, +} from '@backstage/plugin-devtools-common/alpha'; /** * DevTools backend plugin @@ -61,7 +65,11 @@ export const devtoolsPlugin = createBackendPlugin({ path: '/health', allow: 'unauthenticated', }); - permissionsRegistry.addPermissions(devToolsPermissions); + permissionsRegistry.addPermissions([ + ...devToolsPermissions, + devToolsTaskSchedulerReadPermission, + devToolsTaskSchedulerCreatePermission, + ]); }, }); }, diff --git a/plugins/devtools-common/CHANGELOG.md b/plugins/devtools-common/CHANGELOG.md index 6eeced0711..baa07b0bb7 100644 --- a/plugins/devtools-common/CHANGELOG.md +++ b/plugins/devtools-common/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/plugin-devtools-common +## 0.1.20 + +### Patch Changes + +- 291bf9d: Added scheduled tasks UI feature for the DevTools plugin + ## 0.1.19 ### Patch Changes diff --git a/plugins/devtools-common/package.json b/plugins/devtools-common/package.json index cb21e9ed0a..7ece3371fa 100644 --- a/plugins/devtools-common/package.json +++ b/plugins/devtools-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-devtools-common", - "version": "0.1.19", + "version": "0.1.20", "description": "Common functionalities for the devtools plugin", "backstage": { "role": "common-library", @@ -13,10 +13,7 @@ ] }, "publishConfig": { - "access": "public", - "main": "dist/index.cjs.js", - "module": "dist/index.esm.js", - "types": "dist/index.d.ts" + "access": "public" }, "homepage": "https://backstage.io", "repository": { @@ -26,8 +23,23 @@ }, "license": "Apache-2.0", "sideEffects": false, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" + }, "main": "src/index.ts", "types": "src/index.ts", + "typesVersions": { + "*": { + "alpha": [ + "src/alpha.ts" + ], + "package.json": [ + "package.json" + ] + } + }, "files": [ "dist" ], diff --git a/plugins/devtools-common/report-alpha.api.md b/plugins/devtools-common/report-alpha.api.md new file mode 100644 index 0000000000..3c3b7ff89e --- /dev/null +++ b/plugins/devtools-common/report-alpha.api.md @@ -0,0 +1,69 @@ +## API Report File for "@backstage/plugin-devtools-common" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BasicPermission } from '@backstage/plugin-permission-common'; +import { JsonObject } from '@backstage/types'; + +// @alpha (undocumented) +export const devToolsTaskSchedulerCreatePermission: BasicPermission; + +// @alpha (undocumented) +export const devToolsTaskSchedulerReadPermission: BasicPermission; + +// @alpha (undocumented) +export type ScheduledTasks = { + scheduledTasks?: TaskApiTasksResponse[]; + error?: string; +}; + +// @alpha +export interface TaskApiTasksResponse { + // (undocumented) + pluginId: string; + // (undocumented) + scope: 'global' | 'local'; + // (undocumented) + settings: { + version: number; + } & JsonObject; + // (undocumented) + taskId: string; + // (undocumented) + taskState: + | { + status: 'running'; + startedAt: string; + timesOutAt?: string; + lastRunError?: string; + lastRunEndedAt?: string; + } + | { + status: 'idle'; + startsAt?: string; + lastRunError?: string; + lastRunEndedAt?: string; + } + | null; + // (undocumented) + workerState: + | { + status: 'initial-wait'; + } + | { + status: 'idle'; + } + | { + status: 'running'; + } + | null; +} + +// @alpha (undocumented) +export type TriggerScheduledTask = { + error?: string; +}; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/devtools-common/src/alpha.ts b/plugins/devtools-common/src/alpha.ts new file mode 100644 index 0000000000..984967c4f3 --- /dev/null +++ b/plugins/devtools-common/src/alpha.ts @@ -0,0 +1,24 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { + devToolsTaskSchedulerReadPermission, + devToolsTaskSchedulerCreatePermission, +} from './permissions'; +export type { + ScheduledTasks, + TaskApiTasksResponse, + TriggerScheduledTask, +} from './types'; diff --git a/plugins/devtools-common/src/index.ts b/plugins/devtools-common/src/index.ts index be7426394b..88bc0d545f 100644 --- a/plugins/devtools-common/src/index.ts +++ b/plugins/devtools-common/src/index.ts @@ -20,5 +20,19 @@ * @packageDocumentation */ -export * from './types'; -export * from './permissions'; +export type { + ConfigError, + ConfigInfo, + DevToolsInfo, + Endpoint, + ExternalDependency, + PackageDependency, +} from './types'; +export { ExternalDependencyStatus } from './types'; +export { + devToolsAdministerPermission, + devToolsConfigReadPermission, + devToolsExternalDependenciesReadPermission, + devToolsInfoReadPermission, + devToolsPermissions, +} from './permissions'; diff --git a/plugins/devtools-common/src/permissions.ts b/plugins/devtools-common/src/permissions.ts index ba464f7d80..42a7efe777 100644 --- a/plugins/devtools-common/src/permissions.ts +++ b/plugins/devtools-common/src/permissions.ts @@ -48,6 +48,22 @@ export const devToolsExternalDependenciesReadPermission = createPermission({ attributes: { action: 'read' }, }); +/** + * @alpha + */ +export const devToolsTaskSchedulerReadPermission = createPermission({ + name: 'devtools.scheduler.read', + attributes: { action: 'read' }, +}); + +/** + * @alpha + */ +export const devToolsTaskSchedulerCreatePermission = createPermission({ + name: 'devtools.scheduler.trigger', + attributes: { action: 'update' }, +}); + /** * List of all Devtools permissions * diff --git a/plugins/devtools-common/src/types.ts b/plugins/devtools-common/src/types.ts index f1e60d9c2d..dc35188fde 100644 --- a/plugins/devtools-common/src/types.ts +++ b/plugins/devtools-common/src/types.ts @@ -16,7 +16,7 @@ /* We want to maintain the same information as an enum, so we disable the redeclaration warning */ /* eslint-disable @typescript-eslint/no-redeclare */ -import { JsonValue } from '@backstage/types'; +import { JsonObject, JsonValue } from '@backstage/types'; /** @public */ export type Endpoint = { @@ -82,3 +82,54 @@ export type ConfigError = { messages?: string[]; stack?: string; }; + +/** + * The shape of a task definition as returned by the service's REST API. + * This is a duplication of the below: + * @see https://github.com/backstage/backstage/blob/master/packages/backend-defaults/src/entrypoints/scheduler/lib/types.ts + * + * @alpha + */ +export interface TaskApiTasksResponse { + taskId: string; + pluginId: string; + scope: 'global' | 'local'; + settings: { version: number } & JsonObject; + taskState: + | { + status: 'running'; + startedAt: string; + timesOutAt?: string; + lastRunError?: string; + lastRunEndedAt?: string; + } + | { + status: 'idle'; + startsAt?: string; + lastRunError?: string; + lastRunEndedAt?: string; + } + | null; + workerState: + | { + status: 'initial-wait'; + } + | { + status: 'idle'; + } + | { + status: 'running'; + } + | null; +} + +/** @alpha */ +export type ScheduledTasks = { + scheduledTasks?: TaskApiTasksResponse[]; + error?: string; +}; + +/** @alpha */ +export type TriggerScheduledTask = { + error?: string; +}; diff --git a/plugins/devtools/CHANGELOG.md b/plugins/devtools/CHANGELOG.md index 4bc547cbbe..8d842ef87a 100644 --- a/plugins/devtools/CHANGELOG.md +++ b/plugins/devtools/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-devtools +## 0.1.34 + +### Patch Changes + +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- 291bf9d: Added scheduled tasks UI feature for the DevTools plugin +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/plugin-devtools-common@0.1.20 + - @backstage/core-compat-api@0.5.5 + - @backstage/plugin-permission-react@0.4.39 + ## 0.1.34-next.0 ### Patch Changes diff --git a/plugins/devtools/README.md b/plugins/devtools/README.md index aef25ae21c..967f3693a6 100644 --- a/plugins/devtools/README.md +++ b/plugins/devtools/README.md @@ -34,6 +34,12 @@ Lists the configuration being used by your current running Backstage instance. ![Example of Config tab](./docs/devtools-config-tab.png) +### Scheduled Tasks + +Scheduled tasks can be viewed and triggered under the `Scheduled Tasks` tab. [See below to configure](#scheduled-tasks-configuration). + +![Example of Scheduled Tasks tab](./docs/devtools-scheduled-tasks-tab.png) + ## Optional Features The DevTools plugin can be setup with other tabs with additional helpful features. @@ -489,3 +495,14 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ apt-get update && \ apt-get install -y ... iputils-ping ``` + +### Scheduled Tasks Configuration + +Scheduled tasks can be viewed and triggered under the `Scheduled Tasks` tab. You first must add the list of plugins for scheduled tasks to your config: + +```yaml +devTools: + scheduledTasks: + plugins: + - catalog +``` diff --git a/plugins/devtools/config.d.ts b/plugins/devtools/config.d.ts new file mode 100644 index 0000000000..841bb0b042 --- /dev/null +++ b/plugins/devtools/config.d.ts @@ -0,0 +1,30 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export interface Config { + devTools?: { + /** + * Scheduled tasks configuration + * @visibility frontend + */ + scheduledTasks?: { + /** + * A list of plugin IDs to select from, e.g. ['catalog', 'scaffolder'] + * @visibility frontend + */ + plugins: string[]; + }; + }; +} diff --git a/plugins/devtools/docs/devtools-scheduled-tasks-tab.png b/plugins/devtools/docs/devtools-scheduled-tasks-tab.png new file mode 100644 index 0000000000..90e5e57d83 Binary files /dev/null and b/plugins/devtools/docs/devtools-scheduled-tasks-tab.png differ diff --git a/plugins/devtools/package.json b/plugins/devtools/package.json index b62712b1e2..c12374f779 100644 --- a/plugins/devtools/package.json +++ b/plugins/devtools/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-devtools", - "version": "0.1.34-next.0", + "version": "0.1.34", "backstage": { "role": "frontend-plugin", "pluginId": "devtools", @@ -40,7 +40,8 @@ } }, "files": [ - "dist" + "dist", + "config.d.ts" ], "scripts": { "build": "backstage-cli package build", @@ -52,6 +53,7 @@ "test": "backstage-cli package test" }, "dependencies": { + "@backstage/core-compat-api": "workspace:^", "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", "@backstage/errors": "workspace:^", @@ -62,6 +64,7 @@ "@material-ui/core": "^4.9.13", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "^4.0.0-alpha.57", + "lodash": "^4.17.21", "react-json-view": "^1.21.3", "react-use": "^17.2.4" }, @@ -69,6 +72,7 @@ "@backstage/cli": "workspace:^", "@backstage/dev-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0", + "@types/lodash": "^4.14.151", "@types/react": "^18.0.0", "react": "^18.0.2", "react-dom": "^18.0.2", @@ -84,5 +88,6 @@ "@types/react": { "optional": true } - } + }, + "configSchema": "config.d.ts" } diff --git a/plugins/devtools/report.api.md b/plugins/devtools/report.api.md index 70fbcaadb7..5f9a46016d 100644 --- a/plugins/devtools/report.api.md +++ b/plugins/devtools/report.api.md @@ -9,6 +9,7 @@ import { JSX as JSX_2 } from 'react/jsx-runtime'; import { ReactNode } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; import { TabProps } from '@material-ui/core/Tab'; +import { TaskApiTasksResponse } from '@backstage/plugin-devtools-common/alpha'; // @public (undocumented) export const ConfigContent: () => JSX_2.Element; @@ -49,6 +50,16 @@ export const ExternalDependenciesContent: () => JSX_2.Element; // @public (undocumented) export const InfoContent: () => JSX_2.Element; +// @public (undocumented) +export const ScheduledTaskDetailPanel: ({ + rowData, +}: { + rowData: TaskApiTasksResponse; +}) => JSX_2.Element; + +// @public (undocumented) +export const ScheduledTasksContent: () => JSX_2.Element; + // @public (undocumented) export type SubRoute = { path: string; diff --git a/plugins/devtools/src/api/DevToolsApi.ts b/plugins/devtools/src/api/DevToolsApi.ts index ff58a4ea16..4fc579ee06 100644 --- a/plugins/devtools/src/api/DevToolsApi.ts +++ b/plugins/devtools/src/api/DevToolsApi.ts @@ -20,6 +20,10 @@ import { DevToolsInfo, ExternalDependency, } from '@backstage/plugin-devtools-common'; +import { + ScheduledTasks, + TriggerScheduledTask, +} from '@backstage/plugin-devtools-common/alpha'; export const devToolsApiRef = createApiRef({ id: 'plugin.devtools.service', @@ -29,4 +33,9 @@ export interface DevToolsApi { getConfig(): Promise; getExternalDependencies(): Promise; getInfo(): Promise; + getScheduledTasksByPlugin(plugin: string): Promise; + triggerScheduledTask( + plugin: string, + taskId: string, + ): Promise; } diff --git a/plugins/devtools/src/api/DevToolsClient.ts b/plugins/devtools/src/api/DevToolsClient.ts index e0b387a6ca..cd4f53fa81 100644 --- a/plugins/devtools/src/api/DevToolsClient.ts +++ b/plugins/devtools/src/api/DevToolsClient.ts @@ -20,6 +20,10 @@ import { DevToolsInfo, ExternalDependency, } from '@backstage/plugin-devtools-common'; +import { + ScheduledTasks, + TriggerScheduledTask, +} from '@backstage/plugin-devtools-common/alpha'; import { ResponseError } from '@backstage/errors'; import { DevToolsApi } from './DevToolsApi'; @@ -42,6 +46,45 @@ export class DevToolsClient implements DevToolsApi { return configInfo; } + public async getScheduledTasksByPlugin( + plugin: string, + ): Promise { + const baseUrl = `${await this.discoveryApi.getBaseUrl(plugin)}/`; + const url = new URL('.backstage/scheduler/v1/tasks', baseUrl); + + const response = await this.fetchApi.fetch(url.toString()); + + if (!response.ok) { + throw await ResponseError.fromResponse(response); + } + + const scheduledTasks = await response.json(); + return { + scheduledTasks: scheduledTasks.tasks, + }; + } + + public async triggerScheduledTask( + plugin: string, + taskId: string, + ): Promise { + const baseUrl = `${await this.discoveryApi.getBaseUrl(plugin)}/`; + const url = new URL( + `.backstage/scheduler/v1/tasks/${taskId}/trigger`, + baseUrl, + ); + + const response = await this.fetchApi.fetch(url.toString(), { + method: 'POST', + }); + + if (!response.ok) { + throw await ResponseError.fromResponse(response); + } + + return response.json() as Promise; + } + public async getExternalDependencies(): Promise< ExternalDependency[] | undefined > { diff --git a/plugins/devtools/src/components/Content/ScheduledTasksContent/ScheduledTaskDetailedPanel.tsx b/plugins/devtools/src/components/Content/ScheduledTasksContent/ScheduledTaskDetailedPanel.tsx new file mode 100644 index 0000000000..a29e1eb10e --- /dev/null +++ b/plugins/devtools/src/components/Content/ScheduledTasksContent/ScheduledTaskDetailedPanel.tsx @@ -0,0 +1,104 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { TaskApiTasksResponse } from '@backstage/plugin-devtools-common/alpha'; +import Grid from '@material-ui/core/Grid'; +import Typography from '@material-ui/core/Typography'; +import Box from '@material-ui/core/Box'; +import { createStyles, makeStyles, Theme } from '@material-ui/core/styles'; +import Alert from '@material-ui/lab/Alert'; + +const useStyles = makeStyles((theme: Theme) => + createStyles({ + detailPanel: { + padding: theme.spacing(2), + backgroundColor: theme.palette.background.default, + }, + detailLabel: { + fontWeight: 'bold', + marginRight: theme.spacing(1), + }, + errorIcon: { + color: theme.palette.error.main, + marginRight: theme.spacing(1), + fontSize: '1.2rem', + }, + detailPanelAlert: { + marginBottom: theme.spacing(2), + }, + }), +); + +/** @public */ +export const ScheduledTaskDetailPanel = ({ + rowData, +}: { + rowData: TaskApiTasksResponse; +}) => { + const classes = useStyles(); + const lastRunError = rowData.taskState?.lastRunError; + + const DetailItem = ({ title, value }: { title: string; value: any }) => ( + <> + + + {title}: + + + + + {value || 'N/A'} + + + + ); + + return ( + + {lastRunError && ( + + Last Run Error: {lastRunError} + + )} + + + + + + + + + + ); +}; diff --git a/plugins/devtools/src/components/Content/ScheduledTasksContent/ScheduledTasksContent.tsx b/plugins/devtools/src/components/Content/ScheduledTasksContent/ScheduledTasksContent.tsx new file mode 100644 index 0000000000..2d4abd56ef --- /dev/null +++ b/plugins/devtools/src/components/Content/ScheduledTasksContent/ScheduledTasksContent.tsx @@ -0,0 +1,307 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { useState } from 'react'; +import Box from '@material-ui/core/Box'; +import Typography from '@material-ui/core/Typography'; +import IconButton from '@material-ui/core/IconButton'; +import Tooltip from '@material-ui/core/Tooltip'; +import Autocomplete from '@material-ui/lab/Autocomplete'; +import TextField from '@material-ui/core/TextField'; +import { makeStyles, createStyles, Theme } from '@material-ui/core/styles'; +import { + ErrorPanel, + Progress, + Table, + TableColumn, +} from '@backstage/core-components'; +import Alert from '@material-ui/lab/Alert'; +import { useScheduledTasks, useTriggerScheduledTask } from '../../../hooks'; +import { TaskApiTasksResponse } from '@backstage/plugin-devtools-common/alpha'; +import { alertApiRef, configApiRef, useApi } from '@backstage/core-plugin-api'; +import RefreshIcon from '@material-ui/icons/Refresh'; +import NightsStay from '@material-ui/icons/NightsStay'; +import ErrorIcon from '@material-ui/icons/Error'; +import CircularProgress from '@material-ui/core/CircularProgress'; +import { ScheduledTaskDetailPanel } from './ScheduledTaskDetailedPanel'; +import { RequirePermission } from '@backstage/plugin-permission-react'; +import { devToolsTaskSchedulerCreatePermission } from '@backstage/plugin-devtools-common/alpha'; + +const useStyles = makeStyles((theme: Theme) => + createStyles({ + paperStyle: { + display: 'flex', + marginBottom: theme.spacing(2), + }, + flexContainer: { + display: 'flex', + flexDirection: 'row', + padding: 0, + }, + formControl: { + minWidth: 240, + marginBottom: theme.spacing(2), + }, + detailPanel: { + padding: theme.spacing(2), + backgroundColor: theme.palette.background.default, + }, + detailLabel: { + fontWeight: 'bold', + marginRight: theme.spacing(1), + }, + errorIcon: { + color: theme.palette.error.main, + marginRight: theme.spacing(1), + fontSize: '1.2rem', + }, + detailPanelAlert: { + marginBottom: theme.spacing(2), + }, + }), +); + +const StatusDisplay = ({ + icon, + text, +}: { + icon: React.ReactNode; + text: string; +}) => ( + + {icon} + + {text} + + +); + +/** @public */ +export const ScheduledTasksContent = () => { + const classes = useStyles(); + const configApi = useApi(configApiRef); + const alertApi = useApi(alertApiRef); + const plugins = + configApi.getOptionalStringArray('devTools.scheduledTasks.plugins') || []; + const [selectedPlugin, setSelectedPlugin] = useState(plugins[0] || ''); + const { scheduledTasks, loading, error } = useScheduledTasks(selectedPlugin); + const { triggerTask, isTriggering, triggerError } = useTriggerScheduledTask(); + + const [inputValue, setInputValue] = useState(''); + + const handleAutocompleteChange = (_event: any, newValue: string | null) => { + setSelectedPlugin(newValue || ''); + }; + + const handleCommitChange = () => { + if (inputValue !== selectedPlugin) { + setSelectedPlugin(inputValue); + } + }; + + const handleKeyDown = (event: React.KeyboardEvent) => { + if (event.key === 'Enter') { + handleCommitChange(); + // Prevent Autocomplete's default behavior (which might select a filtered item) + event.preventDefault(); + event.stopPropagation(); + } + }; + + if (!plugins || plugins.length === 0) { + return ( + + No plugins configured for scheduled tasks. Please configure + `devTools.scheduledTasks.plugins` in app-config.yaml. + + ); + } + + const columns: TableColumn[] = [ + { + title: 'Task ID', + field: 'taskId', + width: '35%', + render: (rowData: TaskApiTasksResponse) => { + const errorIconStyle: React.CSSProperties = { + color: '#f44336', + marginRight: '8px', + fontSize: '1.2rem', + verticalAlign: 'middle', + }; + + return ( + + {rowData.taskState?.lastRunError && ( + + )} + {rowData.taskId} + + ); + }, + }, + { + title: 'Status', + field: 'taskState.status', + width: '15%', + render: (rowData: TaskApiTasksResponse) => { + const status = rowData.taskState?.status; + + if (status === 'idle') { + return ( + } text="Idle" /> + ); + } + + if (status === 'running') { + return ( + } + text="Running" + /> + ); + } + + return {status || 'N/A'}; + }, + }, + { + title: 'Last Run', + field: 'taskState.lastRunEndedAt', + width: '25%', + render: (rowData: TaskApiTasksResponse) => + rowData.taskState?.lastRunEndedAt + ? new Date(rowData.taskState.lastRunEndedAt).toLocaleString() + : 'N/A', + }, + { + title: 'Next Run', + width: '15%', + render: (rowData: TaskApiTasksResponse) => + rowData.taskState?.status === 'idle' && rowData.taskState.startsAt + ? new Date(rowData.taskState.startsAt).toLocaleString() + : 'N/A', + }, + { + title: 'Actions', + render: (rowData: TaskApiTasksResponse) => ( + + + { + triggerTask(selectedPlugin, rowData.taskId); + if (triggerError) { + alertApi.post({ + message: `Error triggering task ${rowData.taskId}: ${error}`, + severity: 'error', + }); + } else { + alertApi.post({ + message: `Successfully triggered task ${rowData.taskId}`, + severity: 'success', + }); + } + }} + > + + + + + ), + sorting: false, + width: '10%', + }, + ]; + + return ( + + { + setInputValue(newInputValue); + }} + renderInput={params => ( + + )} + /> + + {loading && } + + {error && ( + + + The plugin ID "{selectedPlugin}" doesn't have any scheduled tasks or + may contain a typo. + + + Please verify: + +
    +
  • + + The plugin ID is spelled correctly + +
  • +
  • + + The plugin has registered scheduled tasks + +
  • +
+
+ )} + + {!loading && !error && ( + + No scheduled tasks found for {selectedPlugin}. + + } + detailPanel={({ rowData }) => { + return ; + }} + /> + )} + + ); +}; diff --git a/plugins/devtools/src/components/Content/ScheduledTasksContent/fixtures/scheduledTasksErrors.json b/plugins/devtools/src/components/Content/ScheduledTasksContent/fixtures/scheduledTasksErrors.json new file mode 100644 index 0000000000..89f81b740d --- /dev/null +++ b/plugins/devtools/src/components/Content/ScheduledTasksContent/fixtures/scheduledTasksErrors.json @@ -0,0 +1,205 @@ +{ + "tasks": [ + { + "taskId": "cool-provider", + "pluginId": "catalog", + "scope": "global", + "settings": { + "version": 2, + "cadence": "PT24H", + "timeoutAfterDuration": "PT60M" + }, + "taskState": { + "status": "running", + "startedAt": "2025-10-31T21:02:36.461+00:00", + "timesOutAt": "2025-10-31T22:02:36.461+00:00", + "lastRunEndedAt": "2025-10-31T19:57:15.674+00:00", + "lastRunError": "{\"name\":\"error\",\"message\":\"insert into \\\"refresh_state\\\" (\\\"entity_id\\\", \\\"entity_ref\\\", \\\"errors\\\", \\\"last_discovery_at\\\", \\\"location_key\\\", \\\"next_update_at\\\", \\\"unprocessed_entity\\\", \\\"unprocessed_hash\\\") values ($1, $2, $3, CURRENT_TIMESTAMP, $4, CURRENT_TIMESTAMP, $5, $6), ($7, $8, $9, CURRENT_TIMESTAMP, $10, CURRENT_TIMESTAMP, $11, $12), ($13, $14, $15, CURRENT_TIMESTAMP, $16, CURRENT_TIMESTAMP, $17, $18), ($19, $20, $21, CURRENT_TIMESTAMP, $22, CURRENT_TIMESTAMP, $23, $24), ($25, $26, $27, CURRENT_TIMESTAMP, $28, CURRENT_TIMESTAMP, $29, $30), ($31, $32, $33, CURRENT_TIMESTAMP, $34, CURRENT_TIMESTAMP, $35, $36), ($37, $38, $39, CURRENT_TIMESTAMP, $40, CURRENT_TIMESTAMP, $41, $42), ($43, $44, $45, CURRENT_TIMESTAMP, $46, CURRENT_TIMESTAMP, $47, $48), ($49, $50, $51, CURRENT_TIMESTAMP, $52, CURRENT_TIMESTAMP, $53, $54), ($55, $56, $57, CURRENT_TIMESTAMP, $58, CURRENT_TIMESTAMP, $59, $60), ($61, $62, $63, CURRENT_TIMESTAMP, $64, CURRENT_TIMESTAMP, $65, $66), ($67, $68, $69, CURRENT_TIMESTAMP, $70, CURRENT_TIMESTAMP, $71, $72), ($73, $74, $75, CURRENT_TIMESTAMP, $76, CURRENT_TIMESTAMP, $77, $78), ($79, $80, $81, CURRENT_TIMESTAMP, $82, CURRENT_TIMESTAMP, $83, $84), ($85, $86, $87, CURRENT_TIMESTAMP, $88, CURRENT_TIMESTAMP, $89, $90), ($91, $92, $93, CURRENT_TIMESTAMP, $94, CURRENT_TIMESTAMP, $95, $96), ($97, $98, $99, CURRENT_TIMESTAMP, $100, CURRENT_TIMESTAMP, $101, $102), ($103, $104, $105, CURRENT_TIMESTAMP, $106, CURRENT_TIMESTAMP, $107, $108), ($109, $110, $111, CURRENT_TIMESTAMP, $112, CURRENT_TIMESTAMP, $113, $114), ($115, $116, $117, CURRENT_TIMESTAMP, $118, CURRENT_TIMESTAMP, $119, $120), ($121, $122, $123, CURRENT_TIMESTAMP, $124, CURRENT_TIMESTAMP, $125, $126), ($127, $128, $129, CURRENT_TIMESTAMP, $130, CURRENT_TIMESTAMP, $131, $132), ($133, $134, $135, CURRENT_TIMESTAMP, $136, CURRENT_TIMESTAMP, $137, $138), ($139, $140, $141, CURRENT_TIMESTAMP, $142, CURRENT_TIMESTAMP, $143, $144), ($145, $146, $147, CURRENT_TIMESTAMP, $148, CURRENT_TIMESTAMP, $149, $150), ($151, $152, $153, CURRENT_TIMESTAMP, $154, CURRENT_TIMESTAMP, $155, $156), ($157, $158, $159, CURRENT_TIMESTAMP, $160, CURRENT_TIMESTAMP, $161, $162), ($163, $164, $165, CURRENT_TIMESTAMP, $166, CURRENT_TIMESTAMP, $167, $168), ($169, $170, $171, CURRENT_TIMESTAMP, $172, CURRENT_TIMESTAMP, $173, $174), ($175, $176, $177, CURRENT_TIMESTAMP, $178, CURRENT_TIMESTAMP, $179, $180), ($181, $182, $183, CURRENT_TIMESTAMP, $184, CURRENT_TIMESTAMP, $185, $186), ($187, $188, $189, CURRENT_TIMESTAMP, $190, CURRENT_TIMESTAMP, $191, $192), ($193, $194, $195, CURRENT_TIMESTAMP, $196, CURRENT_TIMESTAMP, $197, $198), ($199, $200, $201, CURRENT_TIMESTAMP, $202, CURRENT_TIMESTAMP, $203, $204), ($205, $206, $207, CURRENT_TIMESTAMP, $208, CURRENT_TIMESTAMP, $209, $210), ($211, $212, $213, CURRENT_TIMESTAMP, $214, CURRENT_TIMESTAMP, $215, $216), ($217, $218, $219, CURRENT_TIMESTAMP, $220, CURRENT_TIMESTAMP, $221, $222), ($223, $224, $225, CURRENT_TIMESTAMP, $226, CURRENT_TIMESTAMP, $227, $228), ($229, $230, $231, CURRENT_TIMESTAMP, $232, CURRENT_TIMESTAMP, $233, $234), ($235, $236, $237, CURRENT_TIMESTAMP, $238, CURRENT_TIMESTAMP, $239, $240), ($241, $242, $243, CURRENT_TIMESTAMP, $244, CURRENT_TIMESTAMP, $245, $246), ($247, $248, $249, CURRENT_TIMESTAMP, $250, CURRENT_TIMESTAMP, $251, $252), ($253, $254, $255, CURRENT_TIMESTAMP, $256, CURRENT_TIMESTAMP, $257, $258), ($259, $260, $261, CURRENT_TIMESTAMP, $262, CURRENT_TIMESTAMP, $263, $264), ($265, $266, $267, CURRENT_TIMESTAMP, $268, CURRENT_TIMESTAMP, $269, $270), ($271, $272, $273, CURRENT_TIMESTAMP, $274, CURRENT_TIMESTAMP, $275, $276), ($277, $278, $279, CURRENT_TIMESTAMP, $280, CURRENT_TIMESTAMP, $281, $282), ($283, $284, $285, CURRENT_TIMESTAMP, $286, CURRENT_TIMESTAMP, $287, $288), ($289, $290, $291, CURRENT_TIMESTAMP, $292, CURRENT_TIMESTAMP, $293, $294), ($295, $296, $297, CURRENT_TIMESTAMP, $298, CURRENT_TIMESTAMP, $299, $300) - value too long for type character varying(255)\",\"length\":99,\"severity\":\"ERROR\",\"code\":\"22001\",\"file\":\"varchar.c\",\"line\":\"637\",\"routine\":\"varchar\"}" + }, + "workerState": { + "status": "running" + } + }, + { + "taskId": "some-provider", + "pluginId": "catalog", + "scope": "global", + "settings": { + "version": 2, + "cadence": "PT24H", + "timeoutAfterDuration": "PT24H" + }, + "taskState": { + "status": "idle", + "startsAt": "2025-11-01T21:02:34.850+00:00", + "lastRunEndedAt": "2025-10-31T21:02:35.556+00:00" + }, + "workerState": { + "status": "idle" + } + }, + { + "taskId": "three-provider", + "pluginId": "catalog", + "scope": "global", + "settings": { + "version": 2, + "cadence": "PT30M", + "timeoutAfterDuration": "PT2M" + }, + "taskState": { + "status": "idle", + "startsAt": "2025-10-31T21:16:04.145+00:00", + "lastRunEndedAt": "2025-10-31T20:46:09.184+00:00", + "lastRunError": "{\"name\":\"TypeError\",\"message\":\"String.prototype.replaceAll called with a non-global RegExp argument\"}" + }, + "workerState": { + "status": "idle" + } + }, + { + "taskId": "a-provider", + "pluginId": "catalog", + "scope": "global", + "settings": { + "version": 2, + "cadence": "PT60M", + "timeoutAfterDuration": "PT24H" + }, + "taskState": { + "status": "idle", + "startsAt": "2025-10-31T21:16:04.152+00:00", + "lastRunEndedAt": "2025-10-31T20:16:08.713+00:00" + }, + "workerState": { + "status": "idle" + } + }, + { + "taskId": "github-provider:provider123:refresh", + "pluginId": "catalog", + "scope": "global", + "settings": { + "version": 2, + "cadence": "PT24H", + "timeoutAfterDuration": "PT1H" + }, + "taskState": { + "status": "idle", + "startsAt": "2025-11-01T18:16:04.153+00:00", + "lastRunEndedAt": "2025-10-31T18:18:56.176+00:00" + }, + "workerState": { + "status": "idle" + } + }, + { + "taskId": "github-provider:provider123:refresh", + "pluginId": "catalog", + "scope": "global", + "settings": { + "version": 2, + "cadence": "PT24H", + "timeoutAfterDuration": "PT1H" + }, + "taskState": { + "status": "idle", + "startsAt": "2025-11-01T18:16:04.156+00:00", + "lastRunEndedAt": "2025-10-31T18:16:04.264+00:00" + }, + "workerState": { + "status": "idle" + } + }, + { + "taskId": "github-provider:provider234:refresh", + "pluginId": "catalog", + "scope": "global", + "settings": { + "version": 2, + "cadence": "PT24H", + "timeoutAfterDuration": "PT1H" + }, + "taskState": { + "status": "idle", + "startsAt": "2025-11-01T18:16:04.157+00:00", + "lastRunEndedAt": "2025-10-31T18:16:08.564+00:00" + }, + "workerState": { + "status": "idle" + } + }, + { + "taskId": "github-provider:provider567:refresh", + "pluginId": "catalog", + "scope": "global", + "settings": { + "version": 2, + "cadence": "PT24H", + "timeoutAfterDuration": "PT1H" + }, + "taskState": { + "status": "idle", + "startsAt": "2025-11-01T18:16:04.154+00:00", + "lastRunEndedAt": "2025-10-31T18:16:06.978+00:00" + }, + "workerState": { + "status": "idle" + } + }, + { + "taskId": "github-provider:provider910:refresh", + "pluginId": "catalog", + "scope": "global", + "settings": { + "version": 2, + "cadence": "PT24H", + "timeoutAfterDuration": "PT1H" + }, + "taskState": { + "status": "idle", + "startsAt": "2025-11-01T18:16:04.160+00:00", + "lastRunEndedAt": "2025-10-31T18:16:08.573+00:00" + }, + "workerState": { + "status": "idle" + } + }, + { + "taskId": "github-provider:provider000:refresh", + "pluginId": "catalog", + "scope": "global", + "settings": { + "version": 2, + "cadence": "PT24H", + "timeoutAfterDuration": "PT1H" + }, + "taskState": { + "status": "idle", + "startsAt": "2025-11-01T18:16:04.161+00:00", + "lastRunEndedAt": "2025-10-31T18:18:54.339+00:00" + }, + "workerState": { + "status": "idle" + } + }, + { + "taskId": "catalog_orphan_cleanup", + "pluginId": "catalog", + "scope": "global", + "settings": { + "version": 2, + "cadence": "PT30S", + "timeoutAfterDuration": "PT24S" + }, + "taskState": { + "status": "idle", + "startsAt": "2025-10-31T21:06:35.672+00:00", + "lastRunEndedAt": "2025-10-31T21:06:09.106+00:00" + }, + "workerState": { + "status": "idle" + } + } + ] +} diff --git a/plugins/devtools/src/components/Content/ScheduledTasksContent/index.ts b/plugins/devtools/src/components/Content/ScheduledTasksContent/index.ts new file mode 100644 index 0000000000..dff8bcf653 --- /dev/null +++ b/plugins/devtools/src/components/Content/ScheduledTasksContent/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { ScheduledTasksContent } from './ScheduledTasksContent'; +export { ScheduledTaskDetailPanel } from './ScheduledTaskDetailedPanel'; diff --git a/plugins/devtools/src/components/Content/index.ts b/plugins/devtools/src/components/Content/index.ts index f5bd64f7c0..964e7116d9 100644 --- a/plugins/devtools/src/components/Content/index.ts +++ b/plugins/devtools/src/components/Content/index.ts @@ -17,3 +17,4 @@ export * from './ConfigContent'; export * from './InfoContent'; export * from './ExternalDependenciesContent'; +export * from './ScheduledTasksContent'; diff --git a/plugins/devtools/src/components/DefaultDevToolsPage/DefaultDevToolsPage.tsx b/plugins/devtools/src/components/DefaultDevToolsPage/DefaultDevToolsPage.tsx index b2c1457161..36393db3b0 100644 --- a/plugins/devtools/src/components/DefaultDevToolsPage/DefaultDevToolsPage.tsx +++ b/plugins/devtools/src/components/DefaultDevToolsPage/DefaultDevToolsPage.tsx @@ -20,9 +20,11 @@ import { } from '@backstage/plugin-devtools-common'; import { ConfigContent } from '../Content'; +import { devToolsTaskSchedulerReadPermission } from '@backstage/plugin-devtools-common/alpha'; import { DevToolsLayout } from '../DevToolsLayout'; import { InfoContent } from '../Content'; import { RequirePermission } from '@backstage/plugin-permission-react'; +import { ScheduledTasksContent } from '../Content/ScheduledTasksContent'; import { DevToolsPageProps } from '../DevToolsPage'; /** @public */ @@ -38,6 +40,11 @@ export const DefaultDevToolsPage = ({ extensions }: DevToolsPageProps) => ( + + + + + {extensions?.map((extension, index) => ( { + const api = useApi(devToolsApiRef); + + const { + value, + loading, + error: asyncError, + } = useAsync(async () => { + return api.getScheduledTasksByPlugin(plugin); + }, [api, plugin]); + + if (asyncError) { + return { + scheduledTasks: undefined, + loading: false, + error: asyncError.message, + }; + } + + return { + scheduledTasks: value?.scheduledTasks, + loading, + error: value?.error, + }; +}; diff --git a/plugins/devtools/src/hooks/useTriggerScheduledTask.ts b/plugins/devtools/src/hooks/useTriggerScheduledTask.ts new file mode 100644 index 0000000000..d26b7a8025 --- /dev/null +++ b/plugins/devtools/src/hooks/useTriggerScheduledTask.ts @@ -0,0 +1,46 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { useState, useCallback } from 'react'; +import { devToolsApiRef } from '../api'; +import { useApi } from '@backstage/core-plugin-api'; + +export const useTriggerScheduledTask = () => { + const api = useApi(devToolsApiRef); + const [isTriggering, setIsTriggering] = useState(false); + const [error, setError] = useState(); + + const triggerTask = useCallback( + async (plugin: string, taskId: string) => { + setIsTriggering(true); + setError(undefined); + + try { + await api.triggerScheduledTask(plugin, taskId); + } catch (e) { + setError(e); + } finally { + setIsTriggering(false); + } + }, + [api], + ); + + return { + triggerTask, + isTriggering, + triggerError: error?.message, + }; +}; diff --git a/plugins/events-backend-module-aws-sqs/CHANGELOG.md b/plugins/events-backend-module-aws-sqs/CHANGELOG.md index d3eacfee63..23eeee8fcd 100644 --- a/plugins/events-backend-module-aws-sqs/CHANGELOG.md +++ b/plugins/events-backend-module-aws-sqs/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-events-backend-module-aws-sqs +## 0.4.18 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + +## 0.4.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/types@1.2.2 + ## 0.4.18-next.0 ### Patch Changes diff --git a/plugins/events-backend-module-aws-sqs/package.json b/plugins/events-backend-module-aws-sqs/package.json index 49d0ef0b3a..dbcca544dd 100644 --- a/plugins/events-backend-module-aws-sqs/package.json +++ b/plugins/events-backend-module-aws-sqs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-aws-sqs", - "version": "0.4.18-next.0", + "version": "0.4.18", "backstage": { "role": "backend-plugin-module", "pluginId": "events", diff --git a/plugins/events-backend-module-azure/CHANGELOG.md b/plugins/events-backend-module-azure/CHANGELOG.md index b176789833..07db604cc3 100644 --- a/plugins/events-backend-module-azure/CHANGELOG.md +++ b/plugins/events-backend-module-azure/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-events-backend-module-azure +## 0.2.27 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + +## 0.2.27-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + ## 0.2.27-next.0 ### Patch Changes diff --git a/plugins/events-backend-module-azure/package.json b/plugins/events-backend-module-azure/package.json index 51e79601c4..e0af5fda5c 100644 --- a/plugins/events-backend-module-azure/package.json +++ b/plugins/events-backend-module-azure/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-azure", - "version": "0.2.27-next.0", + "version": "0.2.27", "backstage": { "role": "backend-plugin-module", "pluginId": "events", diff --git a/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md b/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md index 29a9194bd7..4acd9bf71d 100644 --- a/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-events-backend-module-bitbucket-cloud +## 0.2.27 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + +## 0.2.27-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + ## 0.2.27-next.0 ### Patch Changes diff --git a/plugins/events-backend-module-bitbucket-cloud/package.json b/plugins/events-backend-module-bitbucket-cloud/package.json index 927e8b4ca0..cca7630e0d 100644 --- a/plugins/events-backend-module-bitbucket-cloud/package.json +++ b/plugins/events-backend-module-bitbucket-cloud/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-bitbucket-cloud", - "version": "0.2.27-next.0", + "version": "0.2.27", "backstage": { "role": "backend-plugin-module", "pluginId": "events", diff --git a/plugins/events-backend-module-bitbucket-server/CHANGELOG.md b/plugins/events-backend-module-bitbucket-server/CHANGELOG.md index 1c6b8d868c..3d602aebb2 100644 --- a/plugins/events-backend-module-bitbucket-server/CHANGELOG.md +++ b/plugins/events-backend-module-bitbucket-server/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-events-backend-module-bitbucket-server +## 0.1.8 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + +## 0.1.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + ## 0.1.8-next.0 ### Patch Changes diff --git a/plugins/events-backend-module-bitbucket-server/package.json b/plugins/events-backend-module-bitbucket-server/package.json index b57f83a078..452b3262a0 100644 --- a/plugins/events-backend-module-bitbucket-server/package.json +++ b/plugins/events-backend-module-bitbucket-server/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-bitbucket-server", - "version": "0.1.8-next.0", + "version": "0.1.8", "backstage": { "role": "backend-plugin-module", "pluginId": "events", diff --git a/plugins/events-backend-module-gerrit/CHANGELOG.md b/plugins/events-backend-module-gerrit/CHANGELOG.md index bff39866a7..4c0750ad67 100644 --- a/plugins/events-backend-module-gerrit/CHANGELOG.md +++ b/plugins/events-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-events-backend-module-gerrit +## 0.2.27 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + +## 0.2.27-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + ## 0.2.27-next.0 ### Patch Changes diff --git a/plugins/events-backend-module-gerrit/package.json b/plugins/events-backend-module-gerrit/package.json index 2fbe20a9eb..3d79d8805c 100644 --- a/plugins/events-backend-module-gerrit/package.json +++ b/plugins/events-backend-module-gerrit/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-gerrit", - "version": "0.2.27-next.0", + "version": "0.2.27", "backstage": { "role": "backend-plugin-module", "pluginId": "events", diff --git a/plugins/events-backend-module-github/CHANGELOG.md b/plugins/events-backend-module-github/CHANGELOG.md index 21f89ab3e2..edff58b374 100644 --- a/plugins/events-backend-module-github/CHANGELOG.md +++ b/plugins/events-backend-module-github/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-events-backend-module-github +## 0.4.7 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + +## 0.4.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/types@1.2.2 + ## 0.4.7-next.0 ### Patch Changes diff --git a/plugins/events-backend-module-github/package.json b/plugins/events-backend-module-github/package.json index 18489fe655..83513f30df 100644 --- a/plugins/events-backend-module-github/package.json +++ b/plugins/events-backend-module-github/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-github", - "version": "0.4.7-next.0", + "version": "0.4.7", "backstage": { "role": "backend-plugin-module", "pluginId": "events", diff --git a/plugins/events-backend-module-gitlab/CHANGELOG.md b/plugins/events-backend-module-gitlab/CHANGELOG.md index f819a5918c..b97a60c140 100644 --- a/plugins/events-backend-module-gitlab/CHANGELOG.md +++ b/plugins/events-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-events-backend-module-gitlab +## 0.3.8 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + +## 0.3.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + ## 0.3.8-next.0 ### Patch Changes diff --git a/plugins/events-backend-module-gitlab/package.json b/plugins/events-backend-module-gitlab/package.json index ce1a568cd8..e0d509fa3b 100644 --- a/plugins/events-backend-module-gitlab/package.json +++ b/plugins/events-backend-module-gitlab/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-gitlab", - "version": "0.3.8-next.0", + "version": "0.3.8", "backstage": { "role": "backend-plugin-module", "pluginId": "events", diff --git a/plugins/events-backend-module-google-pubsub/CHANGELOG.md b/plugins/events-backend-module-google-pubsub/CHANGELOG.md index dc8d774d47..d07530ac08 100644 --- a/plugins/events-backend-module-google-pubsub/CHANGELOG.md +++ b/plugins/events-backend-module-google-pubsub/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-events-backend-module-google-pubsub +## 0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + +## 0.1.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + ## 0.1.7-next.0 ### Patch Changes diff --git a/plugins/events-backend-module-google-pubsub/package.json b/plugins/events-backend-module-google-pubsub/package.json index 359c97c7f8..d5a97f3223 100644 --- a/plugins/events-backend-module-google-pubsub/package.json +++ b/plugins/events-backend-module-google-pubsub/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-google-pubsub", - "version": "0.1.7-next.0", + "version": "0.1.7", "description": "The google-pubsub backend module for the events plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/events-backend-module-kafka/CHANGELOG.md b/plugins/events-backend-module-kafka/CHANGELOG.md index 5cd64af42d..3edfcf9487 100644 --- a/plugins/events-backend-module-kafka/CHANGELOG.md +++ b/plugins/events-backend-module-kafka/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-events-backend-module-kafka +## 0.2.0 + +### Minor Changes + +- 2c74ea9: Added support for multiple named instances in `kafkaConsumingEventPublisher` configuration. The previous single configuration format is still supported for backward compatibility. +- 2c74ea9: Added `KafkaPublishingEventConsumer` to support sending Backstage events to Kafka topics. + + This addition enables Backstage to publish events to external Kafka systems, complementing the existing ability to receive events from Kafka. This allows for better integration with external systems that rely on Kafka for event streaming. + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + +## 0.1.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/types@1.2.2 + ## 0.1.6-next.0 ### Patch Changes diff --git a/plugins/events-backend-module-kafka/README.md b/plugins/events-backend-module-kafka/README.md index dbc5bf5607..f77b5d2f21 100644 --- a/plugins/events-backend-module-kafka/README.md +++ b/plugins/events-backend-module-kafka/README.md @@ -2,65 +2,107 @@ Welcome to the `events-backend-module-kafka` backend module! -This package is a module for the `events-backend` backend plugin and extends the events system with an `KafkaConsumingEventPublisher.` +This package is a module for the `events-backend` backend plugin and extends the events system with a `KafkaConsumingEventPublisher` and `KafkaPublishingEventConsumer` -This event publisher will allow you to receive events from an Kafka queue and will publish these to the used `EventsService` implementation. +This module provides two-way integration with Kafka: + +- **KafkaConsumingEventPublisher**: Receives events from Kafka queues and publishes them to the Backstage events system +- **KafkaPublishingEventConsumer**: Consumes events from Backstage and publishes them to Kafka queues ## Configuration -To set up Kafka queues, you need to configure the following values: +To set up Kafka integration, you need to configure one or both of the following components: + +### KafkaConsumingEventPublisher Configuration + +To receive events from Kafka queues and publish them to Backstage: ```yaml events: modules: kafka: kafkaConsumingEventPublisher: - clientId: your-client-id # (Required) Client ID used by Backstage to identify when connecting to the Kafka cluster. - brokers: # (Required) List of brokers in the Kafka cluster to connect to. - - broker1 - - broker2 - topics: - - topic: 'backstage.topic' # (Required) Replace with actual topic name as expected by subscribers - kafka: - topics: # (Required) The Kafka topics to subscribe to. - - topic1 - groupId: your-group-id # (Required) The GroupId to be used by the topic consumers. + production: # Instance name, will be included in logs + clientId: your-client-id # (Required) Client ID used by Backstage to identify when connecting to the Kafka cluster. + brokers: # (Required) List of brokers in the Kafka cluster to connect to. + - broker1 + - broker2 + topics: + - topic: 'backstage.topic' # (Required) Replace with actual topic name as expected by subscribers + kafka: + topics: # (Required) The Kafka topics to subscribe to. + - topic1 + groupId: your-group-id # (Required) The GroupId to be used by the topic consumers. +``` + +### KafkaPublishingEventConsumer Configuration + +To publish events from Backstage to Kafka queues, you can configure the `KafkaPublishingEventConsumer`: + +```yaml +events: + modules: + kafka: + kafkaPublishingEventConsumer: + production: # Instance name, will be included in logs + clientId: your-client-id # (Required) Client ID used by Backstage to identify when connecting to the Kafka cluster. + brokers: # (Required) List of brokers in the Kafka cluster to connect to. + - broker1 + - broker2 + topics: + - topic: 'catalog.entity.created' # (Required) The Backstage topic to consume from + kafka: + topic: kafka-topic-name # (Required) The Kafka topic to publish to ``` For a complete list of all available fields that can be configured, refer to the [config.d.ts file](./config.d.ts). ### Optional SSL Configuration -If your Kafka cluster requires SSL, you can configure it as follows: +If your Kafka cluster requires SSL, you can configure it for both `kafkaConsumingEventPublisher` and `kafkaPublishingEventConsumer` instances: ```yaml events: modules: kafka: kafkaConsumingEventPublisher: - ssl: - rejectUnauthorized: true # (Optional) If true, the server certificate is verified against the list of supplied CAs. - ca: [path/to/ca-cert] # (Optional) Array of trusted certificates in PEM format. - key: path/to/client-key # (Optional) Private key in PEM format. - cert: path/to/client-cert # (Optional) Public x509 certificate in PEM format. + production: + # ... other configuration ... + ssl: + rejectUnauthorized: true # (Optional) If true, the server certificate is verified against the list of supplied CAs. + ca: [path/to/ca-cert] # (Optional) Array of trusted certificates in PEM format. + key: path/to/client-key # (Optional) Private key in PEM format. + cert: path/to/client-cert # (Optional) Public x509 certificate in PEM format. + kafkaPublishingEventConsumer: + production: + # ... other configuration ... + ssl: + # Same SSL configuration options as above ``` ### Optional SASL Authentication Configuration -If your Kafka cluster requires `SASL` authentication, you can configure it as follows: +If your Kafka cluster requires SASL authentication, you can configure it for both components: ```yaml events: modules: kafka: kafkaConsumingEventPublisher: - sasl: - mechanism: 'plain' # SASL mechanism ('plain', 'scram-sha-256' or 'scram-sha-512') - username: your-username # SASL username - password: your-password # SASL password + production: + # ... other configuration ... + sasl: + mechanism: 'plain' # SASL mechanism ('plain', 'scram-sha-256' or 'scram-sha-512') + username: your-username # SASL username + password: your-password # SASL password + kafkaPublishingEventConsumer: + production: + # ... other configuration ... + sasl: + # Same SASL configuration options as above ``` -This section includes optional `SSL` and `SASL` authentication configuration for enhanced security. +These SSL and SASL configurations apply to both Kafka components and provide enhanced security for your Kafka connections. ## Installation diff --git a/plugins/events-backend-module-kafka/config.d.ts b/plugins/events-backend-module-kafka/config.d.ts index 49c417098c..47ebae0653 100644 --- a/plugins/events-backend-module-kafka/config.d.ts +++ b/plugins/events-backend-module-kafka/config.d.ts @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - import { HumanDuration } from '@backstage/types'; export interface Config { @@ -25,179 +24,548 @@ export interface Config { kafka?: { /** * Configuration for KafkaConsumingEventPublisher + * + * Supports either: + * 1. Single configuration object (legacy format) + * 2. Multiple named instances as a record where each key is a unique name for the Kafka instance */ - kafkaConsumingEventPublisher?: { - /** - * (Required) Client ID used by Backstage to identify when connecting to the Kafka cluster. - */ - clientId: string; - /** - * (Required) List of brokers in the Kafka cluster to connect to. - */ - brokers: string[]; - /** - * Optional SSL connection parameters to connect to the cluster. Passed directly to Node tls.connect. - * See https://nodejs.org/dist/latest-v8.x/docs/api/tls.html#tls_tls_createsecurecontext_options - */ - ssl?: - | { - ca?: string[]; + kafkaConsumingEventPublisher?: + | { + /** + * (Required) Client ID used by Backstage to identify when connecting to the Kafka cluster. + */ + clientId: string; + /** + * (Required) List of brokers in the Kafka cluster to connect to. + */ + brokers: string[]; + /** + * Optional SSL connection parameters to connect to the cluster. Passed directly to Node tls.connect. + * See https://nodejs.org/dist/latest-v8.x/docs/api/tls.html#tls_tls_createsecurecontext_options + */ + ssl?: + | { + ca?: string[]; + /** @visibility secret */ + key?: string; + cert?: string; + rejectUnauthorized?: boolean; + } + | boolean; + /** + * Optional SASL connection parameters. + */ + sasl?: { + mechanism: 'plain' | 'scram-sha-256' | 'scram-sha-512'; + username: string; /** @visibility secret */ - key?: string; - cert?: string; - rejectUnauthorized?: boolean; - } - | boolean; - /** - * Optional SASL connection parameters. - */ - sasl?: { - mechanism: 'plain' | 'scram-sha-256' | 'scram-sha-512'; - username: string; - /** @visibility secret */ - password: string; - }; + password: string; + }; - /** - * Optional retry connection parameters. - */ - retry: { - /** - * (Optional) Maximum wait time for a retry - * Default: 30000 ms. - */ - maxRetryTime: HumanDuration | string; - - /** - * (Optional) Initial value used to calculate the retry (This is still randomized following the randomization factor) - * Default: 300 ms. - */ - initialRetryTime: HumanDuration | string; - - /** - * (Optional) Randomization factor - * Default: 0.2. - */ - factor: number; - - /** - * (Optional) Exponential factor - * Default: 2. - */ - multiplier: number; - - /** - * (Optional) Max number of retries per call - * Default: 5. - */ - retries: number; - }; - - /** - * (Optional) Timeout for authentication requests. - * Default: 10000 ms. - */ - authenticationTimeout: HumanDuration | string; - - /** - * (Optional) Time to wait for a successful connection. - * Default: 1000 ms. - */ - connectionTimeout: HumanDuration | string; - - /** - * (Optional) Time to wait for a successful request. - * Default: 30000 ms. - */ - requestTimeout: HumanDuration | string; - - /** - * (Optional) The request timeout can be disabled by setting enforceRequestTimeout to false. - * Default: true - */ - enforceRequestTimeout: boolean; - - /** - * Contains a object per topic for which an Kafka queue - * should be used as source of events. - */ - topics: Array<{ - /** - * (Required) The Backstage topic to publish to - */ - topic: string; - /** - * (Required) KafkaConsumer-related configuration. - */ - kafka: { /** - * (Required) The Kafka topics to subscribe to + * Optional retry connection parameters. */ - topics: string[]; - /** - * (Required) The GroupId to be used by the topic consumers - */ - groupId: string; + retry?: { + /** + * (Optional) Maximum wait time for a retry + * Default: 30000 ms. + */ + maxRetryTime?: HumanDuration | string; + + /** + * (Optional) Initial value used to calculate the retry (This is still randomized following the randomization factor) + * Default: 300 ms. + */ + initialRetryTime?: HumanDuration | string; + + /** + * (Optional) Randomization factor + * Default: 0.2. + */ + factor?: number; + + /** + * (Optional) Exponential factor + * Default: 2. + */ + multiplier?: number; + + /** + * (Optional) Max number of retries per call + * Default: 5. + */ + retries?: number; + }; /** - * (Optional) Timeout used to detect failures. - * The consumer sends periodic heartbeats to indicate its liveness to the broker. - * If no heartbeats are received by the broker before the expiration of this session timeout, - * then the broker will remove this consumer from the group and initiate a rebalance + * (Optional) Timeout for authentication requests. + * Default: 10000 ms. + */ + authenticationTimeout?: HumanDuration | string; + + /** + * (Optional) Time to wait for a successful connection. + * Default: 1000 ms. + */ + connectionTimeout?: HumanDuration | string; + + /** + * (Optional) Time to wait for a successful request. * Default: 30000 ms. */ - sessionTimeout: HumanDuration | string; + requestTimeout?: HumanDuration | string; /** - * (Optional) The maximum time that the coordinator will wait for each member to rejoin when rebalancing the group - * Default: 60000 ms. + * (Optional) The request timeout can be disabled by setting enforceRequestTimeout to false. + * Default: true */ - rebalanceTimeout: HumanDuration | string; + enforceRequestTimeout?: boolean; /** - * (Optional) The expected time between heartbeats to the consumer coordinator. - * Heartbeats are used to ensure that the consumer's session stays active. - * The value must be set lower than session timeout - * Default: 3000 ms. + * Contains an object per topic for which a Kafka queue + * should be used as source of events. */ - heartbeatInterval: HumanDuration | string; + topics: Array<{ + /** + * (Required) The Backstage topic to publish to + */ + topic: string; + /** + * (Required) KafkaConsumer-related configuration. + */ + kafka: { + /** + * (Required) The Kafka topics to subscribe to + */ + topics: string[]; + /** + * (Required) The GroupId to be used by the topic consumers + */ + groupId: string; - /** - * (Optional) The period of time after which we force a refresh of metadata - * even if we haven't seen any partition leadership changes to proactively discover any new brokers or partitions - * Default: 300000 ms (5 minutes). - */ - metadataMaxAge: HumanDuration | string; + /** + * (Optional) Timeout used to detect failures. + * The consumer sends periodic heartbeats to indicate its liveness to the broker. + * If no heartbeats are received by the broker before the expiration of this session timeout, + * then the broker will remove this consumer from the group and initiate a rebalance + * Default: 30000 ms. + */ + sessionTimeout?: HumanDuration | string; - /** - * (Optional) The maximum amount of data per-partition the server will return. - * This size must be at least as large as the maximum message size the server allows - * or else it is possible for the producer to send messages larger than the consumer can fetch. - * If that happens, the consumer can get stuck trying to fetch a large message on a certain partition - * Default: 1048576 (1MB) - */ - maxBytesPerPartition: number; + /** + * (Optional) The maximum time that the coordinator will wait for each member to rejoin when rebalancing the group + * Default: 60000 ms. + */ + rebalanceTimeout?: HumanDuration | string; - /** - * (Optional) Minimum amount of data the server should return for a fetch request, otherwise wait up to maxWaitTime for more data to accumulate. - * Default: 1 - */ - minBytes: number; + /** + * (Optional) The expected time between heartbeats to the consumer coordinator. + * Heartbeats are used to ensure that the consumer's session stays active. + * The value must be set lower than session timeout + * Default: 3000 ms. + */ + heartbeatInterval?: HumanDuration | string; - /** - * (Optional) Maximum amount of bytes to accumulate in the response. Supported by Kafka >= 0.10.1.0 - * Default: 10485760 (10MB) - */ - maxBytes: number; + /** + * (Optional) The period of time after which we force a refresh of metadata + * even if we haven't seen any partition leadership changes to proactively discover any new brokers or partitions + * Default: 300000 ms (5 minutes). + */ + metadataMaxAge?: HumanDuration | string; - /** - * (Optional) The maximum amount of time the server will block before answering the fetch request - * if there isn’t sufficient data to immediately satisfy the requirement given by minBytes - * Default: 5000 - */ - maxWaitTime: HumanDuration | string; + /** + * (Optional) The maximum amount of data per-partition the server will return. + * This size must be at least as large as the maximum message size the server allows + * or else it is possible for the producer to send messages larger than the consumer can fetch. + * If that happens, the consumer can get stuck trying to fetch a large message on a certain partition + * Default: 1048576 (1MB) + */ + maxBytesPerPartition?: number; + + /** + * (Optional) Minimum amount of data the server should return for a fetch request, otherwise wait up to maxWaitTime for more data to accumulate. + * Default: 1 + */ + minBytes?: number; + + /** + * (Optional) Maximum amount of bytes to accumulate in the response. Supported by Kafka >= 0.10.1.0 + * Default: 10485760 (10MB) + */ + maxBytes?: number; + + /** + * (Optional) The maximum amount of time the server will block before answering the fetch request + * if there isn't sufficient data to immediately satisfy the requirement given by minBytes + * Default: 5000 + */ + maxWaitTime?: HumanDuration | string; + }; + }>; + } + | { + [name: string]: { + /** + * (Required) Client ID used by Backstage to identify when connecting to the Kafka cluster. + */ + clientId: string; + /** + * (Required) List of brokers in the Kafka cluster to connect to. + */ + brokers: string[]; + /** + * Optional SSL connection parameters to connect to the cluster. Passed directly to Node tls.connect. + * See https://nodejs.org/dist/latest-v8.x/docs/api/tls.html#tls_tls_createsecurecontext_options + */ + ssl?: + | { + ca?: string[]; + /** @visibility secret */ + key?: string; + cert?: string; + rejectUnauthorized?: boolean; + } + | boolean; + /** + * Optional SASL connection parameters. + */ + sasl?: { + mechanism: 'plain' | 'scram-sha-256' | 'scram-sha-512'; + username: string; + /** @visibility secret */ + password: string; + }; + + /** + * Optional retry connection parameters. + */ + retry?: { + /** + * (Optional) Maximum wait time for a retry + * Default: 30000 ms. + */ + maxRetryTime?: HumanDuration | string; + + /** + * (Optional) Initial value used to calculate the retry (This is still randomized following the randomization factor) + * Default: 300 ms. + */ + initialRetryTime?: HumanDuration | string; + + /** + * (Optional) Randomization factor + * Default: 0.2. + */ + factor?: number; + + /** + * (Optional) Exponential factor + * Default: 2. + */ + multiplier?: number; + + /** + * (Optional) Max number of retries per call + * Default: 5. + */ + retries?: number; + }; + + /** + * (Optional) Timeout for authentication requests. + * Default: 10000 ms. + */ + authenticationTimeout?: HumanDuration | string; + + /** + * (Optional) Time to wait for a successful connection. + * Default: 1000 ms. + */ + connectionTimeout?: HumanDuration | string; + + /** + * (Optional) Time to wait for a successful request. + * Default: 30000 ms. + */ + requestTimeout?: HumanDuration | string; + + /** + * (Optional) The request timeout can be disabled by setting enforceRequestTimeout to false. + * Default: true + */ + enforceRequestTimeout?: boolean; + + /** + * Contains an object per topic for which a Kafka queue + * should be used as source of events. + */ + topics: Array<{ + /** + * (Required) The Backstage topic to publish to + */ + topic: string; + /** + * (Required) KafkaConsumer-related configuration. + */ + kafka: { + /** + * (Required) The Kafka topics to subscribe to + */ + topics: string[]; + /** + * (Required) The GroupId to be used by the topic consumers + */ + groupId: string; + + /** + * (Optional) Timeout used to detect failures. + * The consumer sends periodic heartbeats to indicate its liveness to the broker. + * If no heartbeats are received by the broker before the expiration of this session timeout, + * then the broker will remove this consumer from the group and initiate a rebalance + * Default: 30000 ms. + */ + sessionTimeout?: HumanDuration | string; + + /** + * (Optional) The maximum time that the coordinator will wait for each member to rejoin when rebalancing the group + * Default: 60000 ms. + */ + rebalanceTimeout?: HumanDuration | string; + + /** + * (Optional) The expected time between heartbeats to the consumer coordinator. + * Heartbeats are used to ensure that the consumer's session stays active. + * The value must be set lower than session timeout + * Default: 3000 ms. + */ + heartbeatInterval?: HumanDuration | string; + + /** + * (Optional) The period of time after which we force a refresh of metadata + * even if we haven't seen any partition leadership changes to proactively discover any new brokers or partitions + * Default: 300000 ms (5 minutes). + */ + metadataMaxAge?: HumanDuration | string; + + /** + * (Optional) The maximum amount of data per-partition the server will return. + * This size must be at least as large as the maximum message size the server allows + * or else it is possible for the producer to send messages larger than the consumer can fetch. + * If that happens, the consumer can get stuck trying to fetch a large message on a certain partition + * Default: 1048576 (1MB) + */ + maxBytesPerPartition?: number; + + /** + * (Optional) Minimum amount of data the server should return for a fetch request, otherwise wait up to maxWaitTime for more data to accumulate. + * Default: 1 + */ + minBytes?: number; + + /** + * (Optional) Maximum amount of bytes to accumulate in the response. Supported by Kafka >= 0.10.1.0 + * Default: 10485760 (10MB) + */ + maxBytes?: number; + + /** + * (Optional) The maximum amount of time the server will block before answering the fetch request + * if there isn't sufficient data to immediately satisfy the requirement given by minBytes + * Default: 5000 + */ + maxWaitTime?: HumanDuration | string; + }; + }>; + }; }; - }>; + + /** + * Configuration for KafkaPublishingEventConsumer + * + * Supports multiple named instances as a record where each key is a unique name + * for the Kafka producer configuration. + */ + kafkaPublishingEventConsumer?: { + [name: string]: { + /** + * (Required) Client ID used by Backstage to identify when connecting to the Kafka cluster. + */ + clientId: string; + /** + * (Required) List of brokers in the Kafka cluster to connect to. + */ + brokers: string[]; + /** + * Optional SSL connection parameters to connect to the cluster. Passed directly to Node tls.connect. + * See https://nodejs.org/dist/latest-v8.x/docs/api/tls.html#tls_tls_createsecurecontext_options + */ + ssl?: + | { + ca?: string[]; + /** @visibility secret */ + key?: string; + cert?: string; + rejectUnauthorized?: boolean; + } + | boolean; + /** + * Optional SASL connection parameters. + */ + sasl?: { + mechanism: 'plain' | 'scram-sha-256' | 'scram-sha-512'; + username: string; + /** @visibility secret */ + password: string; + }; + + /** + * Optional retry connection parameters. + */ + retry?: { + /** + * (Optional) Maximum wait time for a retry + * Default: 30000 ms. + */ + maxRetryTime?: HumanDuration | string; + + /** + * (Optional) Initial value used to calculate the retry (This is still randomized following the randomization factor) + * Default: 300 ms. + */ + initialRetryTime?: HumanDuration | string; + + /** + * (Optional) Randomization factor + * Default: 0.2. + */ + factor?: number; + + /** + * (Optional) Exponential factor + * Default: 2. + */ + multiplier?: number; + + /** + * (Optional) Max number of retries per call + * Default: 5. + */ + retries?: number; + }; + + /** + * (Optional) Timeout for authentication requests. + * Default: 10000 ms. + */ + authenticationTimeout?: HumanDuration | string; + + /** + * (Optional) Time to wait for a successful connection. + * Default: 1000 ms. + */ + connectionTimeout?: HumanDuration | string; + + /** + * (Optional) Time to wait for a successful request. + * Default: 30000 ms. + */ + requestTimeout?: HumanDuration | string; + + /** + * (Optional) The request timeout can be disabled by setting enforceRequestTimeout to false. + * Default: true + */ + enforceRequestTimeout?: boolean; + + /** + * Contains an object per topic for which a Kafka queue + * should be used as destination for events. + */ + topics: Array<{ + /** + * (Required) The Backstage topic to consume from + */ + topic: string; + /** + * (Required) KafkaProducer-related configuration. + */ + kafka: { + /** + * (Required) The Kafka topic to publish to + */ + topic: string; + + /** + * (Optional) Allow topic creation when querying metadata for non-existent topics. + * Default: true + */ + allowAutoTopicCreation?: boolean; + + /** + * (Optional) The period of time after which we force a refresh of metadata + * even if we haven't seen any partition leadership changes to proactively discover any new brokers or partitions + * Default: 300000 ms (5 minutes). + */ + metadataMaxAge?: HumanDuration | string; + + /** + * (Optional) The maximum amount of time in ms that the transaction coordinator will wait for a transaction status update + * from the producer before proactively aborting the ongoing transaction. + * If this value is larger than the `transaction.max.timeout.ms`` setting in the broker, the request will fail with a `InvalidTransactionTimeout` error + * Default: 60000 ms. + */ + transactionTimeout?: HumanDuration | string; + + /** + * (Optional) Experimental. If enabled producer will ensure each message is written exactly once. Acks must be set to -1 ("all"). + * Retries will default to MAX_SAFE_INTEGER. + * Default: false. + */ + idempotent?: boolean; + + /** + * (Optional) Max number of requests that may be in progress at any time. If falsey then no limit. + * Default: null. + */ + maxInFlightRequests?: number; + + /** + * Optional retry connection parameters. + */ + retry?: { + /** + * (Optional) Maximum wait time for a retry + * Default: 30000 ms. + */ + maxRetryTime?: HumanDuration | string; + + /** + * (Optional) Initial value used to calculate the retry (This is still randomized following the randomization factor) + * Default: 300 ms. + */ + initialRetryTime?: HumanDuration | string; + + /** + * (Optional) Randomization factor + * Default: 0.2. + */ + factor?: number; + + /** + * (Optional) Exponential factor + * Default: 2. + */ + multiplier?: number; + + /** + * (Optional) Max number of retries per call + * Default: 5. + */ + retries?: number; + }; + }; + }>; + }; }; }; }; diff --git a/plugins/events-backend-module-kafka/package.json b/plugins/events-backend-module-kafka/package.json index a24538a617..d6e7b1ac0e 100644 --- a/plugins/events-backend-module-kafka/package.json +++ b/plugins/events-backend-module-kafka/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-kafka", - "version": "0.1.6-next.0", + "version": "0.2.0", "description": "The kafka backend module for the events plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/events-backend-module-kafka/report.api.md b/plugins/events-backend-module-kafka/report.api.md index a6b129b82e..c5e6d29c6a 100644 --- a/plugins/events-backend-module-kafka/report.api.md +++ b/plugins/events-backend-module-kafka/report.api.md @@ -6,6 +6,6 @@ import { BackendFeature } from '@backstage/backend-plugin-api'; // @public -const eventsModuleKafkaConsumingEventPublisher: BackendFeature; -export default eventsModuleKafkaConsumingEventPublisher; +const _default: BackendFeature; +export default _default; ``` diff --git a/plugins/events-backend-module-kafka/src/KafkaConsumingEventPublisher/KafkaConsumingEventPublisher.test.ts b/plugins/events-backend-module-kafka/src/KafkaConsumingEventPublisher/KafkaConsumingEventPublisher.test.ts new file mode 100644 index 0000000000..98781936b0 --- /dev/null +++ b/plugins/events-backend-module-kafka/src/KafkaConsumingEventPublisher/KafkaConsumingEventPublisher.test.ts @@ -0,0 +1,163 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { KafkaConsumingEventPublisher } from './KafkaConsumingEventPublisher'; +import { Kafka } from 'kafkajs'; +import { ConfigReader } from '@backstage/config'; +import { mockServices } from '@backstage/backend-test-utils'; + +jest.mock('kafkajs'); + +describe('KafkaConsumingEventPublisher', () => { + const mockLogger = mockServices.logger.mock(); + const mockEvents = mockServices.events.mock(); + + const mockConsumer = { + connect: jest.fn(), + disconnect: jest.fn(), + subscribe: jest.fn(), + run: jest.fn(), + }; + + const mockKafkaClient = { + consumer: jest.fn().mockReturnValue(mockConsumer), + } as unknown as Kafka; + + jest.mocked(Kafka).mockImplementation(() => mockKafkaClient); + + const mockConfig = new ConfigReader({ + events: { + modules: { + kafka: { + kafkaConsumingEventPublisher: { + dev: { + clientId: 'backstage-events', + brokers: ['kafka1:9092', 'kafka2:9092'], + topics: [ + { + topic: 'backstage-topic', + kafka: { + topics: ['test-topic'], + groupId: 'test-group', + }, + }, + ], + }, + }, + }, + }, + }, + }); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should create instances from config', () => { + const consumers = KafkaConsumingEventPublisher.fromConfig({ + config: mockConfig, + events: mockEvents, + logger: mockLogger, + }); + + expect(consumers).toBeInstanceOf(Array); + expect(consumers).toHaveLength(1); + expect(consumers[0]).toBeInstanceOf(KafkaConsumingEventPublisher); + }); + + it('should return empty array when no config', () => { + const consumers = KafkaConsumingEventPublisher.fromConfig({ + config: new ConfigReader({}), + events: mockEvents, + logger: mockLogger, + }); + + expect(consumers).toEqual([]); + }); + + it('should start all consumers', async () => { + const consumers = KafkaConsumingEventPublisher.fromConfig({ + config: mockConfig, + events: mockEvents, + logger: mockLogger, + }); + + expect(consumers).toHaveLength(1); + + await consumers[0].start(); + + expect(mockConsumer.connect).toHaveBeenCalled(); + expect(mockConsumer.subscribe).toHaveBeenCalledWith({ + topics: ['test-topic'], + }); + expect(mockConsumer.run).toHaveBeenCalled(); + }); + + it('should shutdown all consumers', async () => { + const consumers = KafkaConsumingEventPublisher.fromConfig({ + config: mockConfig, + events: mockEvents, + logger: mockLogger, + }); + + expect(consumers).toHaveLength(1); + + await consumers[0].shutdown(); + + expect(mockConsumer.disconnect).toHaveBeenCalled(); + }); + + it('should handle multiple consumer configs', () => { + const multiConsumerConfig = new ConfigReader({ + events: { + modules: { + kafka: { + kafkaConsumingEventPublisher: { + dev: { + clientId: 'backstage-events', + brokers: ['kafka1:9092'], + topics: [ + { + topic: 'topic1', + kafka: { + topics: ['kafka-topic-1'], + groupId: 'group1', + }, + }, + { + topic: 'topic2', + kafka: { + topics: ['kafka-topic-2'], + groupId: 'group2', + }, + }, + ], + }, + }, + }, + }, + }, + }); + + const consumers = KafkaConsumingEventPublisher.fromConfig({ + config: multiConsumerConfig, + events: mockEvents, + logger: mockLogger, + }); + + expect(consumers).toHaveLength(1); + expect(mockKafkaClient.consumer).toHaveBeenCalledTimes(2); + }); +}); diff --git a/plugins/events-backend-module-kafka/src/KafkaConsumingEventPublisher/KafkaConsumingEventPublisher.ts b/plugins/events-backend-module-kafka/src/KafkaConsumingEventPublisher/KafkaConsumingEventPublisher.ts new file mode 100644 index 0000000000..b996032575 --- /dev/null +++ b/plugins/events-backend-module-kafka/src/KafkaConsumingEventPublisher/KafkaConsumingEventPublisher.ts @@ -0,0 +1,109 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { LoggerService } from '@backstage/backend-plugin-api'; +import { EventsService } from '@backstage/plugin-events-node'; +import { Consumer, Kafka } from 'kafkajs'; +import { + KafkaConsumerConfig, + KafkaConsumingEventPublisherConfig, + readConsumerConfig, +} from './config'; +import { Config } from '@backstage/config'; +import { loggerServiceAdapter } from '../utils/LoggerServiceAdapter'; +import { convertHeadersToMetadata } from '../utils/kafkaTransformers'; + +type KafkaConsumer = { + consumer: Consumer; + config: KafkaConsumerConfig; +}; + +/** + * This class subscribes to Kafka topics and publishes events received to the registered subscriber. + * The message payload will be used as the event payload and passed to the subscribers. + */ +export class KafkaConsumingEventPublisher { + private readonly kafkaConsumers: KafkaConsumer[]; + private readonly logger: LoggerService; + + static fromConfig(env: { + config: Config; + events: EventsService; + logger: LoggerService; + }): KafkaConsumingEventPublisher[] { + const configs = readConsumerConfig(env.config, env.logger); + + return configs.map( + kafkaConfig => + new KafkaConsumingEventPublisher(env.logger, env.events, kafkaConfig), + ); + } + + private constructor( + logger: LoggerService, + private readonly events: EventsService, + config: KafkaConsumingEventPublisherConfig, + ) { + this.logger = logger.child({ + class: KafkaConsumingEventPublisher.prototype.constructor.name, + instance: config.instance, + }); + + const kafka = new Kafka({ + ...config.kafkaConfig, + logCreator: loggerServiceAdapter(this.logger), + }); + + this.kafkaConsumers = config.kafkaConsumerConfigs.map(consumerConfig => ({ + consumer: kafka.consumer(consumerConfig.consumerConfig), + config: consumerConfig, + })); + } + + async start(): Promise { + await Promise.all( + this.kafkaConsumers.map(async ({ consumer, config }) => { + const consumerLogger = this.logger.child({ + id: `events.kafka.publisher:${config.backstageTopic}`, + groupId: config.consumerConfig.groupId, + kafkaTopics: config.consumerSubscribeTopics.topics.toString(), + backstageTopic: config.backstageTopic, + }); + try { + await consumer.connect(); + await consumer.subscribe(config.consumerSubscribeTopics); + + await consumer.run({ + eachMessage: async ({ message }) => { + this.events.publish({ + topic: config.backstageTopic, + eventPayload: JSON.parse(message.value?.toString()!), + metadata: convertHeadersToMetadata(message.headers), + }); + }, + }); + } catch (error: any) { + consumerLogger.error('Kafka consumer connection failed', error); + } + }), + ); + } + + async shutdown(): Promise { + await Promise.all( + this.kafkaConsumers.map(({ consumer }) => consumer.disconnect()), + ); + } +} diff --git a/plugins/events-backend-module-kafka/src/KafkaConsumingEventPublisher/config.test.ts b/plugins/events-backend-module-kafka/src/KafkaConsumingEventPublisher/config.test.ts new file mode 100644 index 0000000000..16ee9e0a4c --- /dev/null +++ b/plugins/events-backend-module-kafka/src/KafkaConsumingEventPublisher/config.test.ts @@ -0,0 +1,354 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { ConfigReader } from '@backstage/config'; +import { readConsumerConfig } from './config'; +import { mockServices } from '@backstage/backend-test-utils'; + +const mockLogger = mockServices.logger.mock(); + +describe('readConsumerConfig', () => { + it('not configured', () => { + const publisherConfigs = readConsumerConfig( + new ConfigReader({}), + mockLogger, + ); + + expect(publisherConfigs).toEqual([]); + }); + + it('only required fields configured', () => { + const config = new ConfigReader({ + events: { + modules: { + kafka: { + kafkaConsumingEventPublisher: { + dev: { + clientId: 'backstage-events', + brokers: ['kafka1:9092', 'kafka2:9092'], + topics: [ + { + topic: 'fake1', + kafka: { + topics: ['topic-A'], + groupId: 'my-group', + }, + }, + { + topic: 'fake2', + kafka: { + topics: ['topic-B'], + groupId: 'my-group', + }, + }, + ], + }, + }, + }, + }, + }, + }); + + const publisherConfigs = readConsumerConfig(config, mockLogger); + + expect(publisherConfigs).toBeDefined(); + expect(Array.isArray(publisherConfigs)).toBe(true); + expect(publisherConfigs).toHaveLength(1); + + const devConfig = publisherConfigs[0]; + expect(devConfig.instance).toBe('dev'); + expect(devConfig.kafkaConsumerConfigs.length).toBe(2); + + expect(devConfig.kafkaConfig.clientId).toEqual('backstage-events'); + expect(devConfig.kafkaConfig.brokers).toEqual([ + 'kafka1:9092', + 'kafka2:9092', + ]); + + expect(devConfig.kafkaConsumerConfigs).toEqual([ + { + backstageTopic: 'fake1', + consumerConfig: { + groupId: 'my-group', + }, + consumerSubscribeTopics: { + topics: ['topic-A'], + }, + }, + { + backstageTopic: 'fake2', + consumerConfig: { + groupId: 'my-group', + }, + consumerSubscribeTopics: { + topics: ['topic-B'], + }, + }, + ]); + }); + + it('all fields configured', () => { + const config = new ConfigReader({ + events: { + modules: { + kafka: { + kafkaConsumingEventPublisher: { + dev: { + clientId: 'backstage-events', + brokers: ['kafka1:9092', 'kafka2:9092'], + ssl: true, + sasl: { + mechanism: 'plain', + username: 'username', + password: 'password', + }, + retry: { + maxRetryTime: { milliseconds: 20000 }, + initialRetryTime: { milliseconds: 200 }, + factor: '0.4', + multiplier: '4', + retries: '10', + }, + authenticationTimeout: { milliseconds: 20000 }, + connectionTimeout: { milliseconds: 1500 }, + requestTimeout: { milliseconds: 20000 }, + enforceRequestTimeout: false, + topics: [ + { + topic: 'fake1', + kafka: { + topics: ['topic-A'], + groupId: 'my-group', + sessionTimeout: { milliseconds: 20000 }, + rebalanceTimeout: { milliseconds: 50000 }, + heartbeatInterval: { milliseconds: 2000 }, + metadataMaxAge: { milliseconds: 400000 }, + maxBytesPerPartition: 50000, + minBytes: 2, + maxBytes: 500000, + maxWaitTime: { milliseconds: 4000 }, + }, + }, + { + topic: 'fake2', + kafka: { + topics: ['topic-B'], + groupId: 'my-group', + }, + }, + ], + }, + }, + }, + }, + }, + }); + + const publisherConfigs = readConsumerConfig(config, mockLogger); + + expect(publisherConfigs).toBeDefined(); + expect(Array.isArray(publisherConfigs)).toBe(true); + expect(publisherConfigs).toHaveLength(1); + + const devConfig = publisherConfigs[0]; + expect(devConfig.instance).toBe('dev'); + + // Client configuration + expect(devConfig.kafkaConfig.clientId).toEqual('backstage-events'); + expect(devConfig.kafkaConfig.brokers).toEqual([ + 'kafka1:9092', + 'kafka2:9092', + ]); + expect(devConfig.kafkaConfig.ssl).toBeTruthy(); + expect(devConfig.kafkaConfig.sasl).toStrictEqual({ + mechanism: 'plain', + username: 'username', + password: 'password', + }); + expect(devConfig.kafkaConfig.authenticationTimeout).toBe(20000); + expect(devConfig.kafkaConfig.connectionTimeout).toBe(1500); + expect(devConfig.kafkaConfig.requestTimeout).toBe(20000); + expect(devConfig.kafkaConfig.enforceRequestTimeout).toBeFalsy(); + expect(devConfig.kafkaConfig.retry).toStrictEqual({ + maxRetryTime: 20000, + initialRetryTime: 200, + factor: 0.4, + multiplier: 4, + retries: 10, + }); + + // Consumer configuration + expect(devConfig.kafkaConsumerConfigs.length).toBe(2); + + expect(devConfig.kafkaConsumerConfigs).toEqual([ + { + backstageTopic: 'fake1', + consumerConfig: { + groupId: 'my-group', + sessionTimeout: 20000, + rebalanceTimeout: 50000, + heartbeatInterval: 2000, + metadataMaxAge: 400000, + maxBytesPerPartition: 50000, + minBytes: 2, + maxBytes: 500000, + maxWaitTimeInMs: 4000, + }, + consumerSubscribeTopics: { + topics: ['topic-A'], + }, + }, + { + backstageTopic: 'fake2', + consumerConfig: { + groupId: 'my-group', + }, + consumerSubscribeTopics: { + topics: ['topic-B'], + }, + }, + ]); + }); + + it('should handle HumanDuration and string values for durations and timeouts', () => { + const config = new ConfigReader({ + events: { + modules: { + kafka: { + kafkaConsumingEventPublisher: { + dev: { + clientId: 'backstage-events', + brokers: ['kafka1:9092', 'kafka2:9092'], + retry: { + maxRetryTime: { seconds: 1 }, + initialRetryTime: { minutes: 1 }, + factor: 0.4, + multiplier: 4, + retries: 10, + }, + authenticationTimeout: { hours: 1 }, + connectionTimeout: { days: 1 }, + topics: [], + requestTimeout: '1m', + }, + }, + }, + }, + }, + }); + + const publisherConfigs = readConsumerConfig(config, mockLogger); + + expect(publisherConfigs).toBeDefined(); + expect(Array.isArray(publisherConfigs)).toBe(true); + expect(publisherConfigs).toHaveLength(1); + + const devConfig = publisherConfigs[0]; + expect(devConfig.instance).toBe('dev'); + + // Client configuration + expect(devConfig.kafkaConfig.clientId).toEqual('backstage-events'); + expect(devConfig.kafkaConfig.brokers).toEqual([ + 'kafka1:9092', + 'kafka2:9092', + ]); + expect(devConfig.kafkaConfig.authenticationTimeout).toBe(3600000); + expect(devConfig.kafkaConfig.connectionTimeout).toBe(86400000); + expect(devConfig.kafkaConfig.requestTimeout).toBe(60000); + expect(devConfig.kafkaConfig.retry).toStrictEqual({ + maxRetryTime: 1000, + initialRetryTime: 60000, + factor: 0.4, + multiplier: 4, + retries: 10, + }); + + // Consumer configuration + expect(devConfig.kafkaConsumerConfigs.length).toBe(0); + }); + + it('single instance configuration (legacy format)', () => { + const config = new ConfigReader({ + events: { + modules: { + kafka: { + kafkaConsumingEventPublisher: { + clientId: 'backstage-events', + brokers: ['kafka1:9092', 'kafka2:9092'], + topics: [ + { + topic: 'fake1', + kafka: { + topics: ['topic-A'], + groupId: 'my-group', + }, + }, + { + topic: 'fake2', + kafka: { + topics: ['topic-B'], + groupId: 'my-group', + }, + }, + ], + }, + }, + }, + }, + }); + + const publisherConfigs = readConsumerConfig(config, mockLogger); + + expect(publisherConfigs).toBeDefined(); + expect(Array.isArray(publisherConfigs)).toBe(true); + expect(publisherConfigs).toHaveLength(1); + + const defaultConfig = publisherConfigs[0]; + expect(defaultConfig.instance).toBe('default'); + expect(defaultConfig.kafkaConsumerConfigs.length).toBe(2); + + expect(defaultConfig.kafkaConfig.clientId).toEqual('backstage-events'); + expect(defaultConfig.kafkaConfig.brokers).toEqual([ + 'kafka1:9092', + 'kafka2:9092', + ]); + + expect(defaultConfig.kafkaConsumerConfigs).toEqual([ + { + backstageTopic: 'fake1', + consumerConfig: { + groupId: 'my-group', + }, + consumerSubscribeTopics: { + topics: ['topic-A'], + }, + }, + { + backstageTopic: 'fake2', + consumerConfig: { + groupId: 'my-group', + }, + consumerSubscribeTopics: { + topics: ['topic-B'], + }, + }, + ]); + + // Verify deprecation warning was logged + expect(mockLogger.warn).toHaveBeenCalledWith( + 'Legacy single config format detected at events.modules.kafka.kafkaConsumingEventPublisher.', + ); + }); +}); diff --git a/plugins/events-backend-module-kafka/src/KafkaConsumingEventPublisher/config.ts b/plugins/events-backend-module-kafka/src/KafkaConsumingEventPublisher/config.ts new file mode 100644 index 0000000000..b07378a1d6 --- /dev/null +++ b/plugins/events-backend-module-kafka/src/KafkaConsumingEventPublisher/config.ts @@ -0,0 +1,116 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { Config } from '@backstage/config'; +import { ConsumerConfig, ConsumerSubscribeTopics, KafkaConfig } from 'kafkajs'; +import { + readKafkaConfig, + readOptionalHumanDurationInMs, +} from '../utils/config'; +import { LoggerService } from '@backstage/backend-plugin-api'; + +export interface KafkaConsumerConfig { + backstageTopic: string; + consumerConfig: ConsumerConfig; + consumerSubscribeTopics: ConsumerSubscribeTopics; +} + +export interface KafkaConsumingEventPublisherConfig { + instance: string; + kafkaConfig: KafkaConfig; + kafkaConsumerConfigs: KafkaConsumerConfig[]; +} + +const CONFIG_PREFIX_PUBLISHER = + 'events.modules.kafka.kafkaConsumingEventPublisher'; + +const processSinglePublisher = ( + instanceName: string, + publisherConfig: Config, +): KafkaConsumingEventPublisherConfig => { + return { + instance: instanceName, + kafkaConfig: readKafkaConfig(publisherConfig), + kafkaConsumerConfigs: publisherConfig + .getConfigArray('topics') + .map(topicConfig => { + return { + backstageTopic: topicConfig.getString('topic'), + consumerConfig: { + groupId: topicConfig.getString('kafka.groupId'), + sessionTimeout: readOptionalHumanDurationInMs( + topicConfig, + 'kafka.sessionTimeout', + ), + rebalanceTimeout: readOptionalHumanDurationInMs( + topicConfig, + 'kafka.rebalanceTimeout', + ), + heartbeatInterval: readOptionalHumanDurationInMs( + topicConfig, + 'kafka.heartbeatInterval', + ), + metadataMaxAge: readOptionalHumanDurationInMs( + topicConfig, + 'kafka.metadataMaxAge', + ), + maxBytesPerPartition: topicConfig.getOptionalNumber( + 'kafka.maxBytesPerPartition', + ), + minBytes: topicConfig.getOptionalNumber('kafka.minBytes'), + maxBytes: topicConfig.getOptionalNumber('kafka.maxBytes'), + maxWaitTimeInMs: readOptionalHumanDurationInMs( + topicConfig, + 'kafka.maxWaitTime', + ), + }, + consumerSubscribeTopics: { + topics: topicConfig.getStringArray('kafka.topics'), + }, + }; + }), + }; +}; + +export const readConsumerConfig = ( + config: Config, + logger: LoggerService, +): KafkaConsumingEventPublisherConfig[] => { + const publishersConfig = config.getOptionalConfig(CONFIG_PREFIX_PUBLISHER); + + // Check for legacy single publisher format + if (publishersConfig?.getOptionalString('clientId')) { + logger.warn( + 'Legacy single config format detected at events.modules.kafka.kafkaConsumingEventPublisher.', + ); + return [ + processSinglePublisher( + 'default', // use `default` as instance name for legacy single config + publishersConfig, + ), + ]; + } + + return ( + publishersConfig + ?.keys() + ?.map(publisherKey => + processSinglePublisher( + publisherKey, + publishersConfig.getConfig(publisherKey), + ), + ) ?? [] + ); +}; diff --git a/plugins/events-backend-module-kafka/src/KafkaConsumingEventPublisher/index.ts b/plugins/events-backend-module-kafka/src/KafkaConsumingEventPublisher/index.ts new file mode 100644 index 0000000000..94d36a81e0 --- /dev/null +++ b/plugins/events-backend-module-kafka/src/KafkaConsumingEventPublisher/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { eventsModuleKafkaConsumingEventPublisher } from './module'; diff --git a/plugins/events-backend-module-kafka/src/KafkaConsumingEventPublisher/module.test.ts b/plugins/events-backend-module-kafka/src/KafkaConsumingEventPublisher/module.test.ts new file mode 100644 index 0000000000..19ac969800 --- /dev/null +++ b/plugins/events-backend-module-kafka/src/KafkaConsumingEventPublisher/module.test.ts @@ -0,0 +1,122 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { createServiceFactory } from '@backstage/backend-plugin-api'; +import { mockServices, startTestBackend } from '@backstage/backend-test-utils'; +import { eventsServiceRef } from '@backstage/plugin-events-node'; +import { TestEventsService } from '@backstage/plugin-events-backend-test-utils'; +import { eventsModuleKafkaConsumingEventPublisher } from './module'; +import { KafkaConsumingEventPublisher } from './KafkaConsumingEventPublisher'; + +jest.mock('./KafkaConsumingEventPublisher'); + +describe('eventsModuleKafkaConsumingEventPublisher', () => { + it('should be correctly wired and set up', async () => { + const events = new TestEventsService(); + const eventsServiceFactory = createServiceFactory({ + service: eventsServiceRef, + deps: {}, + async factory({}) { + return events; + }, + }); + + const mockKafkaConsumingEventPublisher = { + start: jest.fn(), + shutdown: jest.fn(), + } as unknown as KafkaConsumingEventPublisher; + + jest + .mocked(KafkaConsumingEventPublisher.fromConfig) + .mockReturnValue([mockKafkaConsumingEventPublisher]); + + await startTestBackend({ + features: [ + eventsServiceFactory, + eventsModuleKafkaConsumingEventPublisher, + mockServices.rootConfig.factory({ + data: { + events: { + modules: { + kafka: { + kafkaConsumingEventPublisher: { + dev: { + clientId: 'backstage-events', + brokers: ['kafka1:9092', 'kafka2:9092'], + topics: { + fake1: { + kafka: { + topics: ['topic-A'], + groupId: 'my-group', + }, + }, + fake2: { + kafka: { + topics: ['topic-B'], + groupId: 'my-group', + }, + }, + }, + }, + }, + }, + }, + }, + }, + }), + ], + }); + + // Verify that the Kafka consumer client was started + expect(mockKafkaConsumingEventPublisher.start).toHaveBeenCalled(); + + // Verify that the shutdown hook was registered + expect(mockKafkaConsumingEventPublisher.shutdown).not.toHaveBeenCalled(); + }); + + it('should handle empty configuration gracefully', async () => { + const events = new TestEventsService(); + const eventsServiceFactory = createServiceFactory({ + service: eventsServiceRef, + deps: {}, + async factory({}) { + return events; + }, + }); + + jest.mocked(KafkaConsumingEventPublisher.fromConfig).mockReturnValue([]); + + await startTestBackend({ + features: [ + eventsServiceFactory, + eventsModuleKafkaConsumingEventPublisher, + mockServices.rootConfig.factory({ + data: { + events: { + modules: { + kafka: { + // No kafkaConsumingEventPublisher config + }, + }, + }, + }, + }), + ], + }); + + // Verify that fromConfig was called but returned empty array + expect(KafkaConsumingEventPublisher.fromConfig).toHaveBeenCalled(); + }); +}); diff --git a/plugins/events-backend-module-kafka/src/service/eventsModuleKafkaConsumingEventPublisher.ts b/plugins/events-backend-module-kafka/src/KafkaConsumingEventPublisher/module.ts similarity index 69% rename from plugins/events-backend-module-kafka/src/service/eventsModuleKafkaConsumingEventPublisher.ts rename to plugins/events-backend-module-kafka/src/KafkaConsumingEventPublisher/module.ts index b524454ca0..8ad3396c76 100644 --- a/plugins/events-backend-module-kafka/src/service/eventsModuleKafkaConsumingEventPublisher.ts +++ b/plugins/events-backend-module-kafka/src/KafkaConsumingEventPublisher/module.ts @@ -17,11 +17,11 @@ import { coreServices, createBackendModule, } from '@backstage/backend-plugin-api'; -import { KafkaConsumerClient } from '../publisher/KafkaConsumerClient'; import { eventsServiceRef } from '@backstage/plugin-events-node'; +import { KafkaConsumingEventPublisher } from './KafkaConsumingEventPublisher'; /** - * Kafka module for the Events plugin. + * Reads messages off of Kafka topics and forwards them into the Backstage events system. * * @public */ @@ -34,22 +34,22 @@ export const eventsModuleKafkaConsumingEventPublisher = createBackendModule({ config: coreServices.rootConfig, events: eventsServiceRef, logger: coreServices.logger, - lifecycle: coreServices.lifecycle, + lifecycle: coreServices.rootLifecycle, }, async init({ config, logger, events, lifecycle }) { - const kafka = KafkaConsumerClient.fromConfig({ + const consumers = KafkaConsumingEventPublisher.fromConfig({ config, events, logger, }); - if (!kafka) { - return; - } + lifecycle.addStartupHook(async () => { + await Promise.all(consumers.map(consumer => consumer.start())); + }); - await kafka.start(); - - lifecycle.addShutdownHook(async () => await kafka.shutdown()); + lifecycle.addShutdownHook(async () => { + await Promise.all(consumers.map(consumer => consumer.shutdown())); + }); }, }); }, diff --git a/plugins/events-backend-module-kafka/src/KafkaPublishingEventConsumer/KafkaPublishingEventConsumer.test.ts b/plugins/events-backend-module-kafka/src/KafkaPublishingEventConsumer/KafkaPublishingEventConsumer.test.ts new file mode 100644 index 0000000000..6379605901 --- /dev/null +++ b/plugins/events-backend-module-kafka/src/KafkaPublishingEventConsumer/KafkaPublishingEventConsumer.test.ts @@ -0,0 +1,106 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { KafkaPublishingEventConsumer } from './KafkaPublishingEventConsumer'; +import { Kafka } from 'kafkajs'; +import { mockServices } from '@backstage/backend-test-utils'; +import { ConfigReader } from '@backstage/config'; + +jest.mock('kafkajs'); + +describe('KafkaPublishingEventConsumer', () => { + const mockLogger = mockServices.logger.mock(); + const mockEvents = mockServices.events.mock(); + + const mockProducer = { + connect: jest.fn(), + disconnect: jest.fn(), + send: jest.fn(), + }; + + const mockKafkaClient = { + producer: jest.fn().mockReturnValue(mockProducer), + } as unknown as Kafka; + + jest.mocked(Kafka).mockImplementation(() => mockKafkaClient); + + const mockConfig = new ConfigReader({ + events: { + modules: { + kafka: { + kafkaPublishingEventConsumer: { + dev: { + clientId: 'backstage-events', + brokers: ['kafka1:9092'], + topics: [ + { + topic: 'backstage-topic', + kafka: { + topic: 'kafka-topic', + allowAutoTopicCreation: true, + }, + }, + ], + }, + }, + }, + }, + }, + }); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should create instances from config', () => { + const consumers = KafkaPublishingEventConsumer.fromConfig({ + config: mockConfig, + events: mockEvents, + logger: mockLogger, + }); + + expect(consumers).toHaveLength(1); + expect(consumers[0]).toBeInstanceOf(KafkaPublishingEventConsumer); + }); + + it('should start the consumer and subscribe to events', async () => { + const consumers = KafkaPublishingEventConsumer.fromConfig({ + config: mockConfig, + events: mockEvents, + logger: mockLogger, + }); + + await consumers[0].start(); + + expect(mockProducer.connect).toHaveBeenCalled(); + expect(mockEvents.subscribe).toHaveBeenCalledWith({ + id: 'kafka:publisher:backstage-topic', + topics: ['backstage-topic'], + onEvent: expect.any(Function), + }); + }); + + it('should shutdown the producer', async () => { + const consumers = KafkaPublishingEventConsumer.fromConfig({ + config: mockConfig, + events: mockEvents, + logger: mockLogger, + }); + + await consumers[0].shutdown(); + + expect(mockProducer.disconnect).toHaveBeenCalled(); + }); +}); diff --git a/plugins/events-backend-module-kafka/src/KafkaPublishingEventConsumer/KafkaPublishingEventConsumer.ts b/plugins/events-backend-module-kafka/src/KafkaPublishingEventConsumer/KafkaPublishingEventConsumer.ts new file mode 100644 index 0000000000..f9443f2d69 --- /dev/null +++ b/plugins/events-backend-module-kafka/src/KafkaPublishingEventConsumer/KafkaPublishingEventConsumer.ts @@ -0,0 +1,115 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { LoggerService } from '@backstage/backend-plugin-api'; +import { EventParams, EventsService } from '@backstage/plugin-events-node'; +import { Kafka, Producer } from 'kafkajs'; +import { + KafkaPublisherConfig, + KafkaPublishingEventConsumerConfig, + readPublisherConfig, +} from './config'; +import { Config } from '@backstage/config'; +import { loggerServiceAdapter } from '../utils/LoggerServiceAdapter'; +import { payloadToBuffer } from '../utils/kafkaTransformers'; + +type KafkaPublisher = { + producer: Producer; + config: KafkaPublisherConfig; +}; + +/** + * This class subscribes to Backstage internal events and publishes them to Kafka topics. + * The internal event payload will be serialized and sent to the configured Kafka topic. + */ +export class KafkaPublishingEventConsumer { + private readonly kafkaPublishers: KafkaPublisher[]; + private readonly logger: LoggerService; + + static fromConfig(env: { + config: Config; + events: EventsService; + logger: LoggerService; + }): KafkaPublishingEventConsumer[] { + const configs = readPublisherConfig(env.config); + + return configs.map( + kafkaConfig => + new KafkaPublishingEventConsumer(env.logger, env.events, kafkaConfig), + ); + } + + private constructor( + logger: LoggerService, + private readonly events: EventsService, + config: KafkaPublishingEventConsumerConfig, + ) { + this.logger = logger.child({ + class: KafkaPublishingEventConsumer.prototype.constructor.name, + instance: config.instance, + }); + + const kafka = new Kafka({ + ...config.kafkaConfig, + logCreator: loggerServiceAdapter(this.logger), + }); + + this.kafkaPublishers = config.kafkaPublisherConfigs.map( + publisherConfig => ({ + producer: kafka.producer(publisherConfig.producerConfig), + config: publisherConfig, + }), + ); + } + + async start(): Promise { + await Promise.all( + this.kafkaPublishers.map(async ({ producer, config }) => { + try { + await producer.connect(); + + this.events.subscribe({ + id: `kafka:publisher:${config.backstageTopic}`, + topics: [config.backstageTopic], + onEvent: async (params: EventParams) => { + await producer.send({ + topic: config.kafkaTopic, + messages: [ + { + value: payloadToBuffer(params.eventPayload), + }, + ], + }); + }, + }); + this.logger.info( + `Subscribed to EventService, publishing events to external topic: ${config.backstageTopic}`, + ); + } catch (error: any) { + this.logger.error( + `Kafka producer connection failed for topic ${config.backstageTopic}`, + error, + ); + } + }), + ); + } + + async shutdown(): Promise { + await Promise.all( + this.kafkaPublishers.map(({ producer }) => producer.disconnect()), + ); + } +} diff --git a/plugins/events-backend-module-kafka/src/KafkaPublishingEventConsumer/config.test.ts b/plugins/events-backend-module-kafka/src/KafkaPublishingEventConsumer/config.test.ts new file mode 100644 index 0000000000..bd4d622238 --- /dev/null +++ b/plugins/events-backend-module-kafka/src/KafkaPublishingEventConsumer/config.test.ts @@ -0,0 +1,360 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { ConfigReader } from '@backstage/config'; +import { readPublisherConfig } from './config'; + +describe('readPublisherConfig', () => { + it('not configured', () => { + const publisherConfigs = readPublisherConfig(new ConfigReader({})); + + expect(publisherConfigs).toEqual([]); + }); + + it('only required fields configured', () => { + const config = new ConfigReader({ + events: { + modules: { + kafka: { + kafkaPublishingEventConsumer: { + dev: { + clientId: 'backstage-events', + brokers: ['kafka1:9092', 'kafka2:9092'], + topics: [ + { + topic: 'fake1', + kafka: { + topic: 'topic-A', + }, + }, + { + topic: 'fake2', + kafka: { + topic: 'topic-B', + }, + }, + ], + }, + }, + }, + }, + }, + }); + + const publisherConfigs = readPublisherConfig(config); + + expect(publisherConfigs).toBeDefined(); + expect(Array.isArray(publisherConfigs)).toBe(true); + expect(publisherConfigs).toHaveLength(1); + + const devConfig = publisherConfigs[0]; + expect(devConfig.instance).toBe('dev'); + expect(devConfig.kafkaPublisherConfigs.length).toBe(2); + + expect(devConfig.kafkaConfig.clientId).toEqual('backstage-events'); + expect(devConfig.kafkaConfig.brokers).toEqual([ + 'kafka1:9092', + 'kafka2:9092', + ]); + + expect(devConfig.kafkaPublisherConfigs).toEqual([ + { + backstageTopic: 'fake1', + kafkaTopic: 'topic-A', + producerConfig: { + allowAutoTopicCreation: undefined, + metadataMaxAge: undefined, + transactionTimeout: undefined, + idempotent: undefined, + maxInFlightRequests: undefined, + retry: {}, + }, + }, + { + backstageTopic: 'fake2', + kafkaTopic: 'topic-B', + producerConfig: { + allowAutoTopicCreation: undefined, + metadataMaxAge: undefined, + transactionTimeout: undefined, + idempotent: undefined, + maxInFlightRequests: undefined, + retry: {}, + }, + }, + ]); + }); + + it('all fields configured', () => { + const config = new ConfigReader({ + events: { + modules: { + kafka: { + kafkaPublishingEventConsumer: { + dev: { + clientId: 'backstage-events', + brokers: ['kafka1:9092', 'kafka2:9092'], + ssl: true, + sasl: { + mechanism: 'plain', + username: 'username', + password: 'password', + }, + retry: { + maxRetryTime: { milliseconds: 20000 }, + initialRetryTime: { milliseconds: 200 }, + factor: '0.4', + multiplier: '4', + retries: '10', + }, + authenticationTimeout: { milliseconds: 20000 }, + connectionTimeout: { milliseconds: 1500 }, + requestTimeout: { milliseconds: 20000 }, + enforceRequestTimeout: false, + topics: [ + { + topic: 'fake1', + kafka: { + topic: 'topic-A', + allowAutoTopicCreation: true, + metadataMaxAge: { milliseconds: 400000 }, + transactionTimeout: { milliseconds: 30000 }, + idempotent: true, + maxInFlightRequests: 5, + retry: { + maxRetryTime: { milliseconds: 15000 }, + initialRetryTime: { milliseconds: 100 }, + factor: '0.2', + multiplier: '2', + retries: '5', + }, + }, + }, + { + topic: 'fake2', + kafka: { + topic: 'topic-B', + }, + }, + ], + }, + }, + }, + }, + }, + }); + + const publisherConfigs = readPublisherConfig(config); + + expect(publisherConfigs).toBeDefined(); + expect(Array.isArray(publisherConfigs)).toBe(true); + expect(publisherConfigs).toHaveLength(1); + + const devConfig = publisherConfigs[0]; + expect(devConfig.instance).toBe('dev'); + + // Client configuration + expect(devConfig.kafkaConfig.clientId).toEqual('backstage-events'); + expect(devConfig.kafkaConfig.brokers).toEqual([ + 'kafka1:9092', + 'kafka2:9092', + ]); + expect(devConfig.kafkaConfig.ssl).toBeTruthy(); + expect(devConfig.kafkaConfig.sasl).toStrictEqual({ + mechanism: 'plain', + username: 'username', + password: 'password', + }); + expect(devConfig.kafkaConfig.authenticationTimeout).toBe(20000); + expect(devConfig.kafkaConfig.connectionTimeout).toBe(1500); + expect(devConfig.kafkaConfig.requestTimeout).toBe(20000); + expect(devConfig.kafkaConfig.enforceRequestTimeout).toBeFalsy(); + expect(devConfig.kafkaConfig.retry).toStrictEqual({ + maxRetryTime: 20000, + initialRetryTime: 200, + factor: 0.4, + multiplier: 4, + retries: 10, + }); + + // Publisher configuration + expect(devConfig.kafkaPublisherConfigs.length).toBe(2); + + expect(devConfig.kafkaPublisherConfigs).toEqual([ + { + backstageTopic: 'fake1', + kafkaTopic: 'topic-A', + producerConfig: { + allowAutoTopicCreation: true, + metadataMaxAge: 400000, + transactionTimeout: 30000, + idempotent: true, + maxInFlightRequests: 5, + retry: { + maxRetryTime: 15000, + initialRetryTime: 100, + factor: 0.2, + multiplier: 2, + retries: 5, + }, + }, + }, + { + backstageTopic: 'fake2', + kafkaTopic: 'topic-B', + producerConfig: { + allowAutoTopicCreation: undefined, + metadataMaxAge: undefined, + transactionTimeout: undefined, + idempotent: undefined, + maxInFlightRequests: undefined, + retry: {}, + }, + }, + ]); + }); + + it('should handle HumanDuration and string values for durations and timeouts', () => { + const config = new ConfigReader({ + events: { + modules: { + kafka: { + kafkaPublishingEventConsumer: { + dev: { + clientId: 'backstage-events', + brokers: ['kafka1:9092', 'kafka2:9092'], + retry: { + maxRetryTime: { seconds: 1 }, + initialRetryTime: { minutes: 1 }, + factor: 0.4, + multiplier: 4, + retries: 10, + }, + authenticationTimeout: { hours: 1 }, + connectionTimeout: { days: 1 }, + topics: [ + { + topic: 'fake1', + kafka: { + topic: 'topic-A', + metadataMaxAge: { seconds: 300 }, + transactionTimeout: '30s', + }, + }, + ], + requestTimeout: '1m', + }, + }, + }, + }, + }, + }); + + const publisherConfigs = readPublisherConfig(config); + + expect(publisherConfigs).toBeDefined(); + expect(Array.isArray(publisherConfigs)).toBe(true); + expect(publisherConfigs).toHaveLength(1); + + const devConfig = publisherConfigs[0]; + expect(devConfig.instance).toBe('dev'); + + // Client configuration + expect(devConfig.kafkaConfig.clientId).toEqual('backstage-events'); + expect(devConfig.kafkaConfig.brokers).toEqual([ + 'kafka1:9092', + 'kafka2:9092', + ]); + expect(devConfig.kafkaConfig.authenticationTimeout).toBe(3600000); + expect(devConfig.kafkaConfig.connectionTimeout).toBe(86400000); + expect(devConfig.kafkaConfig.requestTimeout).toBe(60000); + expect(devConfig.kafkaConfig.retry).toStrictEqual({ + maxRetryTime: 1000, + initialRetryTime: 60000, + factor: 0.4, + multiplier: 4, + retries: 10, + }); + + // Publisher configuration + expect(devConfig.kafkaPublisherConfigs.length).toBe(1); + expect( + devConfig.kafkaPublisherConfigs[0].producerConfig.metadataMaxAge, + ).toBe(300000); + expect( + devConfig.kafkaPublisherConfigs[0].producerConfig.transactionTimeout, + ).toBe(30000); + }); + + it('should handle multiple instances', () => { + const config = new ConfigReader({ + events: { + modules: { + kafka: { + kafkaPublishingEventConsumer: { + dev: { + clientId: 'backstage-dev', + brokers: ['kafka-dev:9092'], + topics: [ + { + topic: 'dev-topic', + kafka: { + topic: 'kafka-dev-topic', + }, + }, + ], + }, + prod: { + clientId: 'backstage-prod', + brokers: ['kafka-prod1:9092', 'kafka-prod2:9092'], + topics: [ + { + topic: 'prod-topic', + kafka: { + topic: 'kafka-prod-topic', + }, + }, + ], + }, + }, + }, + }, + }, + }); + + const publisherConfigs = readPublisherConfig(config); + + expect(publisherConfigs).toBeDefined(); + expect(Array.isArray(publisherConfigs)).toBe(true); + expect(publisherConfigs).toHaveLength(2); + + const devConfig = publisherConfigs.find(c => c.instance === 'dev')!; + expect(devConfig.kafkaConfig.clientId).toBe('backstage-dev'); + expect(devConfig.kafkaConfig.brokers).toEqual(['kafka-dev:9092']); + expect(devConfig.kafkaPublisherConfigs).toHaveLength(1); + expect(devConfig.kafkaPublisherConfigs[0].backstageTopic).toBe('dev-topic'); + + const prodConfig = publisherConfigs.find(c => c.instance === 'prod')!; + expect(prodConfig.kafkaConfig.clientId).toBe('backstage-prod'); + expect(prodConfig.kafkaConfig.brokers).toEqual([ + 'kafka-prod1:9092', + 'kafka-prod2:9092', + ]); + expect(prodConfig.kafkaPublisherConfigs).toHaveLength(1); + expect(prodConfig.kafkaPublisherConfigs[0].backstageTopic).toBe( + 'prod-topic', + ); + }); +}); diff --git a/plugins/events-backend-module-kafka/src/KafkaPublishingEventConsumer/config.ts b/plugins/events-backend-module-kafka/src/KafkaPublishingEventConsumer/config.ts new file mode 100644 index 0000000000..8439e24405 --- /dev/null +++ b/plugins/events-backend-module-kafka/src/KafkaPublishingEventConsumer/config.ts @@ -0,0 +1,82 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { Config } from '@backstage/config'; +import { + readKafkaConfig, + readOptionalHumanDurationInMs, + readRetryConfig, +} from '../utils/config'; +import { KafkaConfig, ProducerConfig } from 'kafkajs'; + +export interface KafkaPublisherConfig { + backstageTopic: string; + kafkaTopic: string; + producerConfig: ProducerConfig; +} + +export interface KafkaPublishingEventConsumerConfig { + instance: string; + kafkaConfig: KafkaConfig; + kafkaPublisherConfigs: KafkaPublisherConfig[]; +} + +const CONFIG_PREFIX_PUBLISHER = + 'events.modules.kafka.kafkaPublishingEventConsumer'; + +export const readPublisherConfig = ( + config: Config, +): KafkaPublishingEventConsumerConfig[] => { + const publishers = config.getOptionalConfig(CONFIG_PREFIX_PUBLISHER); + + return ( + publishers?.keys()?.map(publisherKey => { + const publisherConfig = publishers.getConfig(publisherKey); + + return { + instance: publisherKey, + kafkaConfig: readKafkaConfig(publisherConfig), + kafkaPublisherConfigs: publisherConfig + .getConfigArray('topics') + .map(topicConfig => { + return { + backstageTopic: topicConfig.getString('topic'), + kafkaTopic: topicConfig.getString('kafka.topic'), + producerConfig: { + allowAutoTopicCreation: topicConfig.getOptionalBoolean( + 'kafka.allowAutoTopicCreation', + ), + metadataMaxAge: readOptionalHumanDurationInMs( + topicConfig, + 'kafka.metadataMaxAge', + ), + transactionTimeout: readOptionalHumanDurationInMs( + topicConfig, + 'kafka.transactionTimeout', + ), + idempotent: topicConfig.getOptionalBoolean('kafka.idempotent'), + maxInFlightRequests: topicConfig.getOptionalNumber( + 'kafka.maxInFlightRequests', + ), + retry: readRetryConfig( + topicConfig.getOptionalConfig('kafka.retry'), + ), + }, + }; + }), + }; + }) ?? [] + ); +}; diff --git a/plugins/events-backend-module-kafka/src/KafkaPublishingEventConsumer/index.ts b/plugins/events-backend-module-kafka/src/KafkaPublishingEventConsumer/index.ts new file mode 100644 index 0000000000..42fadd2a5a --- /dev/null +++ b/plugins/events-backend-module-kafka/src/KafkaPublishingEventConsumer/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { eventsModuleKafkaPublishingEventConsumer } from './module'; diff --git a/plugins/events-backend-module-kafka/src/KafkaPublishingEventConsumer/module.test.ts b/plugins/events-backend-module-kafka/src/KafkaPublishingEventConsumer/module.test.ts new file mode 100644 index 0000000000..39c8268300 --- /dev/null +++ b/plugins/events-backend-module-kafka/src/KafkaPublishingEventConsumer/module.test.ts @@ -0,0 +1,122 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { createServiceFactory } from '@backstage/backend-plugin-api'; +import { mockServices, startTestBackend } from '@backstage/backend-test-utils'; +import { eventsServiceRef } from '@backstage/plugin-events-node'; +import { TestEventsService } from '@backstage/plugin-events-backend-test-utils'; +import { eventsModuleKafkaPublishingEventConsumer } from './module'; +import { KafkaPublishingEventConsumer } from './KafkaPublishingEventConsumer'; + +jest.mock('./KafkaPublishingEventConsumer'); + +describe('eventsModuleKafkaPublishingEventConsumer', () => { + it('should be correctly wired and set up', async () => { + const events = new TestEventsService(); + const eventsServiceFactory = createServiceFactory({ + service: eventsServiceRef, + deps: {}, + async factory({}) { + return events; + }, + }); + + const mockKafkaPublishingEventConsumer = { + start: jest.fn(), + shutdown: jest.fn(), + } as unknown as KafkaPublishingEventConsumer; + + jest + .mocked(KafkaPublishingEventConsumer.fromConfig) + .mockReturnValue([mockKafkaPublishingEventConsumer]); + + await startTestBackend({ + features: [ + eventsServiceFactory, + eventsModuleKafkaPublishingEventConsumer, + mockServices.rootConfig.factory({ + data: { + events: { + modules: { + kafka: { + kafkaPublishingEventConsumer: { + dev: { + clientId: 'backstage-events', + brokers: ['kafka1:9092', 'kafka2:9092'], + topics: [ + { + topic: 'fake1', + kafka: { + topic: 'topic-A', + }, + }, + { + topic: 'fake2', + kafka: { + topic: 'topic-B', + }, + }, + ], + }, + }, + }, + }, + }, + }, + }), + ], + }); + + // Verify that the Kafka publishing event consumer was started + expect(mockKafkaPublishingEventConsumer.start).toHaveBeenCalled(); + + // Verify that the shutdown hook was registered (but not called yet) + expect(mockKafkaPublishingEventConsumer.shutdown).not.toHaveBeenCalled(); + }); + + it('should handle empty configuration gracefully', async () => { + const events = new TestEventsService(); + const eventsServiceFactory = createServiceFactory({ + service: eventsServiceRef, + deps: {}, + async factory({}) { + return events; + }, + }); + + jest.mocked(KafkaPublishingEventConsumer.fromConfig).mockReturnValue([]); + + await startTestBackend({ + features: [ + eventsServiceFactory, + eventsModuleKafkaPublishingEventConsumer, + mockServices.rootConfig.factory({ + data: { + events: { + modules: { + kafka: { + // No kafkaPublishingEventConsumer config + }, + }, + }, + }, + }), + ], + }); + + // Verify that fromConfig was called but returned empty array + expect(KafkaPublishingEventConsumer.fromConfig).toHaveBeenCalled(); + }); +}); diff --git a/plugins/events-backend-module-kafka/src/KafkaPublishingEventConsumer/module.ts b/plugins/events-backend-module-kafka/src/KafkaPublishingEventConsumer/module.ts new file mode 100644 index 0000000000..dd5f0c50ab --- /dev/null +++ b/plugins/events-backend-module-kafka/src/KafkaPublishingEventConsumer/module.ts @@ -0,0 +1,56 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + coreServices, + createBackendModule, +} from '@backstage/backend-plugin-api'; +import { eventsServiceRef } from '@backstage/plugin-events-node'; +import { KafkaPublishingEventConsumer } from './KafkaPublishingEventConsumer'; + +/** + * Reads internal Backstage events and forwards them to Kafka topics. + * + * @public + */ +export const eventsModuleKafkaPublishingEventConsumer = createBackendModule({ + pluginId: 'events', + moduleId: 'kafka-publishing-event-consumer', + register(env) { + env.registerInit({ + deps: { + config: coreServices.rootConfig, + events: eventsServiceRef, + logger: coreServices.logger, + lifecycle: coreServices.rootLifecycle, + }, + async init({ config, logger, events, lifecycle }) { + const consumers = KafkaPublishingEventConsumer.fromConfig({ + config, + events, + logger, + }); + + lifecycle.addStartupHook(async () => { + await Promise.all(consumers.map(consumer => consumer.start())); + }); + + lifecycle.addShutdownHook(async () => { + await Promise.all(consumers.map(consumer => consumer.shutdown())); + }); + }, + }); + }, +}); diff --git a/plugins/events-backend-module-kafka/src/index.ts b/plugins/events-backend-module-kafka/src/index.ts index 3ba6207d7d..af4fb02bf1 100644 --- a/plugins/events-backend-module-kafka/src/index.ts +++ b/plugins/events-backend-module-kafka/src/index.ts @@ -13,14 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { createBackendFeatureLoader } from '@backstage/backend-plugin-api'; +import { eventsModuleKafkaConsumingEventPublisher } from './KafkaConsumingEventPublisher'; +import { eventsModuleKafkaPublishingEventConsumer } from './KafkaPublishingEventConsumer'; /** * The module "kafka" for the Backstage backend plugin "events" - * adding an Kafka-based publisher, - * receiving events from an Kafka topic and passing it to the - * internal event broker. + * adding Kafka-based event handling: + * - Consumer: receives events from Kafka topics and passes them to the internal event broker + * - Publisher: receives internal events and publishes them to Kafka topics * * @packageDocumentation */ -export { eventsModuleKafkaConsumingEventPublisher as default } from './service/eventsModuleKafkaConsumingEventPublisher'; +export default createBackendFeatureLoader({ + *loader() { + yield eventsModuleKafkaConsumingEventPublisher; + yield eventsModuleKafkaPublishingEventConsumer; + }, +}); diff --git a/plugins/events-backend-module-kafka/src/publisher/KafkaConsumerClient.test.ts b/plugins/events-backend-module-kafka/src/publisher/KafkaConsumerClient.test.ts deleted file mode 100644 index 5824bf4d41..0000000000 --- a/plugins/events-backend-module-kafka/src/publisher/KafkaConsumerClient.test.ts +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2025 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { KafkaConsumerClient } from './KafkaConsumerClient'; -import { ConfigReader } from '@backstage/config'; -import { KafkaConsumingEventPublisher } from './KafkaConsumingEventPublisher'; -import { mockServices } from '@backstage/backend-test-utils'; - -jest.mock('kafkajs'); -jest.mock('./KafkaConsumingEventPublisher'); - -describe('KafkaConsumerClient', () => { - const mockLogger = mockServices.logger.mock(); - const mockEvents = mockServices.events.mock(); - - const mockConfig = new ConfigReader({ - events: { - modules: { - kafka: { - kafkaConsumingEventPublisher: { - clientId: 'backstage-events', - brokers: ['kafka1:9092', 'kafka2:9092'], - topics: [ - { - topic: 'fake1', - kafka: { - topics: ['topic-A'], - groupId: 'my-group', - }, - }, - { - topic: 'fake2', - kafka: { - topics: ['topic-B'], - groupId: 'my-group', - }, - }, - ], - }, - }, - }, - }, - }); - - beforeEach(() => { - jest.clearAllMocks(); - }); - - it('should create an instance from config', () => { - const client = KafkaConsumerClient.fromConfig({ - config: mockConfig, - events: mockEvents, - logger: mockLogger, - }); - - expect(client).toBeInstanceOf(KafkaConsumerClient); - }); - - it('should not create an instance from config', () => { - const client = KafkaConsumerClient.fromConfig({ - config: new ConfigReader({}), - events: mockEvents, - logger: mockLogger, - }); - - expect(client).toBeUndefined(); - }); - - it('should create a consumer for each topic from config', () => { - KafkaConsumerClient.fromConfig({ - config: mockConfig, - events: mockEvents, - logger: mockLogger, - }); - - expect(KafkaConsumingEventPublisher.fromConfig).toHaveBeenCalledTimes(2); - }); - - it('should start all consumers', async () => { - const mockConsumer = { - start: jest.fn().mockResolvedValue(undefined), - }; - (KafkaConsumingEventPublisher.fromConfig as jest.Mock).mockReturnValue( - mockConsumer, - ); - - const client = KafkaConsumerClient.fromConfig({ - config: mockConfig, - events: mockEvents, - logger: mockLogger, - }); - - expect(client).toBeDefined(); - - await client?.start(); - - expect(mockConsumer.start).toHaveBeenCalled(); - }); - - it('should shutdown all consumers', async () => { - const mockConsumer = { - shutdown: jest.fn().mockResolvedValue(undefined), - }; - (KafkaConsumingEventPublisher.fromConfig as jest.Mock).mockReturnValue( - mockConsumer, - ); - - const client = KafkaConsumerClient.fromConfig({ - config: mockConfig, - events: mockEvents, - logger: mockLogger, - }); - - expect(client).toBeDefined(); - - await client?.shutdown(); - - expect(mockConsumer.shutdown).toHaveBeenCalled(); - }); -}); diff --git a/plugins/events-backend-module-kafka/src/publisher/KafkaConsumerClient.ts b/plugins/events-backend-module-kafka/src/publisher/KafkaConsumerClient.ts deleted file mode 100644 index d506e4a6af..0000000000 --- a/plugins/events-backend-module-kafka/src/publisher/KafkaConsumerClient.ts +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2025 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { LoggerService } from '@backstage/backend-plugin-api'; -import { Config } from '@backstage/config'; -import { EventsService } from '@backstage/plugin-events-node'; -import { Kafka } from 'kafkajs'; -import { KafkaEventSourceConfig, readConfig } from './config'; -import { KafkaConsumingEventPublisher } from './KafkaConsumingEventPublisher'; -import { loggerServiceAdapter } from './LoggerServiceAdapter'; - -/** - * KafkaConsumerClient - * - * This class creates the Kafka client that will be used to create the KafkaConsumingEventPublisher - */ -export class KafkaConsumerClient { - private readonly kafka: Kafka; - private readonly consumers: KafkaConsumingEventPublisher[]; - - static fromConfig(options: { - config: Config; - events: EventsService; - logger: LoggerService; - }): KafkaConsumerClient | undefined { - const kafkaConfig = readConfig(options.config); - - if (!kafkaConfig) { - options.logger.info( - 'Kafka consumer not configured, skipping initialization', - ); - return undefined; - } - - return new KafkaConsumerClient(options.logger, options.events, kafkaConfig); - } - - private constructor( - logger: LoggerService, - events: EventsService, - config: KafkaEventSourceConfig, - ) { - this.kafka = new Kafka({ - ...config.kafkaConfig, - logCreator: loggerServiceAdapter(logger), - }); - - this.consumers = config.kafkaConsumerConfigs.map(consumerConfig => - KafkaConsumingEventPublisher.fromConfig({ - kafkaClient: this.kafka, - config: consumerConfig, - logger, - events, - }), - ); - } - - async start(): Promise { - this.consumers.map(async consumer => await consumer.start()); - } - - async shutdown(): Promise { - this.consumers.map(async consumer => await consumer.shutdown()); - } -} diff --git a/plugins/events-backend-module-kafka/src/publisher/KafkaConsumingEventPublisher.test.ts b/plugins/events-backend-module-kafka/src/publisher/KafkaConsumingEventPublisher.test.ts deleted file mode 100644 index 64c53595ad..0000000000 --- a/plugins/events-backend-module-kafka/src/publisher/KafkaConsumingEventPublisher.test.ts +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2025 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { KafkaConsumingEventPublisher } from './KafkaConsumingEventPublisher'; -import { Kafka } from 'kafkajs'; -import { KafkaConsumerConfig } from './config'; -import { mockServices } from '@backstage/backend-test-utils'; - -jest.mock('kafkajs'); - -describe('KafkaConsumingEventPublisher', () => { - const mockLogger = mockServices.logger.mock(); - const mockEvents = mockServices.events.mock(); - - const mockConsumer = { - connect: jest.fn(), - disconnect: jest.fn(), - subscribe: jest.fn(), - run: jest.fn(), - }; - - const mockKafkaClient = { - consumer: jest.fn().mockReturnValue(mockConsumer), - } as unknown as Kafka; - - const kafkaConsumerConfig: KafkaConsumerConfig = { - consumerConfig: { - groupId: 'test-group', - }, - consumerSubscribeTopics: { - topics: ['test-topic'], - }, - backstageTopic: 'backstage-topic', - }; - - beforeEach(() => { - jest.clearAllMocks(); - }); - - it('should create an instance from config', () => { - const consumer = KafkaConsumingEventPublisher.fromConfig({ - kafkaClient: mockKafkaClient, - config: kafkaConsumerConfig, - events: mockEvents, - logger: mockLogger, - }); - - expect(consumer).toBeInstanceOf(KafkaConsumingEventPublisher); - }); - - it('should start the consumer', async () => { - const consumer = KafkaConsumingEventPublisher.fromConfig({ - kafkaClient: mockKafkaClient, - config: kafkaConsumerConfig, - events: mockEvents, - logger: mockLogger, - }); - - await consumer.start(); - - expect(mockConsumer.connect).toHaveBeenCalled(); - expect(mockConsumer.subscribe).toHaveBeenCalledWith( - kafkaConsumerConfig.consumerSubscribeTopics, - ); - expect(mockConsumer.run).toHaveBeenCalled(); - }); - - it('should shutdown the consumer', async () => { - const consumer = KafkaConsumingEventPublisher.fromConfig({ - kafkaClient: mockKafkaClient, - config: kafkaConsumerConfig, - events: mockEvents, - logger: mockLogger, - }); - - await consumer.shutdown(); - - expect(mockConsumer.disconnect).toHaveBeenCalled(); - }); -}); diff --git a/plugins/events-backend-module-kafka/src/publisher/KafkaConsumingEventPublisher.ts b/plugins/events-backend-module-kafka/src/publisher/KafkaConsumingEventPublisher.ts deleted file mode 100644 index dfc6186fb5..0000000000 --- a/plugins/events-backend-module-kafka/src/publisher/KafkaConsumingEventPublisher.ts +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2025 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { LoggerService } from '@backstage/backend-plugin-api'; -import { EventParams, EventsService } from '@backstage/plugin-events-node'; -import { Consumer, ConsumerSubscribeTopics, IHeaders, Kafka } from 'kafkajs'; -import { KafkaConsumerConfig } from './config'; - -type EventMetadata = EventParams['metadata']; - -/** - * This class subscribes to Kafka topics and publishes events received to the registered subscriber. - * The message payload will be used as the event payload and passed to the subscribers. - */ -export class KafkaConsumingEventPublisher { - private readonly kafkaConsumer: Consumer; - private readonly consumerSubscribeTopics: ConsumerSubscribeTopics; - private readonly backstageTopic: string; - private readonly logger: LoggerService; - - static fromConfig(env: { - kafkaClient: Kafka; - config: KafkaConsumerConfig; - events: EventsService; - logger: LoggerService; - }): KafkaConsumingEventPublisher { - return new KafkaConsumingEventPublisher( - env.kafkaClient, - env.logger, - env.events, - env.config, - ); - } - - private readonly events: EventsService; - - private constructor( - kafkaClient: Kafka, - logger: LoggerService, - events: EventsService, - config: KafkaConsumerConfig, - ) { - this.events = events; - this.kafkaConsumer = kafkaClient.consumer(config.consumerConfig); - this.consumerSubscribeTopics = config.consumerSubscribeTopics; - this.backstageTopic = config.backstageTopic; - const id = `events.kafka.publisher:${this.backstageTopic}`; - this.logger = logger.child({ - class: KafkaConsumingEventPublisher.prototype.constructor.name, - groupId: config.consumerConfig.groupId, - kafkaTopics: config.consumerSubscribeTopics.topics.toString(), - backstageTopic: config.backstageTopic, - taskId: id, - }); - } - - async start(): Promise { - try { - await this.kafkaConsumer.connect(); - - await this.kafkaConsumer.subscribe(this.consumerSubscribeTopics); - - await this.kafkaConsumer.run({ - eachMessage: async ({ message }) => { - this.events.publish({ - topic: this.backstageTopic, - eventPayload: JSON.parse(message.value?.toString()!), - metadata: this.convertHeadersToMetadata(message.headers), - }); - }, - }); - } catch (error: any) { - this.logger.error('Kafka consumer connection failed ', error); - } - } - - async shutdown(): Promise { - await this.kafkaConsumer.disconnect(); - } - - private convertHeadersToMetadata = ( - headers: IHeaders | undefined, - ): EventParams['metadata'] => { - if (!headers) return undefined; - - const metadata: EventMetadata = {}; - - Object.entries(headers).forEach(([key, value]) => { - // If value is an array use toString() on all values converting any Buffer types to valid strings - if (Array.isArray(value)) metadata[key] = value.map(v => v.toString()); - // Always return the values using toString() to catch all Buffer types that should be converted to strings - else metadata[key] = value?.toString(); - }); - - return metadata; - }; -} diff --git a/plugins/events-backend-module-kafka/src/publisher/config.test.ts b/plugins/events-backend-module-kafka/src/publisher/config.test.ts deleted file mode 100644 index fc7e3049b0..0000000000 --- a/plugins/events-backend-module-kafka/src/publisher/config.test.ts +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright 2025 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { ConfigReader } from '@backstage/config'; -import { readConfig } from './config'; - -describe('readConfig', () => { - it('not configured', () => { - const publisherConfigs = readConfig(new ConfigReader({})); - - expect(publisherConfigs).toBeUndefined(); - }); - - it('only required fields configured', () => { - const config = new ConfigReader({ - events: { - modules: { - kafka: { - kafkaConsumingEventPublisher: { - clientId: 'backstage-events', - brokers: ['kafka1:9092', 'kafka2:9092'], - topics: [ - { - topic: 'fake1', - kafka: { - topics: ['topic-A'], - groupId: 'my-group', - }, - }, - { - topic: 'fake2', - kafka: { - topics: ['topic-B'], - groupId: 'my-group', - }, - }, - ], - }, - }, - }, - }, - }); - - const publisherConfigs = readConfig(config); - - expect(publisherConfigs).toBeDefined(); - - expect(publisherConfigs?.kafkaConsumerConfigs.length).toBe(2); - - expect(publisherConfigs?.kafkaConfig.clientId).toEqual('backstage-events'); - expect(publisherConfigs?.kafkaConfig.brokers).toEqual([ - 'kafka1:9092', - 'kafka2:9092', - ]); - expect(publisherConfigs?.kafkaConsumerConfigs[0].backstageTopic).toEqual( - 'fake1', - ); - expect( - publisherConfigs?.kafkaConsumerConfigs[0].consumerConfig.groupId, - ).toEqual('my-group'); - expect( - publisherConfigs?.kafkaConsumerConfigs[0].consumerSubscribeTopics.topics, - ).toEqual(['topic-A']); - }); - - it('all fields configured', () => { - const config = new ConfigReader({ - events: { - modules: { - kafka: { - kafkaConsumingEventPublisher: { - clientId: 'backstage-events', - brokers: ['kafka1:9092', 'kafka2:9092'], - ssl: true, - sasl: { - mechanism: 'plain', - username: 'username', - password: 'password', - }, - retry: { - maxRetryTime: { milliseconds: 20000 }, - initialRetryTime: { milliseconds: 200 }, - factor: '0.4', - multiplier: '4', - retries: '10', - }, - authenticationTimeout: { milliseconds: 20000 }, - connectionTimeout: { milliseconds: 1500 }, - requestTimeout: { milliseconds: 20000 }, - enforceRequestTimeout: false, - topics: [ - { - topic: 'fake1', - kafka: { - topics: ['topic-A'], - groupId: 'my-group', - sessionTimeout: { milliseconds: 20000 }, - rebalanceTimeout: { milliseconds: 50000 }, - heartbeatInterval: { milliseconds: 2000 }, - metadataMaxAge: { milliseconds: 400000 }, - maxBytesPerPartition: 50000, - minBytes: 2, - maxBytes: 500000, - maxWaitTime: { milliseconds: 4000 }, - }, - }, - { - topic: 'fake2', - kafka: { - topics: ['topic-B'], - groupId: 'my-group', - }, - }, - ], - }, - }, - }, - }, - }); - - const publisherConfigs = readConfig(config); - - expect(publisherConfigs).toBeDefined(); - - // Client configuration - expect(publisherConfigs?.kafkaConfig.clientId).toEqual('backstage-events'); - expect(publisherConfigs?.kafkaConfig.brokers).toEqual([ - 'kafka1:9092', - 'kafka2:9092', - ]); - expect(publisherConfigs?.kafkaConfig.ssl).toBeTruthy(); - expect(publisherConfigs?.kafkaConfig.sasl).toStrictEqual({ - mechanism: 'plain', - username: 'username', - password: 'password', - }); - expect(publisherConfigs?.kafkaConfig.authenticationTimeout).toBe(20000); - expect(publisherConfigs?.kafkaConfig.connectionTimeout).toBe(1500); - expect(publisherConfigs?.kafkaConfig.requestTimeout).toBe(20000); - expect(publisherConfigs?.kafkaConfig.enforceRequestTimeout).toBeFalsy(); - expect(publisherConfigs?.kafkaConfig.retry).toStrictEqual({ - maxRetryTime: 20000, - initialRetryTime: 200, - factor: 0.4, - multiplier: 4, - retries: 10, - }); - - // Consumer configuration - expect(publisherConfigs?.kafkaConsumerConfigs.length).toBe(2); - expect(publisherConfigs?.kafkaConsumerConfigs[0].backstageTopic).toEqual( - 'fake1', - ); - expect( - publisherConfigs?.kafkaConsumerConfigs[0].consumerConfig.groupId, - ).toEqual('my-group'); - expect( - publisherConfigs?.kafkaConsumerConfigs[0].consumerSubscribeTopics.topics, - ).toEqual(['topic-A']); - - expect( - publisherConfigs?.kafkaConsumerConfigs[0].consumerConfig.sessionTimeout, - ).toBe(20000); - expect( - publisherConfigs?.kafkaConsumerConfigs[0].consumerConfig.rebalanceTimeout, - ).toBe(50000); - expect( - publisherConfigs?.kafkaConsumerConfigs[0].consumerConfig - .heartbeatInterval, - ).toBe(2000); - expect( - publisherConfigs?.kafkaConsumerConfigs[0].consumerConfig.metadataMaxAge, - ).toBe(400000); - expect( - publisherConfigs?.kafkaConsumerConfigs[0].consumerConfig - .maxBytesPerPartition, - ).toBe(50000); - expect( - publisherConfigs?.kafkaConsumerConfigs[0].consumerConfig.minBytes, - ).toBe(2); - expect( - publisherConfigs?.kafkaConsumerConfigs[0].consumerConfig.maxBytes, - ).toBe(500000); - expect( - publisherConfigs?.kafkaConsumerConfigs[0].consumerConfig.maxWaitTimeInMs, - ).toBe(4000); - }); - - it('should handle HumanDuration and string values for durations and timeouts', () => { - const config = new ConfigReader({ - events: { - modules: { - kafka: { - kafkaConsumingEventPublisher: { - clientId: 'backstage-events', - brokers: ['kafka1:9092', 'kafka2:9092'], - retry: { - maxRetryTime: { seconds: 1 }, - initialRetryTime: { minutes: 1 }, - factor: 0.4, - multiplier: 4, - retries: 10, - }, - authenticationTimeout: { hours: 1 }, - connectionTimeout: { days: 1 }, - topics: [], - requestTimeout: '1m', - }, - }, - }, - }, - }); - - const publisherConfigs = readConfig(config); - - expect(publisherConfigs).toBeDefined(); - - // Client configuration - expect(publisherConfigs?.kafkaConfig.clientId).toEqual('backstage-events'); - expect(publisherConfigs?.kafkaConfig.brokers).toEqual([ - 'kafka1:9092', - 'kafka2:9092', - ]); - expect(publisherConfigs?.kafkaConfig.authenticationTimeout).toBe(3600000); - expect(publisherConfigs?.kafkaConfig.connectionTimeout).toBe(86400000); - expect(publisherConfigs?.kafkaConfig.requestTimeout).toBe(60000); - expect(publisherConfigs?.kafkaConfig.retry).toStrictEqual({ - maxRetryTime: 1000, - initialRetryTime: 60000, - factor: 0.4, - multiplier: 4, - retries: 10, - }); - - // Consumer configuration - expect(publisherConfigs?.kafkaConsumerConfigs.length).toBe(0); - }); -}); diff --git a/plugins/events-backend-module-kafka/src/publisher/config.ts b/plugins/events-backend-module-kafka/src/publisher/config.ts deleted file mode 100644 index 7534ce4d38..0000000000 --- a/plugins/events-backend-module-kafka/src/publisher/config.ts +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright 2025 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { Config, readDurationFromConfig } from '@backstage/config'; -import { durationToMilliseconds } from '@backstage/types'; -import { ConsumerConfig, ConsumerSubscribeTopics, KafkaConfig } from 'kafkajs'; - -export interface KafkaConsumerConfig { - backstageTopic: string; - consumerConfig: ConsumerConfig; - consumerSubscribeTopics: ConsumerSubscribeTopics; -} - -export interface KafkaEventSourceConfig { - kafkaConfig: KafkaConfig; - kafkaConsumerConfigs: KafkaConsumerConfig[]; -} - -const CONFIG_PREFIX_PUBLISHER = - 'events.modules.kafka.kafkaConsumingEventPublisher'; - -/** - * Reads an optional HumanDuration from the config and returns the value in milliseconds if the key is defined. - * - * @param config - The configuration object to read from. - * @param key - The key to look up in the configuration. - * @returns The duration in milliseconds, or undefined if the key is not defined. - */ -const readOptionalHumanDurationInMs = ( - config: Config, - key: string, -): number | undefined => { - const humanDuration = config.has(key) - ? readDurationFromConfig(config, { key }) - : undefined; - - if (!humanDuration) return undefined; - - return durationToMilliseconds(humanDuration); -}; - -export const readConfig = ( - config: Config, -): KafkaEventSourceConfig | undefined => { - const kafkaConfig = config.getOptionalConfig(CONFIG_PREFIX_PUBLISHER); - - if (!kafkaConfig) { - return undefined; - } - - const clientId = kafkaConfig.getString('clientId'); - const brokers = kafkaConfig.getStringArray('brokers'); - - const authenticationTimeout = readOptionalHumanDurationInMs( - kafkaConfig, - 'authenticationTimeout', - ); - - const connectionTimeout = readOptionalHumanDurationInMs( - kafkaConfig, - 'connectionTimeout', - ); - const requestTimeout = readOptionalHumanDurationInMs( - kafkaConfig, - 'requestTimeout', - ); - const enforceRequestTimeout = kafkaConfig.getOptionalBoolean( - 'enforceRequestTimeout', - ); - - const ssl = kafkaConfig.getOptional('ssl') as KafkaConfig['ssl']; - const sasl = kafkaConfig.getOptional('sasl') as KafkaConfig['sasl']; - - const retry: KafkaConfig['retry'] = { - maxRetryTime: readOptionalHumanDurationInMs( - kafkaConfig, - 'retry.maxRetryTime', - ), - initialRetryTime: readOptionalHumanDurationInMs( - kafkaConfig, - 'retry.initialRetryTime', - ), - factor: kafkaConfig.getOptionalNumber('retry.factor'), - multiplier: kafkaConfig.getOptionalNumber('retry.multiplier'), - retries: kafkaConfig.getOptionalNumber('retry.retries'), - }; - - const kafkaConsumerConfigs: KafkaConsumerConfig[] = kafkaConfig - .getConfigArray('topics') - .map(topic => { - return { - backstageTopic: topic.getString('topic'), - consumerConfig: { - groupId: topic.getString('kafka.groupId'), - sessionTimeout: readOptionalHumanDurationInMs( - topic, - 'kafka.sessionTimeout', - ), - rebalanceTimeout: readOptionalHumanDurationInMs( - topic, - 'kafka.rebalanceTimeout', - ), - heartbeatInterval: readOptionalHumanDurationInMs( - topic, - 'kafka.heartbeatInterval', - ), - metadataMaxAge: readOptionalHumanDurationInMs( - topic, - 'kafka.metadataMaxAge', - ), - maxBytesPerPartition: topic.getOptionalNumber( - 'kafka.maxBytesPerPartition', - ), - minBytes: topic.getOptionalNumber('kafka.minBytes'), - maxBytes: topic.getOptionalNumber('kafka.maxBytes'), - maxWaitTimeInMs: readOptionalHumanDurationInMs( - topic, - 'kafka.maxWaitTime', - ), - }, - consumerSubscribeTopics: { - topics: topic.getStringArray('kafka.topics'), - }, - }; - }); - - return { - kafkaConfig: { - clientId, - brokers, - ssl, - sasl, - authenticationTimeout, - connectionTimeout, - requestTimeout, - enforceRequestTimeout, - retry, - }, - kafkaConsumerConfigs, - }; -}; diff --git a/plugins/events-backend-module-kafka/src/service/eventsModuleKafkaConsumingEventPublisher.test.ts b/plugins/events-backend-module-kafka/src/service/eventsModuleKafkaConsumingEventPublisher.test.ts deleted file mode 100644 index 816793f635..0000000000 --- a/plugins/events-backend-module-kafka/src/service/eventsModuleKafkaConsumingEventPublisher.test.ts +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2025 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { createServiceFactory } from '@backstage/backend-plugin-api'; -import { mockServices, startTestBackend } from '@backstage/backend-test-utils'; -import { eventsServiceRef } from '@backstage/plugin-events-node'; -import { TestEventsService } from '@backstage/plugin-events-backend-test-utils'; -import { eventsModuleKafkaConsumingEventPublisher } from './eventsModuleKafkaConsumingEventPublisher'; -import { KafkaConsumerClient } from '../publisher/KafkaConsumerClient'; - -jest.mock('../publisher/KafkaConsumerClient'); - -describe('eventsModuleKafkaConsumingEventPublisher', () => { - it('should be correctly wired and set up', async () => { - const events = new TestEventsService(); - const eventsServiceFactory = createServiceFactory({ - service: eventsServiceRef, - deps: {}, - async factory({}) { - return events; - }, - }); - - const mockKafkaConsumerClient = { - start: jest.fn(), - shutdown: jest.fn(), - }; - (KafkaConsumerClient.fromConfig as jest.Mock).mockReturnValue( - mockKafkaConsumerClient, - ); - - await startTestBackend({ - features: [ - eventsServiceFactory, - eventsModuleKafkaConsumingEventPublisher, - mockServices.rootConfig.factory({ - data: { - events: { - modules: { - kafka: { - kafkaConsumingEventPublisher: { - clientId: 'backstage-events', - brokers: ['kafka1:9092', 'kafka2:9092'], - topics: { - fake1: { - kafka: { - topics: ['topic-A'], - groupId: 'my-group', - }, - }, - fake2: { - kafka: { - topics: ['topic-B'], - groupId: 'my-group', - }, - }, - }, - }, - }, - }, - }, - }, - }), - ], - }); - - // Verify that the Kafka consumer client was started - expect(mockKafkaConsumerClient.start).toHaveBeenCalled(); - - // Verify that the shutdown hook was registered - expect(mockKafkaConsumerClient.shutdown).not.toHaveBeenCalled(); - }); -}); diff --git a/plugins/events-backend-module-kafka/src/publisher/LoggerServiceAdapter.ts b/plugins/events-backend-module-kafka/src/utils/LoggerServiceAdapter.ts similarity index 100% rename from plugins/events-backend-module-kafka/src/publisher/LoggerServiceAdapter.ts rename to plugins/events-backend-module-kafka/src/utils/LoggerServiceAdapter.ts diff --git a/plugins/events-backend-module-kafka/src/utils/config.test.ts b/plugins/events-backend-module-kafka/src/utils/config.test.ts new file mode 100644 index 0000000000..2bd6121ba2 --- /dev/null +++ b/plugins/events-backend-module-kafka/src/utils/config.test.ts @@ -0,0 +1,235 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { ConfigReader } from '@backstage/config'; +import { readRetryConfig, readKafkaConfig } from './config'; + +describe('readRetryConfig', () => { + it('should return empty object when config is undefined', () => { + const result = readRetryConfig(undefined); + expect(result).toEqual({}); + }); + + it('should return empty object when config is empty', () => { + const config = new ConfigReader({}); + const result = readRetryConfig(config); + expect(result).toEqual({}); + }); + + it('should read retry configuration with milliseconds', () => { + const config = new ConfigReader({ + maxRetryTime: { milliseconds: 20000 }, + initialRetryTime: { milliseconds: 200 }, + factor: 0.4, + multiplier: 4, + retries: 10, + }); + + const result = readRetryConfig(config); + + expect(result).toEqual({ + maxRetryTime: 20000, + initialRetryTime: 200, + factor: 0.4, + multiplier: 4, + retries: 10, + }); + }); + + it('should read retry configuration with string values', () => { + const config = new ConfigReader({ + maxRetryTime: { seconds: 20 }, + initialRetryTime: { minutes: 1 }, + factor: '0.4', + multiplier: '4', + retries: '10', + }); + + const result = readRetryConfig(config); + + expect(result).toEqual({ + maxRetryTime: 20000, + initialRetryTime: 60000, + factor: 0.4, + multiplier: 4, + retries: 10, + }); + }); + + it('should handle HumanDuration values', () => { + const config = new ConfigReader({ + maxRetryTime: { hours: 1 }, + initialRetryTime: { days: 1 }, + }); + + const result = readRetryConfig(config); + + expect(result).toEqual({ + maxRetryTime: 3600000, + initialRetryTime: 86400000, + factor: undefined, + multiplier: undefined, + retries: undefined, + }); + }); + + it('should handle partial configuration', () => { + const config = new ConfigReader({ + maxRetryTime: { milliseconds: 15000 }, + retries: 5, + }); + + const result = readRetryConfig(config); + + expect(result).toEqual({ + maxRetryTime: 15000, + initialRetryTime: undefined, + factor: undefined, + multiplier: undefined, + retries: 5, + }); + }); +}); + +describe('readKafkaConfig', () => { + it('should read minimal kafka configuration', () => { + const config = new ConfigReader({ + clientId: 'test-client', + brokers: ['kafka1:9092', 'kafka2:9092'], + }); + + const result = readKafkaConfig(config); + + expect(result).toEqual({ + clientId: 'test-client', + brokers: ['kafka1:9092', 'kafka2:9092'], + authenticationTimeout: undefined, + connectionTimeout: undefined, + requestTimeout: undefined, + enforceRequestTimeout: undefined, + ssl: undefined, + sasl: undefined, + retry: {}, + }); + }); + + it('should read full kafka configuration with all optional fields', () => { + const config = new ConfigReader({ + clientId: 'backstage-events', + brokers: ['kafka1:9092', 'kafka2:9092'], + authenticationTimeout: { milliseconds: 20000 }, + connectionTimeout: { milliseconds: 1500 }, + requestTimeout: { milliseconds: 20000 }, + enforceRequestTimeout: false, + ssl: true, + sasl: { + mechanism: 'plain', + username: 'username', + password: 'password', + }, + retry: { + maxRetryTime: { milliseconds: 20000 }, + initialRetryTime: { milliseconds: 200 }, + factor: 0.4, + multiplier: 4, + retries: 10, + }, + }); + + const result = readKafkaConfig(config); + + expect(result).toEqual({ + clientId: 'backstage-events', + brokers: ['kafka1:9092', 'kafka2:9092'], + authenticationTimeout: 20000, + connectionTimeout: 1500, + requestTimeout: 20000, + enforceRequestTimeout: false, + ssl: true, + sasl: { + mechanism: 'plain', + username: 'username', + password: 'password', + }, + retry: { + maxRetryTime: 20000, + initialRetryTime: 200, + factor: 0.4, + multiplier: 4, + retries: 10, + }, + }); + }); + + it('should handle HumanDuration values for timeouts', () => { + const config = new ConfigReader({ + clientId: 'test-client', + brokers: ['kafka:9092'], + authenticationTimeout: { hours: 1 }, + connectionTimeout: { days: 1 }, + requestTimeout: { minutes: 5 }, + }); + + const result = readKafkaConfig(config); + + expect(result.authenticationTimeout).toBe(3600000); + expect(result.connectionTimeout).toBe(86400000); + expect(result.requestTimeout).toBe(300000); + }); + + it('should handle complex SSL configuration', () => { + const config = new ConfigReader({ + clientId: 'secure-client', + brokers: ['secure-kafka:9093'], + ssl: { + rejectUnauthorized: false, + ca: 'ca-certificate', + key: 'client-key', + cert: 'client-cert', + }, + }); + + const result = readKafkaConfig(config); + + expect(result.ssl).toEqual({ + rejectUnauthorized: false, + ca: 'ca-certificate', + key: 'client-key', + cert: 'client-cert', + }); + }); + + it('should handle complex SASL configuration', () => { + const config = new ConfigReader({ + clientId: 'sasl-client', + brokers: ['sasl-kafka:9094'], + sasl: { + mechanism: 'scram-sha-256', + username: 'kafka-user', + password: 'kafka-password', + authorizationIdentity: 'authz-user', + }, + }); + + const result = readKafkaConfig(config); + + expect(result.sasl).toEqual({ + mechanism: 'scram-sha-256', + username: 'kafka-user', + password: 'kafka-password', + authorizationIdentity: 'authz-user', + }); + }); +}); diff --git a/plugins/events-backend-module-kafka/src/utils/config.ts b/plugins/events-backend-module-kafka/src/utils/config.ts new file mode 100644 index 0000000000..4e140d26a3 --- /dev/null +++ b/plugins/events-backend-module-kafka/src/utils/config.ts @@ -0,0 +1,84 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { Config, readDurationFromConfig } from '@backstage/config'; +import { durationToMilliseconds } from '@backstage/types'; +import { KafkaConfig, RetryOptions } from 'kafkajs'; + +/** + * Reads an optional HumanDuration from the config and returns the value in milliseconds if the key is defined. + * + * @param config - The configuration object to read from. + * @param key - The key to look up in the configuration. + * @returns The duration in milliseconds, or undefined if the key is not defined. + */ +export const readOptionalHumanDurationInMs = ( + config: Config, + key: string, +): number | undefined => { + const humanDuration = config.has(key) + ? readDurationFromConfig(config, { key }) + : undefined; + + if (!humanDuration) return undefined; + + return durationToMilliseconds(humanDuration); +}; + +/** + * Reads retry configuration options from the provided config object. + * + * @param config - The configuration object to read retry options from, or undefined. + * @returns A RetryOptions object with optional retry settings, or an empty object if config is undefined. + */ +export const readRetryConfig = (config: Config | undefined): RetryOptions => { + if (!config) { + return {}; + } + + return { + maxRetryTime: readOptionalHumanDurationInMs(config, 'maxRetryTime'), + initialRetryTime: readOptionalHumanDurationInMs(config, 'initialRetryTime'), + factor: config.getOptionalNumber('factor'), + multiplier: config.getOptionalNumber('multiplier'), + retries: config.getOptionalNumber('retries'), + }; +}; + +/** + * Reads Kafka configuration from the provided config object. + * + * @param config - The configuration object containing Kafka settings. + * @returns A KafkaConfig object with all necessary Kafka connection and authentication settings. + */ +export const readKafkaConfig = (config: Config): KafkaConfig => { + return { + clientId: config.getString('clientId'), + brokers: config.getStringArray('brokers'), + authenticationTimeout: readOptionalHumanDurationInMs( + config, + 'authenticationTimeout', + ), + connectionTimeout: readOptionalHumanDurationInMs( + config, + 'connectionTimeout', + ), + requestTimeout: readOptionalHumanDurationInMs(config, 'requestTimeout'), + enforceRequestTimeout: config.getOptionalBoolean('enforceRequestTimeout'), + ssl: config.getOptional('ssl') as KafkaConfig['ssl'], + sasl: config.getOptional('sasl') as KafkaConfig['sasl'], + retry: readRetryConfig(config.getOptionalConfig('retry')), + }; +}; diff --git a/plugins/events-backend-module-kafka/src/utils/kafkaTransformers.test.ts b/plugins/events-backend-module-kafka/src/utils/kafkaTransformers.test.ts new file mode 100644 index 0000000000..bfb373ea53 --- /dev/null +++ b/plugins/events-backend-module-kafka/src/utils/kafkaTransformers.test.ts @@ -0,0 +1,137 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { convertHeadersToMetadata, payloadToBuffer } from './kafkaTransformers'; + +describe('kafka-transformers', () => { + describe('convertHeadersToMetadata', () => { + it('should return undefined when headers is undefined', () => { + const result = convertHeadersToMetadata(undefined); + expect(result).toBeUndefined(); + }); + + it('should convert string headers to metadata', () => { + const headers = { + 'content-type': 'application/json', + 'user-id': '12345', + }; + + const result = convertHeadersToMetadata(headers); + + expect(result).toEqual({ + 'content-type': 'application/json', + 'user-id': '12345', + }); + }); + + it('should convert Buffer headers to string metadata', () => { + const headers = { + 'content-type': Buffer.from('application/json'), + 'correlation-id': Buffer.from('abc-123'), + }; + + const result = convertHeadersToMetadata(headers); + + expect(result).toEqual({ + 'content-type': 'application/json', + 'correlation-id': 'abc-123', + }); + }); + + it('should convert array headers to string array metadata', () => { + const headers = { + tags: ['tag1', 'tag2'], + 'buffer-tags': [Buffer.from('tag3'), Buffer.from('tag4')], + 'mixed-tags': ['tag5', Buffer.from('tag6')], + }; + + const result = convertHeadersToMetadata(headers); + + expect(result).toEqual({ + tags: ['tag1', 'tag2'], + 'buffer-tags': ['tag3', 'tag4'], + 'mixed-tags': ['tag5', 'tag6'], + }); + }); + + it('should handle mixed header types', () => { + const headers = { + 'string-header': 'value', + 'buffer-header': Buffer.from('buffer-value'), + 'array-header': ['item1', Buffer.from('item2')], + 'undefined-header': undefined, + }; + + const result = convertHeadersToMetadata(headers); + + expect(result).toEqual({ + 'string-header': 'value', + 'buffer-header': 'buffer-value', + 'array-header': ['item1', 'item2'], + 'undefined-header': undefined, + }); + }); + + it('should handle empty headers object', () => { + const headers = {}; + const result = convertHeadersToMetadata(headers); + expect(result).toEqual({}); + }); + }); + + describe('payloadToBuffer', () => { + it('should return the same Buffer when payload is already a Buffer', () => { + const originalBuffer = Buffer.from('test data'); + + const result = payloadToBuffer(originalBuffer); + + expect(result).toBe(originalBuffer); + expect(Buffer.isBuffer(result)).toBe(true); + }); + + it('should convert string to Buffer', () => { + const payload = 'hello world'; + + const result = payloadToBuffer(payload); + + expect(Buffer.isBuffer(result)).toBe(true); + expect(result.toString()).toBe('hello world'); + }); + + it('should convert object to JSON Buffer', () => { + const payload = { name: 'John', age: 30 }; + + const result = payloadToBuffer(payload); + + expect(Buffer.isBuffer(result)).toBe(true); + expect(JSON.parse(result.toString())).toEqual(payload); + }); + + it('should convert array to JSON Buffer', () => { + const payload = [1, 2, 3, 'test']; + + const result = payloadToBuffer(payload); + + expect(Buffer.isBuffer(result)).toBe(true); + expect(JSON.parse(result.toString())).toEqual(payload); + }); + + it('should convert primitives to JSON Buffer', () => { + expect(payloadToBuffer(42).toString()).toBe('42'); + expect(payloadToBuffer(true).toString()).toBe('true'); + expect(payloadToBuffer(null).toString()).toBe('null'); + }); + }); +}); diff --git a/plugins/events-backend-module-kafka/src/utils/kafkaTransformers.ts b/plugins/events-backend-module-kafka/src/utils/kafkaTransformers.ts new file mode 100644 index 0000000000..871cb08a04 --- /dev/null +++ b/plugins/events-backend-module-kafka/src/utils/kafkaTransformers.ts @@ -0,0 +1,49 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { EventParams } from '@backstage/plugin-events-node'; +import { IHeaders } from 'kafkajs'; + +type EventMetadata = EventParams['metadata']; + +export const convertHeadersToMetadata = ( + headers: IHeaders | undefined, +): EventMetadata => { + if (!headers) return undefined; + + const metadata: EventMetadata = {}; + + Object.entries(headers).forEach(([key, value]) => { + // If value is an array use toString() on all values converting any Buffer types to valid strings + if (Array.isArray(value)) metadata[key] = value.map(v => v.toString()); + // Always return the values using toString() to catch all Buffer types that should be converted to strings + else metadata[key] = value?.toString(); + }); + + return metadata; +}; + +export const payloadToBuffer = (payload: unknown): Buffer => { + if (Buffer.isBuffer(payload)) { + return payload; + } + + if (typeof payload === 'string') { + return Buffer.from(payload, 'utf8'); // More explicit encoding + } + + // Convert to JSON string then encode + return Buffer.from(JSON.stringify(payload), 'utf8'); +}; diff --git a/plugins/events-backend-test-utils/CHANGELOG.md b/plugins/events-backend-test-utils/CHANGELOG.md index 91ac1aa27e..a9233cc14a 100644 --- a/plugins/events-backend-test-utils/CHANGELOG.md +++ b/plugins/events-backend-test-utils/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-events-backend-test-utils +## 0.1.51 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.18 + ## 0.1.51-next.0 ### Patch Changes diff --git a/plugins/events-backend-test-utils/package.json b/plugins/events-backend-test-utils/package.json index 64c0ee9925..814fb23241 100644 --- a/plugins/events-backend-test-utils/package.json +++ b/plugins/events-backend-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-test-utils", - "version": "0.1.51-next.0", + "version": "0.1.51", "description": "The plugin-events-backend-test-utils for @backstage/plugin-events-node", "backstage": { "role": "node-library", diff --git a/plugins/events-backend/CHANGELOG.md b/plugins/events-backend/CHANGELOG.md index 8663b0707b..d504f3fdaf 100644 --- a/plugins/events-backend/CHANGELOG.md +++ b/plugins/events-backend/CHANGELOG.md @@ -1,5 +1,40 @@ # @backstage/plugin-events-backend +## 0.5.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-openapi-utils@0.6.5-next.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-events-node@0.4.18 + +## 0.5.9 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-openapi-utils@0.6.4 + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + +## 0.5.9-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-openapi-utils@0.6.4-next.1 + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + ## 0.5.9-next.0 ### Patch Changes diff --git a/plugins/events-backend/package.json b/plugins/events-backend/package.json index db9f5c9c72..5089655b6e 100644 --- a/plugins/events-backend/package.json +++ b/plugins/events-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend", - "version": "0.5.9-next.0", + "version": "0.5.10-next.0", "backstage": { "role": "backend-plugin", "pluginId": "events", diff --git a/plugins/events-node/CHANGELOG.md b/plugins/events-node/CHANGELOG.md index 7ed7f0afb1..d748102a2b 100644 --- a/plugins/events-node/CHANGELOG.md +++ b/plugins/events-node/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-events-node +## 0.4.18 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + +## 0.4.18-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + ## 0.4.18-next.0 ### Patch Changes diff --git a/plugins/events-node/package.json b/plugins/events-node/package.json index 156fb4b263..c8dc226198 100644 --- a/plugins/events-node/package.json +++ b/plugins/events-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-node", - "version": "0.4.18-next.0", + "version": "0.4.18", "description": "The plugin-events-node module for @backstage/plugin-events-backend", "backstage": { "role": "node-library", @@ -65,7 +65,7 @@ "devDependencies": { "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", - "msw": "^1.0.0" + "msw": "^2.0.0" }, "configSchema": "config.d.ts" } diff --git a/plugins/events-node/src/api/DefaultEventsService.test.ts b/plugins/events-node/src/api/DefaultEventsService.test.ts index 13a6a68fa4..a62cc24f14 100644 --- a/plugins/events-node/src/api/DefaultEventsService.test.ts +++ b/plugins/events-node/src/api/DefaultEventsService.test.ts @@ -17,7 +17,7 @@ import { DefaultEventsService } from './DefaultEventsService'; import { EventParams } from './EventParams'; import { EVENTS_NOTIFY_TIMEOUT_HEADER } from './EventsService'; -import { rest } from 'msw'; +import { http, HttpResponse } from 'msw'; import { setupServer } from 'msw/node'; import { mockServices, @@ -129,18 +129,18 @@ describe('DefaultEventsService', () => { }); mswServer.use( - rest.put( + http.put( 'http://localhost:0/api/events/bus/v1/subscriptions/a.tester', - (_req, res, ctx) => res(ctx.status(200)), + () => new HttpResponse(null, { status: 200 }), ), - rest.get( + http.get( 'http://localhost:0/api/events/bus/v1/subscriptions/a.tester/events', - (_req, res, ctx) => - res( - ctx.status(200), - ctx.json({ + () => + HttpResponse.json( + { events: [{ topic: 'test', payload: { foo: 'bar' } }], - }), + }, + { status: 200 }, ), ), ); @@ -180,38 +180,36 @@ describe('DefaultEventsService', () => { }); mswServer.use( - rest.put( + http.put( 'http://localhost:0/api/events/bus/v1/subscriptions/a.tester', - (_req, res, ctx) => res(ctx.status(200)), + () => new HttpResponse(null, { status: 200 }), ), // The first and third calls result in a blocking 202 that is resolved after 100ms // The second and fourth calls result in a 200 with an event // The fifth call blocks until the end of the test // No more than 5 calls should be made - rest.get( + http.get( 'http://localhost:0/api/events/bus/v1/subscriptions/a.tester/events', - (_req, res, ctx) => { + () => { callCount += 1; if (callCount === 1 || callCount === 3) { - return res( - ctx.status(202), - ctx.body( - new ReadableStream({ - start(controller) { - setTimeout(() => controller.close(), 100); - }, - }), - ), + return new HttpResponse( + new ReadableStream({ + start(controller) { + setTimeout(() => controller.close(), 100); + }, + }), + { status: 202 }, ); } else if (callCount === 2 || callCount === 4) { - return res( - ctx.status(200), - ctx.json({ + return HttpResponse.json( + { events: [{ topic: 'test', payload: { callCount } }], - }), + }, + { status: 200 }, ); } else if (callCount === 5) { - return res(ctx.status(202), ctx.body(blockingStream)); + return new HttpResponse(blockingStream, { status: 202 }); } throw new Error(`events endpoint called too many times`); }, @@ -268,45 +266,42 @@ describe('DefaultEventsService', () => { }); mswServer.use( - rest.put( + http.put( 'http://localhost:0/api/events/bus/v1/subscriptions/a.tester', - (_req, res, ctx) => res(ctx.status(200)), + () => new HttpResponse(null, { status: 200 }), ), // The first and third calls result in a blocking 202 that is resolved after 100ms // The second and fourth calls result in a 200 with an event // The fifth call blocks until the end of the test // No more than 5 calls should be made - rest.get( + http.get( 'http://localhost:0/api/events/bus/v1/subscriptions/a.tester/events', - (_req, res, ctx) => { + () => { callCount += 1; if (callCount === 1 || callCount === 3) { - return res( - ctx.status(202), - ctx.body( - new ReadableStream({ - start(controller) { - setTimeout(() => controller.close(), 100); - }, - }), - ), + return new HttpResponse( + new ReadableStream({ + start(controller) { + setTimeout(() => controller.close(), 100); + }, + }), + { status: 202 }, ); } else if (callCount === 2 || callCount === 4) { - return res( - ctx.status(200), - ctx.json({ + return HttpResponse.json( + { events: [{ topic: 'test', payload: { callCount } }], - }), + }, + { status: 200 }, ); } else if (callCount === 5) { // 5th call has a timeout header so polling should proceed to the next call - return res( - ctx.set(EVENTS_NOTIFY_TIMEOUT_HEADER, '100'), - ctx.status(202), - ctx.body(blockingStream), - ); + return new HttpResponse(blockingStream, { + status: 202, + headers: { [EVENTS_NOTIFY_TIMEOUT_HEADER]: '100' }, + }); } else if (callCount === 6) { - return res(ctx.status(202), ctx.body(blockingStream)); + return new HttpResponse(blockingStream, { status: 202 }); } throw new Error(`events endpoint called too many times`); }, @@ -358,11 +353,11 @@ describe('DefaultEventsService', () => { let calledApi = false; mswServer.use( - rest.put( + http.put( 'http://localhost:0/api/events/bus/v1/subscriptions/a.tester', - (_req, res, ctx) => { + () => { calledApi = true; - res(ctx.status(200)); + return new HttpResponse(null, { status: 200 }); }, ), ); @@ -393,9 +388,9 @@ describe('DefaultEventsService', () => { }); mswServer.use( - rest.put( + http.put( 'http://localhost:0/api/events/bus/v1/subscriptions/a.tester', - (_req, res, ctx) => res(ctx.status(404)), + () => new HttpResponse(null, { status: 404 }), ), ); @@ -432,9 +427,9 @@ describe('DefaultEventsService', () => { }); mswServer.use( - rest.put( + http.put( 'http://localhost:0/api/events/bus/v1/subscriptions/a.tester', - (_req, res, ctx) => res(ctx.status(404)), + () => new HttpResponse(null, { status: 404 }), ), ); diff --git a/plugins/example-todo-list-backend/CHANGELOG.md b/plugins/example-todo-list-backend/CHANGELOG.md index 411e010d16..4d7a89509f 100644 --- a/plugins/example-todo-list-backend/CHANGELOG.md +++ b/plugins/example-todo-list-backend/CHANGELOG.md @@ -1,5 +1,20 @@ # @internal/plugin-todo-list-backend +## 1.0.46 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + +## 1.0.46-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/errors@1.2.7 + ## 1.0.46-next.0 ### Patch Changes diff --git a/plugins/example-todo-list-backend/package.json b/plugins/example-todo-list-backend/package.json index 4a8e2748c2..108655947a 100644 --- a/plugins/example-todo-list-backend/package.json +++ b/plugins/example-todo-list-backend/package.json @@ -1,6 +1,6 @@ { "name": "@internal/plugin-todo-list-backend", - "version": "1.0.46-next.0", + "version": "1.0.46", "backstage": { "role": "backend-plugin", "pluginId": "todo-list", diff --git a/plugins/example-todo-list/CHANGELOG.md b/plugins/example-todo-list/CHANGELOG.md index d2db721b76..798fa8df02 100644 --- a/plugins/example-todo-list/CHANGELOG.md +++ b/plugins/example-todo-list/CHANGELOG.md @@ -1,5 +1,13 @@ # @internal/plugin-todo-list +## 1.0.46 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + ## 1.0.46-next.0 ### Patch Changes diff --git a/plugins/example-todo-list/package.json b/plugins/example-todo-list/package.json index 7867750b3a..ad138b4713 100644 --- a/plugins/example-todo-list/package.json +++ b/plugins/example-todo-list/package.json @@ -1,6 +1,6 @@ { "name": "@internal/plugin-todo-list", - "version": "1.0.46-next.0", + "version": "1.0.46", "backstage": { "role": "frontend-plugin", "pluginId": "todo-list", diff --git a/plugins/gateway-backend/CHANGELOG.md b/plugins/gateway-backend/CHANGELOG.md index fe3719d120..5e6c6254d9 100644 --- a/plugins/gateway-backend/CHANGELOG.md +++ b/plugins/gateway-backend/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-gateway-backend +## 1.1.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- 7e860dd: Updated dependency `eventsource` to `^4.0.0`. +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + +## 1.1.1-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + ## 1.1.1-next.0 ### Patch Changes diff --git a/plugins/gateway-backend/package.json b/plugins/gateway-backend/package.json index 7d5bd658e1..4cc39faf7b 100644 --- a/plugins/gateway-backend/package.json +++ b/plugins/gateway-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-gateway-backend", - "version": "1.1.1-next.0", + "version": "1.1.1", "backstage": { "role": "backend-plugin", "pluginId": "gateway", @@ -46,7 +46,7 @@ "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/express": "^4.17.6", - "eventsource": "^3.0.6", + "eventsource": "^4.0.0", "wait-for-expect": "^3.0.2" } } diff --git a/plugins/home-react/CHANGELOG.md b/plugins/home-react/CHANGELOG.md index 6da0bf0084..81c9fbc1be 100644 --- a/plugins/home-react/CHANGELOG.md +++ b/plugins/home-react/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-home-react +## 0.1.33 + +### Patch Changes + +- be21c5c: Updated dependency `@rjsf/utils` to `5.24.13`. + Updated dependency `@rjsf/core` to `5.24.13`. + Updated dependency `@rjsf/material-ui` to `5.24.13`. + Updated dependency `@rjsf/validator-ajv8` to `5.24.13`. +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + +## 0.1.33-next.1 + +### Patch Changes + +- be21c5c: Updated dependency `@rjsf/utils` to `5.24.13`. + Updated dependency `@rjsf/core` to `5.24.13`. + Updated dependency `@rjsf/material-ui` to `5.24.13`. + Updated dependency `@rjsf/validator-ajv8` to `5.24.13`. +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2-next.1 + - @backstage/core-components@0.18.4-next.2 + - @backstage/core-plugin-api@1.12.1-next.0 + ## 0.1.33-next.0 ### Patch Changes diff --git a/plugins/home-react/package.json b/plugins/home-react/package.json index f94413ca64..8f69f7eab7 100644 --- a/plugins/home-react/package.json +++ b/plugins/home-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-home-react", - "version": "0.1.33-next.0", + "version": "0.1.33", "description": "A Backstage plugin that contains react components helps you build a home page", "backstage": { "role": "web-library", diff --git a/plugins/home/CHANGELOG.md b/plugins/home/CHANGELOG.md index 29d73e946a..6a1cbcd825 100644 --- a/plugins/home/CHANGELOG.md +++ b/plugins/home/CHANGELOG.md @@ -1,5 +1,43 @@ # @backstage/plugin-home +## 0.8.15 + +### Patch Changes + +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- be21c5c: Updated dependency `@rjsf/utils` to `5.24.13`. + Updated dependency `@rjsf/core` to `5.24.13`. + Updated dependency `@rjsf/material-ui` to `5.24.13`. + Updated dependency `@rjsf/validator-ajv8` to `5.24.13`. +- Updated dependencies + - @backstage/core-app-api@1.19.3 + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/plugin-home-react@0.1.33 + - @backstage/theme@0.7.1 + +## 0.8.15-next.1 + +### Patch Changes + +- be21c5c: Updated dependency `@rjsf/utils` to `5.24.13`. + Updated dependency `@rjsf/core` to `5.24.13`. + Updated dependency `@rjsf/material-ui` to `5.24.13`. + Updated dependency `@rjsf/validator-ajv8` to `5.24.13`. +- Updated dependencies + - @backstage/core-app-api@1.19.3-next.1 + - @backstage/frontend-plugin-api@0.13.2-next.1 + - @backstage/plugin-catalog-react@1.21.4-next.2 + - @backstage/core-components@0.18.4-next.2 + - @backstage/plugin-home-react@0.1.33-next.1 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/theme@0.7.1-next.0 + ## 0.8.15-next.0 ### Patch Changes diff --git a/plugins/home/package.json b/plugins/home/package.json index 01c0c5bb40..5716626c36 100644 --- a/plugins/home/package.json +++ b/plugins/home/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-home", - "version": "0.8.15-next.0", + "version": "0.8.15", "description": "A Backstage plugin that helps you build a home page", "backstage": { "role": "frontend-plugin", diff --git a/plugins/kubernetes-backend/CHANGELOG.md b/plugins/kubernetes-backend/CHANGELOG.md index 888354fa2e..a8ebfa6f8f 100644 --- a/plugins/kubernetes-backend/CHANGELOG.md +++ b/plugins/kubernetes-backend/CHANGELOG.md @@ -1,5 +1,49 @@ # @backstage/plugin-kubernetes-backend +## 0.21.0 + +### Minor Changes + +- 7f9846f: Add possibility to extends Kubernetes REST API. Add fetcher to parameters for custom objects provider + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- fb029b6: Updated luxon types +- e9589d9: Replace `@aws-sdk/signature-v4` with `@smithy/signature-v4`, + as stated in the [package documentation](https://www.npmjs.com/package/@aws-sdk/signature-v4?activeTab=readme) +- 8fa8d87: Add Kubernetes Plugin Secrets Accordion with masked secret datas +- Updated dependencies + - @backstage/plugin-permission-node@0.10.7 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-kubernetes-node@0.4.0 + - @backstage/plugin-kubernetes-common@0.9.9 + - @backstage/plugin-catalog-node@1.20.1 + +## 0.21.0-next.2 + +### Minor Changes + +- 7f9846f: Add possibility to extends Kubernetes REST API. Add fetcher to parameters for custom objects provider + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- fb029b6: Updated luxon types +- Updated dependencies + - @backstage/plugin-permission-node@0.10.7-next.1 + - @backstage/plugin-kubernetes-node@0.4.0-next.2 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/integration-aws-node@0.1.19 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-node@1.20.1-next.1 + - @backstage/plugin-kubernetes-common@0.9.9-next.0 + - @backstage/plugin-permission-common@0.9.3 + ## 0.20.5-next.1 ### Patch Changes diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json index a4cb8e924a..2aac84c616 100644 --- a/plugins/kubernetes-backend/package.json +++ b/plugins/kubernetes-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-kubernetes-backend", - "version": "0.20.5-next.1", + "version": "0.21.0", "description": "A Backstage backend plugin that integrates towards Kubernetes", "backstage": { "role": "backend-plugin", diff --git a/plugins/kubernetes-backend/src/cluster-locator/__snapshots__/CatalogClusterLocator.test.ts.snap b/plugins/kubernetes-backend/src/cluster-locator/__snapshots__/CatalogClusterLocator.test.ts.snap index f8b3e71515..64526faacb 100644 --- a/plugins/kubernetes-backend/src/cluster-locator/__snapshots__/CatalogClusterLocator.test.ts.snap +++ b/plugins/kubernetes-backend/src/cluster-locator/__snapshots__/CatalogClusterLocator.test.ts.snap @@ -1,4 +1,4 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`CatalogClusterLocator returns the aws cluster details provided by annotations 1`] = ` { diff --git a/plugins/kubernetes-cluster/CHANGELOG.md b/plugins/kubernetes-cluster/CHANGELOG.md index f61279e01b..5666354a62 100644 --- a/plugins/kubernetes-cluster/CHANGELOG.md +++ b/plugins/kubernetes-cluster/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-kubernetes-cluster +## 0.0.32 + +### Patch Changes + +- 2bae83a: Bumped dev dependencies `@types/node` +- Updated dependencies + - @backstage/plugin-kubernetes-react@0.5.14 + - @backstage/core-components@0.18.4 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/plugin-kubernetes-common@0.9.9 + - @backstage/core-plugin-api@1.12.1 + - @backstage/plugin-permission-react@0.4.39 + +## 0.0.32-next.2 + +### Patch Changes + +- 2bae83a: Bumped dev dependencies `@types/node` +- Updated dependencies + - @backstage/plugin-catalog-react@1.21.4-next.2 + - @backstage/core-components@0.18.4-next.2 + - @backstage/catalog-model@1.7.6 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/plugin-kubernetes-common@0.9.9-next.0 + - @backstage/plugin-kubernetes-react@0.5.14-next.1 + - @backstage/plugin-permission-react@0.4.39-next.0 + ## 0.0.32-next.1 ### Patch Changes diff --git a/plugins/kubernetes-cluster/package.json b/plugins/kubernetes-cluster/package.json index f5f67971f9..4e43179c0c 100644 --- a/plugins/kubernetes-cluster/package.json +++ b/plugins/kubernetes-cluster/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-kubernetes-cluster", - "version": "0.0.32-next.1", + "version": "0.0.32", "description": "A Backstage plugin that shows details of Kubernetes clusters", "backstage": { "role": "frontend-plugin", diff --git a/plugins/kubernetes-common/CHANGELOG.md b/plugins/kubernetes-common/CHANGELOG.md index 902a7e1f1d..de8f93897c 100644 --- a/plugins/kubernetes-common/CHANGELOG.md +++ b/plugins/kubernetes-common/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/plugin-kubernetes-common +## 0.9.9 + +### Patch Changes + +- 8fa8d87: Add Kubernetes Plugin Secrets Accordion with masked secret datas + ## 0.9.9-next.0 ### Patch Changes diff --git a/plugins/kubernetes-common/package.json b/plugins/kubernetes-common/package.json index 512ed1f7eb..db2d9c2837 100644 --- a/plugins/kubernetes-common/package.json +++ b/plugins/kubernetes-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-kubernetes-common", - "version": "0.9.9-next.0", + "version": "0.9.9", "description": "Common functionalities for kubernetes, to be shared between kubernetes and kubernetes-backend plugin", "backstage": { "role": "common-library", diff --git a/plugins/kubernetes-node/CHANGELOG.md b/plugins/kubernetes-node/CHANGELOG.md index d3f12c3c7d..a0fad104d8 100644 --- a/plugins/kubernetes-node/CHANGELOG.md +++ b/plugins/kubernetes-node/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-kubernetes-node +## 0.4.0 + +### Minor Changes + +- 7f9846f: Add possibility to extends Kubernetes REST API. Add fetcher to parameters for custom objects provider + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-kubernetes-common@0.9.9 + +## 0.4.0-next.2 + +### Minor Changes + +- 7f9846f: Add possibility to extends Kubernetes REST API. Add fetcher to parameters for custom objects provider + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/types@1.2.2 + - @backstage/plugin-kubernetes-common@0.9.9-next.0 + ## 0.3.7-next.1 ### Patch Changes diff --git a/plugins/kubernetes-node/package.json b/plugins/kubernetes-node/package.json index 9796e05212..8778449eaa 100644 --- a/plugins/kubernetes-node/package.json +++ b/plugins/kubernetes-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-kubernetes-node", - "version": "0.3.7-next.1", + "version": "0.4.0", "description": "Node.js library for the kubernetes plugin", "backstage": { "role": "node-library", diff --git a/plugins/kubernetes-react/CHANGELOG.md b/plugins/kubernetes-react/CHANGELOG.md index b260e25475..d1bb328016 100644 --- a/plugins/kubernetes-react/CHANGELOG.md +++ b/plugins/kubernetes-react/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-kubernetes-react +## 0.5.14 + +### Patch Changes + +- f966a85: Enabled a pod terminal at GKE +- 8fa8d87: Add Kubernetes Plugin Secrets Accordion with masked secret datas +- f15d5f1: add missing i18n support for kubernetes and kubernetes-react +- Updated dependencies + - @backstage/core-components@0.18.4 + - @backstage/plugin-kubernetes-common@0.9.9 + - @backstage/core-plugin-api@1.12.1 + ## 0.5.14-next.1 ### Patch Changes diff --git a/plugins/kubernetes-react/package.json b/plugins/kubernetes-react/package.json index da1b5f6e3e..a634594e60 100644 --- a/plugins/kubernetes-react/package.json +++ b/plugins/kubernetes-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-kubernetes-react", - "version": "0.5.14-next.1", + "version": "0.5.14", "description": "Web library for the kubernetes-react plugin", "backstage": { "role": "web-library", @@ -84,7 +84,7 @@ "@testing-library/react": "^16.0.0", "@types/react": "^18.0.0", "jest-websocket-mock": "^2.5.0", - "msw": "^1.3.1", + "msw": "^2.0.0", "react": "^18.0.2", "react-dom": "^18.0.2", "react-router-dom": "^6.3.0" diff --git a/plugins/kubernetes-react/src/api/KubernetesBackendClient.test.ts b/plugins/kubernetes-react/src/api/KubernetesBackendClient.test.ts index 4698f01dfe..3e8b7aa437 100644 --- a/plugins/kubernetes-react/src/api/KubernetesBackendClient.test.ts +++ b/plugins/kubernetes-react/src/api/KubernetesBackendClient.test.ts @@ -16,7 +16,7 @@ import { KubernetesAuthProvidersApi } from '../kubernetes-auth-provider'; import { KubernetesBackendClient } from './KubernetesBackendClient'; -import { rest } from 'msw'; +import { http, HttpResponse } from 'msw'; import { UrlPatternDiscovery } from '@backstage/core-app-api'; import { setupServer } from 'msw/node'; import { MockFetchApi, registerMswTestHooks } from '@backstage/test-utils'; @@ -89,23 +89,24 @@ describe('KubernetesBackendClient', () => { it('hits the /clusters API', async () => { identityApi.getCredentials.mockResolvedValue({ token: 'idToken' }); worker.use( - rest.get('http://localhost:1234/api/kubernetes/clusters', (_, res, ctx) => - res(ctx.json({ items: [{ name: 'cluster-a', authProvider: 'aws' }] })), + http.get('http://localhost:1234/api/kubernetes/clusters', () => + HttpResponse.json({ + items: [{ name: 'cluster-a', authProvider: 'aws' }], + }), ), ); const clusters = await backendClient.getClusters(); - expect(clusters).toStrictEqual([ - { name: 'cluster-a', authProvider: 'aws' }, - ]); + expect(clusters).toEqual([{ name: 'cluster-a', authProvider: 'aws' }]); }); it('/clusters API throws a 404 Error', async () => { identityApi.getCredentials.mockResolvedValue({ token: 'idToken' }); worker.use( - rest.get('http://localhost:1234/api/kubernetes/clusters', (_, res, ctx) => - res(ctx.status(404)), + http.get( + 'http://localhost:1234/api/kubernetes/clusters', + () => new HttpResponse(null, { status: 404 }), ), ); @@ -117,8 +118,9 @@ describe('KubernetesBackendClient', () => { it('/clusters API throws a 500 Error', async () => { identityApi.getCredentials.mockResolvedValue({ token: 'idToken' }); worker.use( - rest.get('http://localhost:1234/api/kubernetes/clusters', (_, res, ctx) => - res(ctx.status(500)), + http.get( + 'http://localhost:1234/api/kubernetes/clusters', + () => new HttpResponse(null, { status: 500 }), ), ); @@ -130,9 +132,9 @@ describe('KubernetesBackendClient', () => { it('hits the /resources/custom/query API', async () => { identityApi.getCredentials.mockResolvedValue({ token: 'idToken' }); worker.use( - rest.post( + http.post( 'http://localhost:1234/api/kubernetes/resources/custom/query', - (_, res, ctx) => res(ctx.json(mockResponse)), + () => HttpResponse.json(mockResponse), ), ); @@ -157,15 +159,15 @@ describe('KubernetesBackendClient', () => { const customObject: ObjectsByEntityResponse = await backendClient.getCustomObjectsByEntity(request); - expect(customObject).toStrictEqual(mockResponse); + expect(customObject).toEqual(mockResponse); }); it('/resources/custom/query API throws a 404 error', async () => { identityApi.getCredentials.mockResolvedValue({ token: 'idToken' }); worker.use( - rest.post( + http.post( 'http://localhost:1234/api/kubernetes/resources/custom/query', - (_, res, ctx) => res(ctx.status(404)), + () => new HttpResponse(null, { status: 404 }), ), ); @@ -197,9 +199,9 @@ describe('KubernetesBackendClient', () => { it('/resources/custom/query API throws a 500 error', async () => { identityApi.getCredentials.mockResolvedValue({ token: 'idToken' }); worker.use( - rest.post( + http.post( 'http://localhost:1234/api/kubernetes/resources/custom/query', - (_, res, ctx) => res(ctx.status(500)), + () => new HttpResponse(null, { status: 500 }), ), ); @@ -231,9 +233,8 @@ describe('KubernetesBackendClient', () => { it('hits the /services/{entityName} API', async () => { identityApi.getCredentials.mockResolvedValue({ token: 'idToken' }); worker.use( - rest.post( - 'http://localhost:1234/api/kubernetes/services/test-name', - (_, res, ctx) => res(ctx.json(mockResponse)), + http.post('http://localhost:1234/api/kubernetes/services/test-name', () => + HttpResponse.json(mockResponse), ), ); @@ -250,15 +251,15 @@ describe('KubernetesBackendClient', () => { const entityObject: ObjectsByEntityResponse = await backendClient.getObjectsByEntity(request); - expect(entityObject).toStrictEqual(mockResponse); + expect(entityObject).toEqual(mockResponse); }); it('services/{entityName} API throws a 404 error', async () => { identityApi.getCredentials.mockResolvedValue({ token: 'idToken' }); worker.use( - rest.post( + http.post( 'http://localhost:1234/api/kubernetes/services/test-name', - (_, res, ctx) => res(ctx.status(404)), + () => new HttpResponse(null, { status: 404 }), ), ); @@ -282,9 +283,9 @@ describe('KubernetesBackendClient', () => { it('services/{entityName} API throws a 500 error', async () => { identityApi.getCredentials.mockResolvedValue({ token: 'idToken' }); worker.use( - rest.post( + http.post( 'http://localhost:1234/api/kubernetes/services/test-name', - (_, res, ctx) => res(ctx.status(500)), + () => new HttpResponse(null, { status: 500 }), ), ); @@ -308,9 +309,9 @@ describe('KubernetesBackendClient', () => { it('hits the /resources/workloads/query API', async () => { identityApi.getCredentials.mockResolvedValue({ token: 'idToken' }); worker.use( - rest.post( + http.post( 'http://localhost:1234/api/kubernetes/resources/workloads/query', - (_, res, ctx) => res(ctx.json(mockResponse)), + () => HttpResponse.json(mockResponse), ), ); @@ -328,15 +329,15 @@ describe('KubernetesBackendClient', () => { const response: ObjectsByEntityResponse = await backendClient.getWorkloadsByEntity(request); - expect(response).toStrictEqual(mockResponse); + expect(response).toEqual(mockResponse); }); it('/resources/workloads/query API throws a 404 error', async () => { identityApi.getCredentials.mockResolvedValue({ token: 'idToken' }); worker.use( - rest.post( + http.post( 'http://localhost:1234/api/kubernetes/resources/workloads/query', - (_, res, ctx) => res(ctx.status(404)), + () => new HttpResponse(null, { status: 404 }), ), ); @@ -361,9 +362,9 @@ describe('KubernetesBackendClient', () => { it('/resources/workloads/query API throws a 500 error', async () => { identityApi.getCredentials.mockResolvedValue({ token: 'idToken' }); worker.use( - rest.post( + http.post( 'http://localhost:1234/api/kubernetes/resources/workloads/query', - (_, res, ctx) => res(ctx.status(500)), + () => new HttpResponse(null, { status: 500 }), ), ); @@ -388,12 +389,10 @@ describe('KubernetesBackendClient', () => { describe('proxy', () => { beforeEach(() => { worker.use( - rest.get( - 'http://localhost:1234/api/kubernetes/clusters', - (_, res, ctx) => - res( - ctx.json({ items: [{ name: 'cluster-a', authProvider: 'aws' }] }), - ), + http.get('http://localhost:1234/api/kubernetes/clusters', () => + HttpResponse.json({ + items: [{ name: 'cluster-a', authProvider: 'aws' }], + }), ), ); identityApi.getCredentials.mockResolvedValue({ token: 'idToken' }); @@ -401,20 +400,16 @@ describe('KubernetesBackendClient', () => { it('hits the /proxy API with oidc as protocol and okta as auth provider', async () => { worker.use( - rest.get( - 'http://localhost:1234/api/kubernetes/clusters', - (_, res, ctx) => - res( - ctx.json({ - items: [ - { - name: 'cluster-a', - authProvider: 'oidc', - oidcTokenProvider: 'okta', - }, - ], - }), - ), + http.get('http://localhost:1234/api/kubernetes/clusters', () => + HttpResponse.json({ + items: [ + { + name: 'cluster-a', + authProvider: 'oidc', + oidcTokenProvider: 'okta', + }, + ], + }), ), ); kubernetesAuthProvidersApi.getCredentials.mockResolvedValue({ @@ -428,16 +423,14 @@ describe('KubernetesBackendClient', () => { }, }; worker.use( - rest.get( + http.get( 'http://localhost:1234/api/kubernetes/proxy/api/v1/namespaces', - (req, res, ctx) => - res( - req.headers.get( - 'Backstage-Kubernetes-Authorization-oidc-okta', - ) === 'k8-token3' - ? ctx.json(nsResponse) - : ctx.status(403), - ), + ({ request }) => + request.headers.get( + 'Backstage-Kubernetes-Authorization-oidc-okta', + ) === 'k8-token3' + ? HttpResponse.json(nsResponse) + : new HttpResponse(null, { status: 403 }), ), ); @@ -448,7 +441,7 @@ describe('KubernetesBackendClient', () => { const response = await backendClient.proxy(request); - await expect(response.json()).resolves.toStrictEqual(nsResponse); + await expect(response.json()).resolves.toEqual(nsResponse); expect(kubernetesAuthProvidersApi.getCredentials).toHaveBeenCalledWith( 'oidc.okta', ); @@ -457,19 +450,15 @@ describe('KubernetesBackendClient', () => { it('hits the /proxy API with serviceAccount as auth provider', async () => { identityApi.getCredentials.mockResolvedValue({ token: 'idToken' }); worker.use( - rest.get( - 'http://localhost:1234/api/kubernetes/clusters', - (_, res, ctx) => - res( - ctx.json({ - items: [ - { - name: 'cluster-a', - authProvider: 'serviceAccount', - }, - ], - }), - ), + http.get('http://localhost:1234/api/kubernetes/clusters', () => + HttpResponse.json({ + items: [ + { + name: 'cluster-a', + authProvider: 'serviceAccount', + }, + ], + }), ), ); @@ -481,14 +470,12 @@ describe('KubernetesBackendClient', () => { }, }; worker.use( - rest.get( + http.get( 'http://localhost:1234/api/kubernetes/proxy/api/v1/namespaces', - (req, res, ctx) => - res( - req.headers.get('Authorization') === 'Bearer idToken' - ? ctx.json(nsResponse) - : ctx.status(403), - ), + ({ request }) => + request.headers.get('Authorization') === 'Bearer idToken' + ? HttpResponse.json(nsResponse) + : new HttpResponse(null, { status: 403 }), ), ); @@ -499,7 +486,7 @@ describe('KubernetesBackendClient', () => { const response = await backendClient.proxy(request); - await expect(response.json()).resolves.toStrictEqual(nsResponse); + await expect(response.json()).resolves.toEqual(nsResponse); expect(kubernetesAuthProvidersApi.getCredentials).toHaveBeenCalledWith( 'serviceAccount', ); @@ -507,24 +494,20 @@ describe('KubernetesBackendClient', () => { it('ignores oidcTokenProvider for non-oidc auth provider', async () => { worker.use( - rest.get( - 'http://localhost:1234/api/kubernetes/clusters', - (_, res, ctx) => - res( - ctx.json({ - items: [ - { - name: 'cluster-a', - authProvider: 'not oidc', - oidcTokenProvider: 'should be ignored', - }, - ], - }), - ), + http.get('http://localhost:1234/api/kubernetes/clusters', () => + HttpResponse.json({ + items: [ + { + name: 'cluster-a', + authProvider: 'not oidc', + oidcTokenProvider: 'should be ignored', + }, + ], + }), ), - rest.get( + http.get( 'http://localhost:1234/api/kubernetes/proxy/api/v1/namespaces', - (_, res, ctx) => res(ctx.json([])), + () => HttpResponse.json([]), ), ); @@ -552,15 +535,13 @@ describe('KubernetesBackendClient', () => { }, }; worker.use( - rest.get( + http.get( 'http://localhost:1234/api/kubernetes/proxy/api/v1/namespaces', - (req, res, ctx) => - res( - req.headers.get('Backstage-Kubernetes-Authorization-aws') === - 'k8-token' - ? ctx.json(nsResponse) - : ctx.status(403), - ), + ({ request }) => + request.headers.get('Backstage-Kubernetes-Authorization-aws') === + 'k8-token' + ? HttpResponse.json(nsResponse) + : new HttpResponse(null, { status: 403 }), ), ); @@ -570,7 +551,7 @@ describe('KubernetesBackendClient', () => { }; const response = await backendClient.proxy(request); - await expect(response.json()).resolves.toStrictEqual(nsResponse); + await expect(response.json()).resolves.toEqual(nsResponse); }); it('/proxy API throws a 404 error', async () => { @@ -578,9 +559,9 @@ describe('KubernetesBackendClient', () => { token: 'k8-token', }); worker.use( - rest.get( + http.get( 'http://localhost:1234/api/kubernetes/proxy/api/v1/namespaces', - (_, res, ctx) => res(ctx.status(404)), + () => new HttpResponse(null, { status: 404 }), ), ); @@ -616,15 +597,13 @@ describe('KubernetesBackendClient', () => { }, }; worker.use( - rest.get( + http.get( 'http://localhost:1234/api/kubernetes/proxy/api/v1/namespaces', - (req, res, ctx) => - res( - req.headers.get('Backstage-Kubernetes-Authorization') === - 'Bearer k8-token' - ? ctx.json(nsResponse) - : ctx.status(403), - ), + ({ request }) => + request.headers.get('Backstage-Kubernetes-Authorization') === + 'Bearer k8-token' + ? HttpResponse.json(nsResponse) + : new HttpResponse(null, { status: 403 }), ), ); @@ -646,14 +625,12 @@ describe('KubernetesBackendClient', () => { }, }; worker.use( - rest.get( + http.get( 'http://localhost:1234/api/kubernetes/proxy/api/v1/namespaces/new-ns', - (req, res, ctx) => - res( - req.headers.get('Backstage-Kubernetes-Authorization') - ? ctx.status(403) - : ctx.json(nsResponse), - ), + ({ request }) => + request.headers.get('Backstage-Kubernetes-Authorization') + ? new HttpResponse(null, { status: 403 }) + : HttpResponse.json(nsResponse), ), ); kubernetesAuthProvidersApi.getCredentials.mockResolvedValue({}); @@ -663,7 +640,7 @@ describe('KubernetesBackendClient', () => { path: '/api/v1/namespaces/new-ns', }); - await expect(response.json()).resolves.toStrictEqual(nsResponse); + await expect(response.json()).resolves.toEqual(nsResponse); }); }); }); diff --git a/plugins/kubernetes-react/src/api/formatters/HeadlampClusterLinksFormatter.test.ts b/plugins/kubernetes-react/src/api/formatters/HeadlampClusterLinksFormatter.test.ts index 533e966137..12de678718 100644 --- a/plugins/kubernetes-react/src/api/formatters/HeadlampClusterLinksFormatter.test.ts +++ b/plugins/kubernetes-react/src/api/formatters/HeadlampClusterLinksFormatter.test.ts @@ -21,11 +21,6 @@ describe('HeadlampClusterLinksFormatter', () => { beforeEach(() => { formatter = new HeadlampClusterLinksFormatter(); - // Mock window.location.origin - Object.defineProperty(window, 'location', { - value: { origin: 'http://localhost:3000' }, - writable: true, - }); }); it('formats internal dashboard link correctly', async () => { @@ -41,7 +36,7 @@ describe('HeadlampClusterLinksFormatter', () => { const result = await formatter.formatClusterLink(options); expect(result.toString()).toBe( - 'http://localhost:3000/headlamp?to=%2Fc%2Ftest-cluster%2Fpods%2Fdefault%2Ftest-pod', + 'http://localhost/headlamp?to=%2Fc%2Ftest-cluster%2Fpods%2Fdefault%2Ftest-pod', ); }); diff --git a/plugins/kubernetes/CHANGELOG.md b/plugins/kubernetes/CHANGELOG.md index 3780dee9c6..3aeaa369fa 100644 --- a/plugins/kubernetes/CHANGELOG.md +++ b/plugins/kubernetes/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-kubernetes +## 0.12.14 + +### Patch Changes + +- f15d5f1: add missing i18n support for kubernetes and kubernetes-react +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/plugin-kubernetes-react@0.5.14 + - @backstage/core-components@0.18.4 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/plugin-kubernetes-common@0.9.9 + - @backstage/core-plugin-api@1.12.1 + - @backstage/plugin-permission-react@0.4.39 + ## 0.12.14-next.1 ### Patch Changes diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index a455747640..33692f5886 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-kubernetes", - "version": "0.12.14-next.1", + "version": "0.12.14", "description": "A Backstage plugin that integrates towards Kubernetes", "backstage": { "role": "frontend-plugin", diff --git a/plugins/mcp-actions-backend/CHANGELOG.md b/plugins/mcp-actions-backend/CHANGELOG.md index 78341c0273..c91b47584c 100644 --- a/plugins/mcp-actions-backend/CHANGELOG.md +++ b/plugins/mcp-actions-backend/CHANGELOG.md @@ -1,5 +1,43 @@ # @backstage/plugin-mcp-actions-backend +## 0.1.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.14.1-next.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/catalog-client@1.12.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-node@1.20.1 + +## 0.1.6 + +### Patch Changes + +- e83e038: Added `@cfworker/json-schema` as a dependency to this package part of the `@modelcontextprotocol/sdk` bump as it's required in the types +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- 79ef471: Clarify error handling in readme and update handleError.ts to include all backstage/errors +- Updated dependencies + - @backstage/backend-defaults@0.14.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## 0.1.6-next.1 + +### Patch Changes + +- e83e038: Added `@cfworker/json-schema` as a dependency to this package part of the `@modelcontextprotocol/sdk` bump as it's required in the types +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-defaults@0.14.0-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-client@1.12.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-node@1.20.1-next.1 + ## 0.1.6-next.0 ### Patch Changes diff --git a/plugins/mcp-actions-backend/package.json b/plugins/mcp-actions-backend/package.json index da90397438..b99cb48afe 100644 --- a/plugins/mcp-actions-backend/package.json +++ b/plugins/mcp-actions-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-mcp-actions-backend", - "version": "0.1.6-next.0", + "version": "0.1.7-next.0", "backstage": { "role": "backend-plugin", "pluginId": "mcp-actions", @@ -40,7 +40,8 @@ "@backstage/errors": "workspace:^", "@backstage/plugin-catalog-node": "workspace:^", "@backstage/types": "workspace:^", - "@modelcontextprotocol/sdk": "^1.12.3", + "@cfworker/json-schema": "^4.1.1", + "@modelcontextprotocol/sdk": "^1.24.3", "express": "^4.22.0", "express-promise-router": "^4.1.0", "zod": "^3.22.4" diff --git a/plugins/mui-to-bui/CHANGELOG.md b/plugins/mui-to-bui/CHANGELOG.md index 81ccaeb013..7f4a45c885 100644 --- a/plugins/mui-to-bui/CHANGELOG.md +++ b/plugins/mui-to-bui/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-mui-to-bui +## 0.2.3-next.0 + +### Patch Changes + +- e4a1180: Updated tokens from `--bui-bg` to `--bui-bg-surface-0` +- Updated dependencies + - @backstage/ui@0.11.0-next.0 + - @backstage/core-plugin-api@1.12.1 + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/theme@0.7.1 + +## 0.2.2 + +### Patch Changes + +- Updated dependencies + - @backstage/ui@0.10.0 + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-plugin-api@1.12.1 + - @backstage/theme@0.7.1 + ## 0.2.2-next.1 ### Patch Changes diff --git a/plugins/mui-to-bui/package.json b/plugins/mui-to-bui/package.json index f5f014a9ed..2305eec5a3 100644 --- a/plugins/mui-to-bui/package.json +++ b/plugins/mui-to-bui/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-mui-to-bui", - "version": "0.2.2-next.1", + "version": "0.2.3-next.0", "backstage": { "role": "frontend-plugin", "pluginId": "mui-to-bui", diff --git a/plugins/mui-to-bui/src/components/BuiThemerPage/convertMuiToBuiTheme.test.ts b/plugins/mui-to-bui/src/components/BuiThemerPage/convertMuiToBuiTheme.test.ts index 6ba3f7d2d9..48bb318a71 100644 --- a/plugins/mui-to-bui/src/components/BuiThemerPage/convertMuiToBuiTheme.test.ts +++ b/plugins/mui-to-bui/src/components/BuiThemerPage/convertMuiToBuiTheme.test.ts @@ -59,7 +59,7 @@ describe('convertMuiToBuiTheme', () => { // Border radius tokens are only generated when radius is 0 expect(result.css).not.toContain('--bui-radius-3:'); // Background default maps to surface-2 - expect(result.css).toContain('--bui-bg: #f5f5f5;'); + expect(result.css).toContain('--bui-bg-surface-0: #f5f5f5;'); expect(result.css).toContain('--bui-bg-surface-2: #f5f5f5;'); expect(result.css).toContain('--bui-bg-surface-1: #ffffff;'); expect(result.css).toContain('--bui-fg-primary: #000000;'); @@ -98,7 +98,7 @@ describe('convertMuiToBuiTheme', () => { expect(result.css).toContain("[data-theme-mode='dark'] {"); // Background default maps to surface-2 in dark mode as well - expect(result.css).toContain('--bui-bg: #121212;'); + expect(result.css).toContain('--bui-bg-surface-0: #121212;'); expect(result.css).toContain('--bui-bg-surface-2: #121212;'); expect(result.css).toContain('--bui-bg-surface-1: #1e1e1e;'); expect(result.css).toContain('--bui-fg-primary: #ffffff;'); diff --git a/plugins/mui-to-bui/src/components/BuiThemerPage/convertMuiToBuiTheme.ts b/plugins/mui-to-bui/src/components/BuiThemerPage/convertMuiToBuiTheme.ts index 1b8528922b..029d70cec7 100644 --- a/plugins/mui-to-bui/src/components/BuiThemerPage/convertMuiToBuiTheme.ts +++ b/plugins/mui-to-bui/src/components/BuiThemerPage/convertMuiToBuiTheme.ts @@ -110,9 +110,10 @@ function generateBuiVariables(theme: Mui5Theme): Record { // Generate surface colors Object.entries({ - '': palette.background.default, + 'surface-0': palette.background.default, 'surface-1': palette.background.paper, 'surface-2': palette.background.default, + 'surface-3': palette.background.default, solid: palette.primary.main, 'solid-hover': blend(palette.primary.main, palette.primary.dark, 0.5), 'solid-pressed': palette.primary.dark, @@ -125,7 +126,7 @@ function generateBuiVariables(theme: Mui5Theme): Record { warning: palette.warning.light, success: palette.success.light, }).forEach(([key, value]) => { - styleObject[`--bui-bg${key ? `-${key}` : ''}`] = value; + styleObject[`--bui-bg-${key}`] = value; }); // Border colors diff --git a/plugins/notifications-backend-module-email/CHANGELOG.md b/plugins/notifications-backend-module-email/CHANGELOG.md index feade91398..21cb61c4c4 100644 --- a/plugins/notifications-backend-module-email/CHANGELOG.md +++ b/plugins/notifications-backend-module-email/CHANGELOG.md @@ -1,5 +1,49 @@ # @backstage/plugin-notifications-backend-module-email +## 0.3.17 + +### Patch Changes + +- a5d5b3a: SES config for the notification email processor now supports utilizing an ARN for the SES identity when sending an email after the SES SDK V2 update. + + The `sesConfig.fromArn` will set the `fromEmailAddressIdentityArn` option for the SES `SendEmailCommand`. The `sesConfig.sourceArn` field is removed since no equivalent option is available in the send email command options. Setting `sesConfig.sourceArn` will have no effect and log a warning. Example changes: + + ```diff + notifications: + processors: + email: + transportConfig: + transport: "ses" + region: "us-west-2" + sender: "sender@mycompany.com" + replyTo: "no-reply@mycompany.com" + sesConfig: + - sourceArn: "arn:aws:ses:us-west-2:123456789012:identity/example.com" + fromArn: "arn:aws:ses:us-west-2:123456789012:identity/example.com" + ``` + +- b267aea: Updated dependency `@types/nodemailer` to `^7.0.0`. +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + - @backstage/plugin-notifications-node@0.2.22 + +## 0.3.17-next.1 + +### Patch Changes + +- b267aea: Updated dependency `@types/nodemailer` to `^7.0.0`. +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/integration-aws-node@0.1.19 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-node@1.20.1-next.1 + - @backstage/plugin-notifications-common@0.2.0 + - @backstage/plugin-notifications-node@0.2.22-next.1 + ## 0.3.17-next.0 ### Patch Changes diff --git a/plugins/notifications-backend-module-email/README.md b/plugins/notifications-backend-module-email/README.md index c1ead48876..248bb2c501 100644 --- a/plugins/notifications-backend-module-email/README.md +++ b/plugins/notifications-backend-module-email/README.md @@ -81,7 +81,6 @@ notifications: receiver: 'users' # Optional SES config # sesConfig: - # sourceArn: 'arn:aws:ses:us-west-2:123456789012:identity/example.com' # fromArn: 'arn:aws:ses:us-west-2:123456789012:identity/example.com' # configurationSetName: 'custom-config' # How many emails to send concurrently, defaults to 2 diff --git a/plugins/notifications-backend-module-email/config.d.ts b/plugins/notifications-backend-module-email/config.d.ts index 7116826c5d..55a751f8fa 100644 --- a/plugins/notifications-backend-module-email/config.d.ts +++ b/plugins/notifications-backend-module-email/config.d.ts @@ -136,10 +136,6 @@ export interface Config { * Optional SES config for mail options. Allows for delegated sender */ sesConfig?: { - /** - * ARN of the identity to use as the source of the email - */ - sourceArn?: string; /** * ARN of the identity to use for the "From"/sender address of the email */ diff --git a/plugins/notifications-backend-module-email/package.json b/plugins/notifications-backend-module-email/package.json index e62ae5e92f..b1f2831758 100644 --- a/plugins/notifications-backend-module-email/package.json +++ b/plugins/notifications-backend-module-email/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-notifications-backend-module-email", - "version": "0.3.17-next.0", + "version": "0.3.17", "description": "The email backend module for the notifications plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/notifications-backend-module-email/src/processor/NotificationsEmailProcessor.test.ts b/plugins/notifications-backend-module-email/src/processor/NotificationsEmailProcessor.test.ts index ebe1b90f35..ad0817521f 100644 --- a/plugins/notifications-backend-module-email/src/processor/NotificationsEmailProcessor.test.ts +++ b/plugins/notifications-backend-module-email/src/processor/NotificationsEmailProcessor.test.ts @@ -497,9 +497,13 @@ describe('NotificationsEmailProcessor', () => { text: 'https://example.org/notifications', to: 'mock@backstage.io', ses: { - SourceArn: 'arn:aws:ses:us-west-2:123456789012:identity/example.com', - FromArn: 'arn:aws:ses:us-west-2:123456789012:identity/example.com', + FromEmailAddressIdentityArn: + 'arn:aws:ses:us-west-2:123456789012:identity/example.com', }, }); + + expect(logger.warn).toHaveBeenCalledWith( + 'sourceArn is not supported in SESv2 and will be ignored', + ); }); }); diff --git a/plugins/notifications-backend-module-email/src/processor/NotificationsEmailProcessor.ts b/plugins/notifications-backend-module-email/src/processor/NotificationsEmailProcessor.ts index eadfe7747e..e0e27232c2 100644 --- a/plugins/notifications-backend-module-email/src/processor/NotificationsEmailProcessor.ts +++ b/plugins/notifications-backend-module-email/src/processor/NotificationsEmailProcessor.ts @@ -45,6 +45,7 @@ import { DefaultAwsCredentialsManager } from '@backstage/integration-aws-node'; import { NotificationTemplateRenderer } from '../extensions'; import Mail from 'nodemailer/lib/mailer'; import pThrottle from 'p-throttle'; +import { SendEmailCommandInput } from '@aws-sdk/client-sesv2'; export class NotificationsEmailProcessor implements NotificationProcessor { private transporter: any; @@ -53,6 +54,7 @@ export class NotificationsEmailProcessor implements NotificationProcessor { private readonly sender: string; private readonly replyTo?: string; private readonly sesConfig?: Config; + private readonly sesOptions?: Partial; private readonly cacheTtl: number; private readonly concurrencyLimit: number; private readonly throttleInterval: number; @@ -91,6 +93,7 @@ export class NotificationsEmailProcessor implements NotificationProcessor { this.sender = emailProcessorConfig.getString('sender'); this.replyTo = emailProcessorConfig.getOptionalString('replyTo'); this.sesConfig = emailProcessorConfig.getOptionalConfig('sesConfig'); + this.sesOptions = this.getSesOptions(); this.concurrencyLimit = emailProcessorConfig.getOptionalNumber('concurrencyLimit') ?? 2; this.throttleInterval = emailProcessorConfig.has('throttleInterval') @@ -307,20 +310,23 @@ export class NotificationsEmailProcessor implements NotificationProcessor { return contentParts.join('\n\n'); } - private async getSesOptions() { + private getSesOptions(): Partial | undefined { if (!this.sesConfig) { return undefined; } - const ses: Record = {}; - const sourceArn = this.sesConfig.getOptionalString('sourceArn'); + const ses: Partial = {}; const fromArn = this.sesConfig.getOptionalString('fromArn'); + const sourceArn = this.sesConfig.getOptionalString('sourceArn'); const configurationSetName = this.sesConfig.getOptionalString( 'configurationSetName', ); - if (sourceArn) ses.SourceArn = sourceArn; - if (fromArn) ses.FromArn = fromArn; + if (fromArn) ses.FromEmailAddressIdentityArn = fromArn; if (configurationSetName) ses.ConfigurationSetName = configurationSetName; + if (sourceArn) + this.logger.warn( + 'sourceArn is not supported in SESv2 and will be ignored', + ); return Object.keys(ses).length > 0 ? ses : undefined; } @@ -332,7 +338,7 @@ export class NotificationsEmailProcessor implements NotificationProcessor { html: this.getHtmlContent(notification), text: this.getTextContent(notification), replyTo: this.replyTo, - ses: await this.getSesOptions(), + ses: this.sesOptions, }; await this.sendMails(mailOptions, emails); @@ -350,7 +356,7 @@ export class NotificationsEmailProcessor implements NotificationProcessor { html: await this.templateRenderer?.getHtml?.(notification), text: await this.templateRenderer?.getText?.(notification), replyTo: this.replyTo, - ses: await this.getSesOptions(), + ses: this.sesOptions, }; await this.sendMails(mailOptions, emails); diff --git a/plugins/notifications-backend-module-slack/CHANGELOG.md b/plugins/notifications-backend-module-slack/CHANGELOG.md index 9000ef2203..4d9c711297 100644 --- a/plugins/notifications-backend-module-slack/CHANGELOG.md +++ b/plugins/notifications-backend-module-slack/CHANGELOG.md @@ -1,5 +1,34 @@ # @backstage/plugin-notifications-backend-module-slack +## 0.3.0 + +### Minor Changes + +- f95a516: Enables optional routes to Slack channels for broadcast notifications based on origin and/or topics. + +### Patch Changes + +- b80857a: Slack notification handler throttling can now be configured with the `concurrencyLimit` and `throttleInterval` options. +- f8230e4: Updated dependency `@faker-js/faker` to `^10.0.0`. +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + - @backstage/plugin-notifications-node@0.2.22 + +## 0.2.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-node@1.20.1-next.1 + - @backstage/plugin-notifications-common@0.2.0 + - @backstage/plugin-notifications-node@0.2.22-next.1 + ## 0.2.2-next.0 ### Patch Changes diff --git a/plugins/notifications-backend-module-slack/config.d.ts b/plugins/notifications-backend-module-slack/config.d.ts index 8cd450940e..17a4e25e0d 100644 --- a/plugins/notifications-backend-module-slack/config.d.ts +++ b/plugins/notifications-backend-module-slack/config.d.ts @@ -13,6 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { HumanDuration } from '@backstage/types'; + export interface Config { notifications?: { processors?: { @@ -26,8 +28,40 @@ export interface Config { * Broadcast notification receivers when receiver is set to config * These can be Slack User IDs, Slack User Email addresses, Slack Channel * Names, or Slack Channel IDs. Any valid identifier that chat.postMessage can accept. + * @deprecated Use broadcastRoutes instead for more granular control */ broadcastChannels?: string[]; + /** + * Optional username to display as the sender of the notification + */ + username?: string; + /** + * Routes for broadcast notifications based on origin and/or topic. + * Routes are evaluated in order, first match wins. + * Origin+topic matches take precedence over origin-only matches. + */ + broadcastRoutes?: Array<{ + /** + * The origin to match (e.g., 'plugin:catalog', 'external:my-service') + */ + origin?: string; + /** + * The topic to match (e.g., 'entity-updated', 'alerts') + */ + topic?: string; + /** + * The Slack channel(s) to send to. Can be channel IDs, channel names, or user IDs. + */ + channel: string | string[]; + }>; + /** + * Concurrency limit for Slack notifications per backend instance of the notifications plugin, defaults to 10. + */ + concurrencyLimit?: number; + /** + * Throttle duration between Slack notifications per backend instance of the notifications plugin, defaults to 1 minute. + */ + throttleInterval?: HumanDuration | string; }>; }; }; diff --git a/plugins/notifications-backend-module-slack/package.json b/plugins/notifications-backend-module-slack/package.json index 9cb2486d3e..0e35577006 100644 --- a/plugins/notifications-backend-module-slack/package.json +++ b/plugins/notifications-backend-module-slack/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-notifications-backend-module-slack", - "version": "0.2.2-next.0", + "version": "0.3.0", "description": "The slack backend module for the notifications plugin.", "backstage": { "role": "backend-plugin-module", @@ -54,7 +54,7 @@ "@backstage/cli": "workspace:^", "@backstage/plugin-catalog-node": "workspace:^", "@backstage/test-utils": "workspace:^", - "@faker-js/faker": "^8.4.1", + "@faker-js/faker": "^10.0.0", "msw": "^2.0.0" }, "configSchema": "config.d.ts" diff --git a/plugins/notifications-backend-module-slack/src/lib/SlackNotificationProcessor.test.ts b/plugins/notifications-backend-module-slack/src/lib/SlackNotificationProcessor.test.ts index ad4bf01e9f..9490ff7dde 100644 --- a/plugins/notifications-backend-module-slack/src/lib/SlackNotificationProcessor.test.ts +++ b/plugins/notifications-backend-module-slack/src/lib/SlackNotificationProcessor.test.ts @@ -19,6 +19,22 @@ import { SlackNotificationProcessor } from './SlackNotificationProcessor'; import { catalogServiceMock } from '@backstage/plugin-catalog-node/testUtils'; import { WebClient } from '@slack/web-api'; import { Entity } from '@backstage/catalog-model'; +import pThrottle from 'p-throttle'; +import { durationToMilliseconds } from '@backstage/types'; + +const throttleConfigs: Array<{ limit: number; interval: number }> = []; + +jest.mock('p-throttle', () => ({ + __esModule: true, + default: jest.fn((config: { limit: number; interval: number }) => { + throttleConfigs.push(config); + return Promise | any>(fn: T) => + (...args: Parameters) => + Promise.resolve(fn(...args)); + }), +})); + +const mockedPThrottle = pThrottle as jest.MockedFunction; jest.mock('@slack/web-api', () => { const mockSlack = { @@ -128,6 +144,8 @@ describe('SlackNotificationProcessor', () => { beforeEach(() => { jest.clearAllMocks(); + throttleConfigs.length = 0; + mockedPThrottle.mockClear(); }); it('should send a notification to a group', async () => { @@ -393,6 +411,462 @@ describe('SlackNotificationProcessor', () => { }); }); + describe('when broadcast routes are configured', () => { + it('should route by origin and topic (highest priority)', async () => { + const slack = new WebClient(); + const routesConfig = mockServices.rootConfig({ + data: { + app: { + baseUrl: 'https://example.org', + }, + notifications: { + processors: { + slack: [ + { + token: 'mock-token', + broadcastChannels: ['default-channel'], + broadcastRoutes: [ + { origin: 'plugin:catalog', channel: 'catalog-channel' }, + { topic: 'alerts', channel: 'alerts-channel' }, + { + origin: 'plugin:catalog', + topic: 'alerts', + channel: 'catalog-alerts-channel', + }, + ], + }, + ], + }, + }, + }, + }); + + const processor = SlackNotificationProcessor.fromConfig(routesConfig, { + auth, + logger, + catalog: catalogServiceMock({ + entities: DEFAULT_ENTITIES_RESPONSE.items, + }), + slack, + })[0]; + + await processor.postProcess( + { + origin: 'plugin:catalog', + id: '1234', + user: null, + created: new Date(), + payload: { + title: 'notification', + topic: 'alerts', + }, + }, + { + recipients: { type: 'broadcast' }, + payload: { title: 'notification', topic: 'alerts' }, + }, + ); + + expect(slack.chat.postMessage).toHaveBeenCalledTimes(1); + expect(slack.chat.postMessage).toHaveBeenCalledWith( + expect.objectContaining({ channel: 'catalog-alerts-channel' }), + ); + }); + + it('should route by origin only when no origin+topic match', async () => { + const slack = new WebClient(); + const routesConfig = mockServices.rootConfig({ + data: { + app: { + baseUrl: 'https://example.org', + }, + notifications: { + processors: { + slack: [ + { + token: 'mock-token', + broadcastRoutes: [ + { origin: 'plugin:catalog', channel: 'catalog-channel' }, + { topic: 'alerts', channel: 'alerts-channel' }, + ], + }, + ], + }, + }, + }, + }); + + const processor = SlackNotificationProcessor.fromConfig(routesConfig, { + auth, + logger, + catalog: catalogServiceMock({ + entities: DEFAULT_ENTITIES_RESPONSE.items, + }), + slack, + })[0]; + + await processor.postProcess( + { + origin: 'plugin:catalog', + id: '1234', + user: null, + created: new Date(), + payload: { + title: 'notification', + topic: 'updates', + }, + }, + { + recipients: { type: 'broadcast' }, + payload: { title: 'notification', topic: 'updates' }, + }, + ); + + expect(slack.chat.postMessage).toHaveBeenCalledTimes(1); + expect(slack.chat.postMessage).toHaveBeenCalledWith( + expect.objectContaining({ channel: 'catalog-channel' }), + ); + }); + + it('should route by topic only when no origin match', async () => { + const slack = new WebClient(); + const routesConfig = mockServices.rootConfig({ + data: { + app: { + baseUrl: 'https://example.org', + }, + notifications: { + processors: { + slack: [ + { + token: 'mock-token', + broadcastRoutes: [ + { origin: 'plugin:catalog', channel: 'catalog-channel' }, + { topic: 'alerts', channel: 'alerts-channel' }, + ], + }, + ], + }, + }, + }, + }); + + const processor = SlackNotificationProcessor.fromConfig(routesConfig, { + auth, + logger, + catalog: catalogServiceMock({ + entities: DEFAULT_ENTITIES_RESPONSE.items, + }), + slack, + })[0]; + + await processor.postProcess( + { + origin: 'plugin:unknown', + id: '1234', + user: null, + created: new Date(), + payload: { + title: 'notification', + topic: 'alerts', + }, + }, + { + recipients: { type: 'broadcast' }, + payload: { title: 'notification', topic: 'alerts' }, + }, + ); + + expect(slack.chat.postMessage).toHaveBeenCalledTimes(1); + expect(slack.chat.postMessage).toHaveBeenCalledWith( + expect.objectContaining({ channel: 'alerts-channel' }), + ); + }); + + it('should fall back to broadcastChannels when no route matches', async () => { + const slack = new WebClient(); + const routesConfig = mockServices.rootConfig({ + data: { + app: { + baseUrl: 'https://example.org', + }, + notifications: { + processors: { + slack: [ + { + token: 'mock-token', + broadcastChannels: ['default-channel'], + broadcastRoutes: [ + { origin: 'plugin:catalog', channel: 'catalog-channel' }, + ], + }, + ], + }, + }, + }, + }); + + const processor = SlackNotificationProcessor.fromConfig(routesConfig, { + auth, + logger, + catalog: catalogServiceMock({ + entities: DEFAULT_ENTITIES_RESPONSE.items, + }), + slack, + })[0]; + + await processor.postProcess( + { + origin: 'plugin:unknown', + id: '1234', + user: null, + created: new Date(), + payload: { + title: 'notification', + }, + }, + { + recipients: { type: 'broadcast' }, + payload: { title: 'notification' }, + }, + ); + + expect(slack.chat.postMessage).toHaveBeenCalledTimes(1); + expect(slack.chat.postMessage).toHaveBeenCalledWith( + expect.objectContaining({ channel: 'default-channel' }), + ); + }); + + it('should support multiple channels in a route', async () => { + const slack = new WebClient(); + const routesConfig = mockServices.rootConfig({ + data: { + app: { + baseUrl: 'https://example.org', + }, + notifications: { + processors: { + slack: [ + { + token: 'mock-token', + broadcastRoutes: [ + { + origin: 'plugin:catalog', + channel: ['channel1', 'channel2', 'channel3'], + }, + ], + }, + ], + }, + }, + }, + }); + + const processor = SlackNotificationProcessor.fromConfig(routesConfig, { + auth, + logger, + catalog: catalogServiceMock({ + entities: DEFAULT_ENTITIES_RESPONSE.items, + }), + slack, + })[0]; + + await processor.postProcess( + { + origin: 'plugin:catalog', + id: '1234', + user: null, + created: new Date(), + payload: { + title: 'notification', + }, + }, + { + recipients: { type: 'broadcast' }, + payload: { title: 'notification' }, + }, + ); + + expect(slack.chat.postMessage).toHaveBeenCalledTimes(3); + expect(slack.chat.postMessage).toHaveBeenCalledWith( + expect.objectContaining({ channel: 'channel1' }), + ); + expect(slack.chat.postMessage).toHaveBeenCalledWith( + expect.objectContaining({ channel: 'channel2' }), + ); + expect(slack.chat.postMessage).toHaveBeenCalledWith( + expect.objectContaining({ channel: 'channel3' }), + ); + }); + + it('should support single channel as string in a route', async () => { + const slack = new WebClient(); + const routesConfig = mockServices.rootConfig({ + data: { + app: { + baseUrl: 'https://example.org', + }, + notifications: { + processors: { + slack: [ + { + token: 'mock-token', + broadcastRoutes: [ + { topic: 'alerts', channel: 'single-alerts-channel' }, + ], + }, + ], + }, + }, + }, + }); + + const processor = SlackNotificationProcessor.fromConfig(routesConfig, { + auth, + logger, + catalog: catalogServiceMock({ + entities: DEFAULT_ENTITIES_RESPONSE.items, + }), + slack, + })[0]; + + await processor.postProcess( + { + origin: 'plugin:any', + id: '1234', + user: null, + created: new Date(), + payload: { + title: 'notification', + topic: 'alerts', + }, + }, + { + recipients: { type: 'broadcast' }, + payload: { title: 'notification', topic: 'alerts' }, + }, + ); + + expect(slack.chat.postMessage).toHaveBeenCalledTimes(1); + expect(slack.chat.postMessage).toHaveBeenCalledWith( + expect.objectContaining({ channel: 'single-alerts-channel' }), + ); + }); + + it('should not send when no route matches and no broadcastChannels configured', async () => { + const slack = new WebClient(); + const routesConfig = mockServices.rootConfig({ + data: { + app: { + baseUrl: 'https://example.org', + }, + notifications: { + processors: { + slack: [ + { + token: 'mock-token', + broadcastRoutes: [ + { origin: 'plugin:catalog', channel: 'catalog-channel' }, + ], + }, + ], + }, + }, + }, + }); + + const processor = SlackNotificationProcessor.fromConfig(routesConfig, { + auth, + logger, + catalog: catalogServiceMock({ + entities: DEFAULT_ENTITIES_RESPONSE.items, + }), + slack, + })[0]; + + await processor.postProcess( + { + origin: 'plugin:unknown', + id: '1234', + user: null, + created: new Date(), + payload: { + title: 'notification', + topic: 'unknown-topic', + }, + }, + { + recipients: { type: 'broadcast' }, + payload: { title: 'notification', topic: 'unknown-topic' }, + }, + ); + + expect(slack.chat.postMessage).not.toHaveBeenCalled(); + }); + + it('should match origin+topic route over origin-only route', async () => { + const slack = new WebClient(); + const routesConfig = mockServices.rootConfig({ + data: { + app: { + baseUrl: 'https://example.org', + }, + notifications: { + processors: { + slack: [ + { + token: 'mock-token', + broadcastRoutes: [ + // Origin-only route defined first + { origin: 'plugin:catalog', channel: 'general-catalog' }, + // More specific origin+topic route defined second + { + origin: 'plugin:catalog', + topic: 'entity-deleted', + channel: 'catalog-deletions', + }, + ], + }, + ], + }, + }, + }, + }); + + const processor = SlackNotificationProcessor.fromConfig(routesConfig, { + auth, + logger, + catalog: catalogServiceMock({ + entities: DEFAULT_ENTITIES_RESPONSE.items, + }), + slack, + })[0]; + + await processor.postProcess( + { + origin: 'plugin:catalog', + id: '1234', + user: null, + created: new Date(), + payload: { + title: 'notification', + topic: 'entity-deleted', + }, + }, + { + recipients: { type: 'broadcast' }, + payload: { title: 'notification', topic: 'entity-deleted' }, + }, + ); + + // Should use the origin+topic match, not the origin-only match + expect(slack.chat.postMessage).toHaveBeenCalledTimes(1); + expect(slack.chat.postMessage).toHaveBeenCalledWith( + expect.objectContaining({ channel: 'catalog-deletions' }), + ); + }); + }); + describe('when slack.com/bot-notify annotation is missing', () => { it('should not send notification to a group without annotation', async () => { const slack = new WebClient(); @@ -953,4 +1427,81 @@ describe('SlackNotificationProcessor', () => { ); }); }); + + describe('when throttling is not configured', () => { + it('should use default concurrency limit of 10 per minute', async () => { + const slack = new WebClient(); + + const processor = SlackNotificationProcessor.fromConfig(config, { + auth, + logger, + catalog: catalogServiceMock({ + entities: DEFAULT_ENTITIES_RESPONSE.items, + }), + slack, + })[0]; + + await processor.processOptions({ + recipients: { type: 'entity', entityRef: 'group:default/mock' }, + payload: { title: 'notification' }, + }); + + expect(slack.chat.postMessage).toHaveBeenCalled(); + expect(throttleConfigs).toEqual([ + { + limit: 10, + interval: durationToMilliseconds({ minutes: 1 }), + }, + ]); + }); + }); + + describe('when throttling is configured', () => { + it('should use custom concurrency limit and interval values', async () => { + const slack = new WebClient(); + const throttlingConfig = mockServices.rootConfig({ + data: { + app: { + baseUrl: 'https://example.org', + }, + notifications: { + processors: { + slack: [ + { + token: 'mock-token', + concurrencyLimit: 5, + throttleInterval: 'PT30S', + }, + ], + }, + }, + }, + }); + + const processor = SlackNotificationProcessor.fromConfig( + throttlingConfig, + { + auth, + logger, + catalog: catalogServiceMock({ + entities: DEFAULT_ENTITIES_RESPONSE.items, + }), + slack, + }, + )[0]; + + await processor.processOptions({ + recipients: { type: 'entity', entityRef: 'group:default/mock' }, + payload: { title: 'notification' }, + }); + + expect(slack.chat.postMessage).toHaveBeenCalled(); + expect(throttleConfigs).toEqual([ + { + limit: 5, + interval: durationToMilliseconds({ seconds: 30 }), + }, + ]); + }); + }); }); diff --git a/plugins/notifications-backend-module-slack/src/lib/SlackNotificationProcessor.ts b/plugins/notifications-backend-module-slack/src/lib/SlackNotificationProcessor.ts index f9b00c9a58..e8f8d9eda4 100644 --- a/plugins/notifications-backend-module-slack/src/lib/SlackNotificationProcessor.ts +++ b/plugins/notifications-backend-module-slack/src/lib/SlackNotificationProcessor.ts @@ -21,7 +21,7 @@ import { parseEntityRef, UserEntity, } from '@backstage/catalog-model'; -import { Config } from '@backstage/config'; +import { Config, readDurationFromConfig } from '@backstage/config'; import { NotFoundError } from '@backstage/errors'; import { Notification } from '@backstage/plugin-notifications-common'; import { @@ -34,6 +34,7 @@ import { ChatPostMessageArguments, WebClient } from '@slack/web-api'; import DataLoader from 'dataloader'; import pThrottle from 'p-throttle'; import { ANNOTATION_SLACK_BOT_NOTIFY } from './constants'; +import { BroadcastRoute } from './types'; import { ExpiryMap, toChatPostMessageArgs } from './util'; import { CatalogService } from '@backstage/plugin-catalog-node'; @@ -48,8 +49,11 @@ export class SlackNotificationProcessor implements NotificationProcessor { private readonly messagesSent: Counter; private readonly messagesFailed: Counter; private readonly broadcastChannels?: string[]; + private readonly broadcastRoutes?: BroadcastRoute[]; private readonly entityLoader: DataLoader; private readonly username?: string; + private readonly concurrencyLimit: number; + private readonly throttleInterval: number; static fromConfig( config: Config, @@ -68,10 +72,23 @@ export class SlackNotificationProcessor implements NotificationProcessor { const slack = options.slack ?? new WebClient(token); const broadcastChannels = c.getOptionalStringArray('broadcastChannels'); const username = c.getOptionalString('username'); + const broadcastRoutesConfig = c.getOptionalConfigArray('broadcastRoutes'); + const broadcastRoutes = broadcastRoutesConfig?.map(route => + this.parseBroadcastRoute(route), + ); + const concurrencyLimit = c.getOptionalNumber('concurrencyLimit') ?? 10; + const throttleInterval = c.has('throttleInterval') + ? durationToMilliseconds( + readDurationFromConfig(c, { key: 'throttleInterval' }), + ) + : durationToMilliseconds({ minutes: 1 }); return new SlackNotificationProcessor({ slack, broadcastChannels, + broadcastRoutes, username, + concurrencyLimit, + throttleInterval, ...options, }); }); @@ -83,16 +100,32 @@ export class SlackNotificationProcessor implements NotificationProcessor { logger: LoggerService; catalog: CatalogService; broadcastChannels?: string[]; + broadcastRoutes?: BroadcastRoute[]; username?: string; + concurrencyLimit?: number; + throttleInterval?: number; }) { - const { auth, catalog, logger, slack, broadcastChannels, username } = - options; + const { + auth, + catalog, + logger, + slack, + broadcastChannels, + broadcastRoutes, + username, + concurrencyLimit, + throttleInterval, + } = options; this.logger = logger; this.catalog = catalog; this.auth = auth; this.slack = slack; this.broadcastChannels = broadcastChannels; + this.broadcastRoutes = broadcastRoutes; this.username = username; + this.concurrencyLimit = concurrencyLimit ?? 10; + this.throttleInterval = + throttleInterval ?? durationToMilliseconds({ minutes: 1 }); this.entityLoader = new DataLoader( async entityRefs => { @@ -134,8 +167,8 @@ export class SlackNotificationProcessor implements NotificationProcessor { ); const throttle = pThrottle({ - limit: 10, - interval: durationToMilliseconds({ minutes: 1 }), + limit: this.concurrencyLimit, + interval: this.throttleInterval, }); const throttled = throttle((opts: ChatPostMessageArguments) => this.sendNotification(opts), @@ -235,7 +268,8 @@ export class SlackNotificationProcessor implements NotificationProcessor { // Handle broadcast case if (notification.user === null) { - destinations.push(...(this.broadcastChannels ?? [])); + const routedChannels = this.getBroadcastDestinations(notification); + destinations.push(...routedChannels); } else if (options.recipients.type === 'entity') { // Handle user-specific notification const entityRefs = [options.recipients.entityRef].flat(); @@ -384,4 +418,88 @@ export class SlackNotificationProcessor implements NotificationProcessor { throw new Error(`Failed to send notification: ${response.error}`); } } + + private static parseBroadcastRoute(route: Config): BroadcastRoute { + const channelValue = route.getOptional('channel'); + let channels: string[]; + + if (typeof channelValue === 'string') { + channels = [channelValue]; + } else if (Array.isArray(channelValue)) { + channels = channelValue as string[]; + } else { + throw new Error( + 'broadcastRoutes entry must have a channel property (string or string[])', + ); + } + + return { + origin: route.getOptionalString('origin'), + topic: route.getOptionalString('topic'), + channels, + }; + } + + /** + * Gets the destination channels for a broadcast notification based on + * configured routes. Routes are matched by origin and/or topic. + * + * Matching precedence: + * 1. Routes with both origin AND topic matching (most specific) + * 2. Routes with only origin matching + * 3. Routes with only topic matching + * 4. Default broadcastChannels (least specific fallback) + * + * The first matching route wins within each precedence level. + */ + private getBroadcastDestinations(notification: Notification): string[] { + const { origin } = notification; + const { topic } = notification.payload; + + if (!this.broadcastRoutes || this.broadcastRoutes.length === 0) { + // Fall back to legacy broadcastChannels config + return this.broadcastChannels ?? []; + } + + // Find most specific match + // Priority 1: origin AND topic match + const originAndTopicMatch = this.broadcastRoutes.find( + route => + route.origin !== undefined && + route.topic !== undefined && + route.origin === origin && + route.topic === topic, + ); + + if (originAndTopicMatch) { + return originAndTopicMatch.channels; + } + + // Priority 2: origin-only match (no topic specified in route) + const originOnlyMatch = this.broadcastRoutes.find( + route => + route.origin !== undefined && + route.topic === undefined && + route.origin === origin, + ); + + if (originOnlyMatch) { + return originOnlyMatch.channels; + } + + // Priority 3: topic-only match (no origin specified in route) + const topicOnlyMatch = this.broadcastRoutes.find( + route => + route.topic !== undefined && + route.origin === undefined && + route.topic === topic, + ); + + if (topicOnlyMatch) { + return topicOnlyMatch.channels; + } + + // No match found, fall back to legacy broadcastChannels + return this.broadcastChannels ?? []; + } } diff --git a/plugins/notifications-backend-module-slack/src/lib/types.ts b/plugins/notifications-backend-module-slack/src/lib/types.ts index bd87e9656c..316df03462 100644 --- a/plugins/notifications-backend-module-slack/src/lib/types.ts +++ b/plugins/notifications-backend-module-slack/src/lib/types.ts @@ -18,3 +18,16 @@ export interface SlackNotificationOptions { url: string; payload: string; } + +/** + * Configuration for routing broadcast notifications to specific Slack channels + * based on origin and/or topic. + */ +export type BroadcastRoute = { + /** The origin to match (e.g., 'plugin:catalog', 'external:my-service') */ + origin?: string; + /** The topic to match (e.g., 'entity-updated', 'alerts') */ + topic?: string; + /** The Slack channel(s) to send to */ + channels: string[]; +}; diff --git a/plugins/notifications-backend/CHANGELOG.md b/plugins/notifications-backend/CHANGELOG.md index 7ae71e5b23..91da5468ca 100644 --- a/plugins/notifications-backend/CHANGELOG.md +++ b/plugins/notifications-backend/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-notifications-backend +## 0.6.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-signals-node@0.1.27 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + - @backstage/plugin-notifications-node@0.2.22 + +## 0.6.1-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-signals-node@0.1.27-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-node@1.20.1-next.1 + - @backstage/plugin-notifications-common@0.2.0 + - @backstage/plugin-notifications-node@0.2.22-next.1 + ## 0.6.1-next.0 ### Patch Changes diff --git a/plugins/notifications-backend/package.json b/plugins/notifications-backend/package.json index 5e50a6b787..7262b65d38 100644 --- a/plugins/notifications-backend/package.json +++ b/plugins/notifications-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-notifications-backend", - "version": "0.6.1-next.0", + "version": "0.6.1", "backstage": { "role": "backend-plugin", "pluginId": "notifications", diff --git a/plugins/notifications-node/CHANGELOG.md b/plugins/notifications-node/CHANGELOG.md index 97cd9b2585..98d1b3c84c 100644 --- a/plugins/notifications-node/CHANGELOG.md +++ b/plugins/notifications-node/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-notifications-node +## 0.2.22 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-signals-node@0.1.27 + - @backstage/backend-plugin-api@1.6.0 + +## 0.2.22-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-signals-node@0.1.27-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/plugin-notifications-common@0.2.0 + ## 0.2.22-next.0 ### Patch Changes diff --git a/plugins/notifications-node/package.json b/plugins/notifications-node/package.json index 25d7b2f9ca..8007852dd5 100644 --- a/plugins/notifications-node/package.json +++ b/plugins/notifications-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-notifications-node", - "version": "0.2.22-next.0", + "version": "0.2.22", "description": "Node.js library for the notifications plugin", "backstage": { "role": "node-library", diff --git a/plugins/notifications/CHANGELOG.md b/plugins/notifications/CHANGELOG.md index b40d8540bf..50bd9b35a3 100644 --- a/plugins/notifications/CHANGELOG.md +++ b/plugins/notifications/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-notifications +## 0.5.12 + +### Patch Changes + +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- 53347cc: Move long notification descriptions behind `Show more/less` button. + + This improves readability of the notifications list by preventing long descriptions from taking up too much space + or rendering very small scrollable areas. + +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/theme@0.7.1 + - @backstage/plugin-signals-react@0.0.18 + ## 0.5.12-next.0 ### Patch Changes diff --git a/plugins/notifications/package.json b/plugins/notifications/package.json index 5f2c652425..1a6b544da3 100644 --- a/plugins/notifications/package.json +++ b/plugins/notifications/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-notifications", - "version": "0.5.12-next.0", + "version": "0.5.12", "backstage": { "role": "frontend-plugin", "pluginId": "notifications", diff --git a/plugins/notifications/src/components/NotificationsFilters/NotificationsFilters.tsx b/plugins/notifications/src/components/NotificationsFilters/NotificationsFilters.tsx index 7e3f519b0c..e8fa422fa1 100644 --- a/plugins/notifications/src/components/NotificationsFilters/NotificationsFilters.tsx +++ b/plugins/notifications/src/components/NotificationsFilters/NotificationsFilters.tsx @@ -14,14 +14,11 @@ * limitations under the License. */ import { ChangeEvent } from 'react'; - -import Divider from '@material-ui/core/Divider'; import FormControl from '@material-ui/core/FormControl'; import Grid from '@material-ui/core/Grid'; import InputLabel from '@material-ui/core/InputLabel'; import MenuItem from '@material-ui/core/MenuItem'; import Select from '@material-ui/core/Select'; -import Typography from '@material-ui/core/Typography'; import { GetNotificationsOptions } from '../../api'; import { NotificationSeverity } from '@backstage/plugin-notifications-common'; @@ -200,11 +197,6 @@ export const NotificationsFilters = ({ return ( <> - - Filters - - - View diff --git a/plugins/notifications/src/components/NotificationsPage/NotificationsPage.tsx b/plugins/notifications/src/components/NotificationsPage/NotificationsPage.tsx index 739e9a1535..69242ac60e 100644 --- a/plugins/notifications/src/components/NotificationsPage/NotificationsPage.tsx +++ b/plugins/notifications/src/components/NotificationsPage/NotificationsPage.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { useState, useMemo, useEffect } from 'react'; +import { useEffect, useMemo, useState } from 'react'; import throttle from 'lodash/throttle'; import { Content, @@ -156,13 +156,17 @@ export const NotificationsPage = (props?: NotificationsPageProps) => { const isUnread = !!value?.[1]?.unread; const allTopics = value?.[2]?.topics; - let tableTitle = `All notifications (${totalCount})`; + let tableTitle = `All notifications `; if (saved) { - tableTitle = `Saved notifications (${totalCount})`; + tableTitle = `Saved notifications`; } else if (unreadOnly === true) { - tableTitle = `Unread notifications (${totalCount})`; + tableTitle = `Unread notifications`; } else if (unreadOnly === false) { - tableTitle = `Read notifications (${totalCount})`; + tableTitle = `Read notifications`; + } + + if (totalCount) { + tableTitle += ` (${totalCount})`; } return ( diff --git a/plugins/notifications/src/components/NotificationsTable/NotificationDescription.tsx b/plugins/notifications/src/components/NotificationsTable/NotificationDescription.tsx new file mode 100644 index 0000000000..762900c2b9 --- /dev/null +++ b/plugins/notifications/src/components/NotificationsTable/NotificationDescription.tsx @@ -0,0 +1,61 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import Typography from '@material-ui/core/Typography'; +import Button from '@material-ui/core/Button'; +import { useState } from 'react'; + +const MAX_LENGTH = 100; + +export const NotificationDescription = (props: { description: string }) => { + const { description } = props; + const [shown, setShown] = useState(false); + const isLong = description.length > MAX_LENGTH; + + if (!isLong) { + return {description}; + } + + if (shown) { + return ( + + {description}{' '} + + + ); + } + return ( + + {description.substring(0, MAX_LENGTH)}...{' '} + + + ); +}; diff --git a/plugins/notifications/src/components/NotificationsTable/NotificationsTable.tsx b/plugins/notifications/src/components/NotificationsTable/NotificationsTable.tsx index 8ec237e62f..952c18f9f9 100644 --- a/plugins/notifications/src/components/NotificationsTable/NotificationsTable.tsx +++ b/plugins/notifications/src/components/NotificationsTable/NotificationsTable.tsx @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { useState, useCallback, useMemo, useEffect } from 'react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; import throttle from 'lodash/throttle'; // @ts-ignore import RelativeTime from 'react-relative-time'; @@ -37,14 +37,11 @@ import { notificationsApiRef } from '../../api'; import { SelectAll } from './SelectAll'; import { BulkActions } from './BulkActions'; import { NotificationIcon } from './NotificationIcon'; +import { NotificationDescription } from './NotificationDescription'; const ThrottleDelayMs = 1000; const useStyles = makeStyles(theme => ({ - description: { - maxHeight: '5rem', - overflow: 'auto', - }, severityItem: { alignContent: 'center', }, @@ -53,8 +50,10 @@ const useStyles = makeStyles(theme => ({ verticalAlign: 'text-bottom', }, notificationInfoRow: { - marginLeft: theme.spacing(0.5), marginRight: theme.spacing(0.5), + '&:not(:first-child)': { + marginLeft: theme.spacing(0.5), + }, }, })); @@ -240,9 +239,9 @@ export const NotificationsTable = ({ )} {notification.payload.description ? ( - - {notification.payload.description} - + ) : null} @@ -318,7 +317,6 @@ export const NotificationsTable = ({ onMarkAllRead, onNotificationsSelectChange, classes.severityItem, - classes.description, classes.broadcastIcon, classes.notificationInfoRow, markAsReadOnLinkOpen, diff --git a/plugins/notifications/src/components/NotificationsTable/SelectAll.tsx b/plugins/notifications/src/components/NotificationsTable/SelectAll.tsx index 9bcc497132..f6d6ff48c9 100644 --- a/plugins/notifications/src/components/NotificationsTable/SelectAll.tsx +++ b/plugins/notifications/src/components/NotificationsTable/SelectAll.tsx @@ -16,6 +16,7 @@ import Checkbox from '@material-ui/core/Checkbox'; import FormControlLabel from '@material-ui/core/FormControlLabel'; import { makeStyles } from '@material-ui/core/styles'; +import Tooltip from '@material-ui/core/Tooltip'; const useStyles = makeStyles({ label: { @@ -23,6 +24,7 @@ const useStyles = makeStyles({ maxWidth: '2rem', '& span': { paddingRight: '0px', + marginRight: '2px', }, }, }); @@ -43,13 +45,15 @@ export const SelectAll = ({ label={count > 0 ? `(${count})` : undefined} className={classes.label} control={ - 0} - indeterminate={count > 0 && totalCount !== count} - onChange={onSelectAll} - /> + + 0} + indeterminate={count > 0 && totalCount !== count} + onChange={onSelectAll} + /> + } /> ); diff --git a/plugins/org-react/CHANGELOG.md b/plugins/org-react/CHANGELOG.md index 5cfb6f1a18..ffe7af52f1 100644 --- a/plugins/org-react/CHANGELOG.md +++ b/plugins/org-react/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-org-react +## 0.1.45 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.18.4 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/core-plugin-api@1.12.1 + ## 0.1.45-next.0 ### Patch Changes diff --git a/plugins/org-react/package.json b/plugins/org-react/package.json index a077894bc7..99403d689d 100644 --- a/plugins/org-react/package.json +++ b/plugins/org-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-org-react", - "version": "0.1.45-next.0", + "version": "0.1.45", "backstage": { "role": "web-library", "pluginId": "org", diff --git a/plugins/org/CHANGELOG.md b/plugins/org/CHANGELOG.md index 3bc994dcfe..90292a0f78 100644 --- a/plugins/org/CHANGELOG.md +++ b/plugins/org/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-org +## 0.6.47 + +### Patch Changes + +- f3f84f1: Minor extension type updates after frontend API bump +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/core-plugin-api@1.12.1 + +## 0.6.47-next.1 + +### Patch Changes + +- f3f84f1: Minor extension type updates after frontend API bump +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2-next.1 + - @backstage/plugin-catalog-react@1.21.4-next.2 + - @backstage/core-components@0.18.4-next.2 + - @backstage/catalog-model@1.7.6 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/plugin-catalog-common@1.1.7 + ## 0.6.47-next.0 ### Patch Changes diff --git a/plugins/org/package.json b/plugins/org/package.json index 09e801d7be..a48dad9f25 100644 --- a/plugins/org/package.json +++ b/plugins/org/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-org", - "version": "0.6.47-next.0", + "version": "0.6.47", "description": "A Backstage plugin that helps you create entity pages for your organization", "backstage": { "role": "frontend-plugin", diff --git a/plugins/permission-backend-module-policy-allow-all/CHANGELOG.md b/plugins/permission-backend-module-policy-allow-all/CHANGELOG.md index ec8e371159..a9709fd88b 100644 --- a/plugins/permission-backend-module-policy-allow-all/CHANGELOG.md +++ b/plugins/permission-backend-module-policy-allow-all/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-permission-backend-module-allow-all-policy +## 0.2.15 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/plugin-permission-node@0.10.7 + - @backstage/backend-plugin-api@1.6.0 + +## 0.2.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/plugin-permission-node@0.10.7-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/plugin-permission-common@0.9.3 + ## 0.2.15-next.0 ### Patch Changes diff --git a/plugins/permission-backend-module-policy-allow-all/package.json b/plugins/permission-backend-module-policy-allow-all/package.json index 1d4c5af43c..5cddb60c98 100644 --- a/plugins/permission-backend-module-policy-allow-all/package.json +++ b/plugins/permission-backend-module-policy-allow-all/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-permission-backend-module-allow-all-policy", - "version": "0.2.15-next.0", + "version": "0.2.15", "description": "Allow all policy backend module for the permission plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/permission-backend/CHANGELOG.md b/plugins/permission-backend/CHANGELOG.md index 4b63ed405c..196de3238b 100644 --- a/plugins/permission-backend/CHANGELOG.md +++ b/plugins/permission-backend/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-permission-backend +## 0.7.7 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/plugin-permission-node@0.10.7 + - @backstage/backend-plugin-api@1.6.0 + +## 0.7.7-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/plugin-permission-node@0.10.7-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-permission-common@0.9.3 + ## 0.7.7-next.0 ### Patch Changes diff --git a/plugins/permission-backend/package.json b/plugins/permission-backend/package.json index 5e599c2d3b..f3c840b693 100644 --- a/plugins/permission-backend/package.json +++ b/plugins/permission-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-permission-backend", - "version": "0.7.7-next.0", + "version": "0.7.7", "backstage": { "role": "backend-plugin", "pluginId": "permission", diff --git a/plugins/permission-backend/src/service/PermissionIntegrationClient.test.ts b/plugins/permission-backend/src/service/PermissionIntegrationClient.test.ts index ece99f08c7..822d10b858 100644 --- a/plugins/permission-backend/src/service/PermissionIntegrationClient.test.ts +++ b/plugins/permission-backend/src/service/PermissionIntegrationClient.test.ts @@ -148,9 +148,7 @@ describe('PermissionIntegrationClient', () => { ], ); - expect(response).toEqual( - expect.objectContaining([{ id: '123', result: AuthorizeResult.ALLOW }]), - ); + expect(response).toEqual([{ id: '123', result: AuthorizeResult.ALLOW }]); }); it('should not include authorization headers if no token is supplied', async () => { diff --git a/plugins/permission-node/CHANGELOG.md b/plugins/permission-node/CHANGELOG.md index 4594d38882..6c9fe8a91b 100644 --- a/plugins/permission-node/CHANGELOG.md +++ b/plugins/permission-node/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-permission-node +## 0.10.7 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-plugin-api@1.6.0 + +## 0.10.7-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-permission-common@0.9.3 + ## 0.10.7-next.0 ### Patch Changes diff --git a/plugins/permission-node/package.json b/plugins/permission-node/package.json index 3384aa7524..1ae3935b4c 100644 --- a/plugins/permission-node/package.json +++ b/plugins/permission-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-permission-node", - "version": "0.10.7-next.0", + "version": "0.10.7", "description": "Common permission and authorization utilities for backend plugins", "backstage": { "role": "node-library", diff --git a/plugins/permission-react/CHANGELOG.md b/plugins/permission-react/CHANGELOG.md index cf0248c840..9a377d5dc8 100644 --- a/plugins/permission-react/CHANGELOG.md +++ b/plugins/permission-react/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-permission-react +## 0.4.39 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.12.1 + ## 0.4.39-next.0 ### Patch Changes diff --git a/plugins/permission-react/package.json b/plugins/permission-react/package.json index 098959f342..17b4d65b51 100644 --- a/plugins/permission-react/package.json +++ b/plugins/permission-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-permission-react", - "version": "0.4.39-next.0", + "version": "0.4.39", "backstage": { "role": "web-library", "pluginId": "permission", diff --git a/plugins/proxy-backend/CHANGELOG.md b/plugins/proxy-backend/CHANGELOG.md index 8bb9e73f52..7541c8faf1 100644 --- a/plugins/proxy-backend/CHANGELOG.md +++ b/plugins/proxy-backend/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-proxy-backend +## 0.6.9 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-proxy-node@0.1.11 + +## 0.6.9-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/types@1.2.2 + - @backstage/plugin-proxy-node@0.1.11-next.1 + ## 0.6.9-next.0 ### Patch Changes diff --git a/plugins/proxy-backend/package.json b/plugins/proxy-backend/package.json index 331ea354c2..c75e9a42e7 100644 --- a/plugins/proxy-backend/package.json +++ b/plugins/proxy-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-proxy-backend", - "version": "0.6.9-next.0", + "version": "0.6.9", "description": "A Backstage backend plugin that helps you set up proxy endpoints in the backend", "backstage": { "role": "backend-plugin", diff --git a/plugins/proxy-node/CHANGELOG.md b/plugins/proxy-node/CHANGELOG.md index 12abd91157..e2bf6a15cf 100644 --- a/plugins/proxy-node/CHANGELOG.md +++ b/plugins/proxy-node/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-proxy-node +## 0.1.11 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + +## 0.1.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + ## 0.1.11-next.0 ### Patch Changes diff --git a/plugins/proxy-node/package.json b/plugins/proxy-node/package.json index 4ac4d1fe96..9134a6c2b5 100644 --- a/plugins/proxy-node/package.json +++ b/plugins/proxy-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-proxy-node", - "version": "0.1.11-next.0", + "version": "0.1.11", "description": "The plugin-proxy-node module for @backstage/plugin-proxy-backend", "backstage": { "role": "node-library", diff --git a/plugins/scaffolder-backend-module-azure/CHANGELOG.md b/plugins/scaffolder-backend-module-azure/CHANGELOG.md index f1984afffd..6061d57a41 100644 --- a/plugins/scaffolder-backend-module-azure/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-azure/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-scaffolder-backend-module-azure +## 0.2.16 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-node@0.12.2 + +## 0.2.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + ## 0.2.16-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-azure/package.json b/plugins/scaffolder-backend-module-azure/package.json index ff47d56ed1..d76d5c41d8 100644 --- a/plugins/scaffolder-backend-module-azure/package.json +++ b/plugins/scaffolder-backend-module-azure/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-azure", - "version": "0.2.16-next.0", + "version": "0.2.16", "description": "The azure module for @backstage/plugin-scaffolder-backend", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/scaffolder-backend-module-bitbucket-cloud/CHANGELOG.md b/plugins/scaffolder-backend-module-bitbucket-cloud/CHANGELOG.md index 3238b13b21..d18fbaf5d4 100644 --- a/plugins/scaffolder-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,50 @@ # @backstage/plugin-scaffolder-backend-module-bitbucket-cloud +## 0.3.0 + +### Minor Changes + +- 37fba1d: Added support for Bitbucket Cloud OAuth. This introduces an alternative authentication method using a workspace OAuth consumer, alongside App Passwords (deprecated) and API tokens. OAuth does not require a bot or service account and avoids token expiry issues. + + **BREAKING CHANGES** + + - **@backstage/integration** (`src/bitbucketCloud/core.ts`) + + - `getBitbucketCloudRequestOptions` now returns a `Promise` and **must** be awaited. + + - **@backstage/plugin-scaffolder-backend-module-bitbucket-cloud** (`src/actions/helpers.ts`) + - `getBitbucketClient` now returns a `Promise` and **must** be awaited. + - `getAuthorizationHeader` now returns a `Promise` and **must** be awaited. + + **OAuth usage example** + + ```yaml + integrations: + bitbucketCloud: + - clientId: client-id + clientSecret: client-secret + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/plugin-bitbucket-cloud-common@0.3.5 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-node@0.12.2 + +## 0.2.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-bitbucket-cloud-common@0.3.5-next.0 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + ## 0.2.16-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-bitbucket-cloud/package.json b/plugins/scaffolder-backend-module-bitbucket-cloud/package.json index 7c44716291..512e5a7c55 100644 --- a/plugins/scaffolder-backend-module-bitbucket-cloud/package.json +++ b/plugins/scaffolder-backend-module-bitbucket-cloud/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-bitbucket-cloud", - "version": "0.2.16-next.0", + "version": "0.3.0", "description": "The Bitbucket Cloud module for @backstage/plugin-scaffolder-backend", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloud.ts b/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloud.ts index 722bf01303..a278410639 100644 --- a/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloud.ts +++ b/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloud.ts @@ -25,6 +25,7 @@ import { import { Config } from '@backstage/config'; import { getAuthorizationHeader } from './helpers'; +import { getBitbucketCloudOAuthToken } from '@backstage/integration'; import { examples } from './bitbucketCloud.examples'; const createRepository = async (opts: { @@ -216,7 +217,7 @@ export function createPublishBitbucketCloudAction(options: { ); } - const authorization = getAuthorizationHeader( + const authorization = await getAuthorizationHeader( ctx.input.token ? { token: ctx.input.token } : integrationConfig.config, ); @@ -249,6 +250,18 @@ export function createPublishBitbucketCloudAction(options: { username: 'x-token-auth', password: ctx.input.token, }; + } else if ( + integrationConfig.config.clientId && + integrationConfig.config.clientSecret + ) { + const token = await getBitbucketCloudOAuthToken( + integrationConfig.config.clientId, + integrationConfig.config.clientSecret, + ); + auth = { + username: 'x-token-auth', + password: token, + }; } else { if ( !integrationConfig.config.username || diff --git a/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloudBranchRestriction.test.ts b/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloudBranchRestriction.test.ts index 55ee430091..2ac54894d5 100644 --- a/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloudBranchRestriction.test.ts +++ b/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloudBranchRestriction.test.ts @@ -22,11 +22,11 @@ jest.mock('bitbucket', () => ({ })); describe('bitbucketCloud:branchRestriction:create', () => { - it('getBitbucketClient should return the correct headers with username and password', () => { + it('getBitbucketClient should return the correct headers with username and password', async () => { expect.assertions(1); const username = 'username'; const password = 'password'; - getBitbucketClient({ username: username, appPassword: password }); + await getBitbucketClient({ username: username, appPassword: password }); expect(Bitbucket).toHaveBeenCalledWith({ auth: { username: username, @@ -35,12 +35,14 @@ describe('bitbucketCloud:branchRestriction:create', () => { }); }); - it('getBitbucketClient should throw if only one of username or password is provided', () => { + it('getBitbucketClient should throw if only one of username or password is provided', async () => { expect.assertions(2); const username = 'username'; const password = 'password'; - expect(() => getBitbucketClient({ username })).toThrow(Error); - expect(() => getBitbucketClient({ appPassword: password })).toThrow(Error); + await expect(getBitbucketClient({ username })).rejects.toThrow(Error); + await expect(getBitbucketClient({ appPassword: password })).rejects.toThrow( + Error, + ); }); }); diff --git a/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloudBranchRestriction.ts b/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloudBranchRestriction.ts index 233818e00a..a12f63f980 100644 --- a/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloudBranchRestriction.ts +++ b/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloudBranchRestriction.ts @@ -37,6 +37,8 @@ const createBitbucketCloudBranchRestriction = async (opts: { token?: string; username?: string; appPassword?: string; + clientId?: string; + clientSecret?: string; }; }) => { const { @@ -52,7 +54,7 @@ const createBitbucketCloudBranchRestriction = async (opts: { authorization, } = opts; - const bitbucket = getBitbucketClient(authorization); + const bitbucket = await getBitbucketClient(authorization); return await bitbucket.branchrestrictions.create({ _body: { groups: groups, diff --git a/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloudPipelinesRun.ts b/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloudPipelinesRun.ts index 4bf9226db7..372f45c928 100644 --- a/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloudPipelinesRun.ts +++ b/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloudPipelinesRun.ts @@ -68,7 +68,7 @@ export const createBitbucketPipelinesRunAction = (options: { const host = 'bitbucket.org'; const integrationConfig = integrations.bitbucketCloud.byHost(host); - const authorization = getAuthorizationHeader( + const authorization = await getAuthorizationHeader( token ? { token } : integrationConfig!.config, ); let response: Response; diff --git a/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloudPullRequest.ts b/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloudPullRequest.ts index 9969f13eb2..40dd09d386 100644 --- a/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloudPullRequest.ts +++ b/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloudPullRequest.ts @@ -28,6 +28,7 @@ import { import { Config } from '@backstage/config'; import fs from 'fs-extra'; import { getAuthorizationHeader } from './helpers'; +import { getBitbucketCloudOAuthToken } from '@backstage/integration'; import { examples } from './bitbucketCloudPullRequest.examples'; const createPullRequest = async (opts: { @@ -317,7 +318,7 @@ export function createPublishBitbucketCloudPullRequestAction(options: { ); } - const authorization = getAuthorizationHeader( + const authorization = await getAuthorizationHeader( ctx.input.token ? { token: ctx.input.token } : integrationConfig.config, ); @@ -365,6 +366,18 @@ export function createPublishBitbucketCloudPullRequestAction(options: { username: 'x-token-auth', password: ctx.input.token, }; + } else if ( + integrationConfig.config.clientId && + integrationConfig.config.clientSecret + ) { + const token = await getBitbucketCloudOAuthToken( + integrationConfig.config.clientId, + integrationConfig.config.clientSecret, + ); + auth = { + username: 'x-token-auth', + password: token, + }; } else { if ( !integrationConfig.config.username || diff --git a/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/helpers.ts b/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/helpers.ts index 2e68d4e8b8..47a212fcab 100644 --- a/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/helpers.ts +++ b/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/helpers.ts @@ -15,12 +15,28 @@ */ import { Bitbucket } from 'bitbucket'; +import { getBitbucketCloudOAuthToken } from '@backstage/integration'; -export const getBitbucketClient = (config: { +export const getBitbucketClient = async (config: { token?: string; username?: string; appPassword?: string; + clientId?: string; + clientSecret?: string; }) => { + // If OAuth credentials provided, fetch token + if (config.clientId && config.clientSecret) { + const token = await getBitbucketCloudOAuthToken( + config.clientId, + config.clientSecret, + ); + return new Bitbucket({ + auth: { + token, + }, + }); + } + if (config.token) { return new Bitbucket({ auth: { @@ -38,15 +54,26 @@ export const getBitbucketClient = (config: { }); } throw new Error( - `Authorization has not been provided for Bitbucket Cloud. Please add either provide a username and token or username and appPassword to the Integrations config`, + `Authorization has not been provided for Bitbucket Cloud. Please provide either OAuth credentials (clientId/clientSecret), username and token, or username and appPassword in the Integrations config`, ); }; -export const getAuthorizationHeader = (config: { +export const getAuthorizationHeader = async (config: { username?: string; appPassword?: string; token?: string; -}) => { + clientId?: string; + clientSecret?: string; +}): Promise => { + // OAuth authentication + if (config.clientId && config.clientSecret) { + const token = await getBitbucketCloudOAuthToken( + config.clientId, + config.clientSecret, + ); + return `Bearer ${token}`; + } + // TODO: appPassword can be removed once fully // deprecated by BitBucket on 9th June 2026. if (config.username && (config.token ?? config.appPassword)) { @@ -62,6 +89,6 @@ export const getAuthorizationHeader = (config: { } throw new Error( - `Authorization has not been provided for Bitbucket Cloud. Please add either provide a username and token or username and appPassword to the Integrations config`, + `Authorization has not been provided for Bitbucket Cloud. Please provide either OAuth credentials (clientId/clientSecret), username and token, or username and appPassword in the Integrations config`, ); }; diff --git a/plugins/scaffolder-backend-module-bitbucket-server/CHANGELOG.md b/plugins/scaffolder-backend-module-bitbucket-server/CHANGELOG.md index d533bb63f4..1591b4f1df 100644 --- a/plugins/scaffolder-backend-module-bitbucket-server/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-bitbucket-server/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-scaffolder-backend-module-bitbucket-server +## 0.2.16 + +### Patch Changes + +- 5a6aca2: Improve error message when provided target branch is missing +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-node@0.12.2 + +## 0.2.16-next.1 + +### Patch Changes + +- 5a6aca2: Improve error message when provided target branch is missing +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + ## 0.2.16-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-bitbucket-server/package.json b/plugins/scaffolder-backend-module-bitbucket-server/package.json index 3590b4112a..98544c3baa 100644 --- a/plugins/scaffolder-backend-module-bitbucket-server/package.json +++ b/plugins/scaffolder-backend-module-bitbucket-server/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-bitbucket-server", - "version": "0.2.16-next.0", + "version": "0.2.16", "description": "The Bitbucket Server module for @backstage/plugin-scaffolder-backend", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/scaffolder-backend-module-bitbucket/CHANGELOG.md b/plugins/scaffolder-backend-module-bitbucket/CHANGELOG.md index 56c67b9a14..404670d688 100644 --- a/plugins/scaffolder-backend-module-bitbucket/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-bitbucket/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-scaffolder-backend-module-bitbucket +## 0.3.17 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.3.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.16 + - @backstage/plugin-scaffolder-node@0.12.2 + +## 0.3.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.16-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.16-next.1 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + ## 0.3.17-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-bitbucket/package.json b/plugins/scaffolder-backend-module-bitbucket/package.json index 4516920aa7..cbbab54143 100644 --- a/plugins/scaffolder-backend-module-bitbucket/package.json +++ b/plugins/scaffolder-backend-module-bitbucket/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-bitbucket", - "version": "0.3.17-next.0", + "version": "0.3.17", "description": "The bitbucket module for @backstage/plugin-scaffolder-backend", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md b/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md index db8919e652..1644c76641 100644 --- a/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-scaffolder-backend-module-confluence-to-markdown +## 0.3.16 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-node@0.12.2 + +## 0.3.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + ## 0.3.16-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-confluence-to-markdown/package.json b/plugins/scaffolder-backend-module-confluence-to-markdown/package.json index ada64e8f9c..177f7ea512 100644 --- a/plugins/scaffolder-backend-module-confluence-to-markdown/package.json +++ b/plugins/scaffolder-backend-module-confluence-to-markdown/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-confluence-to-markdown", - "version": "0.3.16-next.0", + "version": "0.3.16", "description": "The confluence-to-markdown module for @backstage/plugin-scaffolder-backend", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md index 4f600fc7b0..89042a3074 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-scaffolder-backend-module-cookiecutter +## 0.3.19-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.14.1-next.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/integration@1.19.0 + - @backstage/types@1.2.2 + - @backstage/plugin-scaffolder-node@0.12.2 + +## 0.3.18 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-defaults@0.14.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-node@0.12.2 + +## 0.3.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.14.0-next.1 + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + ## 0.3.18-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-cookiecutter/package.json b/plugins/scaffolder-backend-module-cookiecutter/package.json index 64fb9236af..82e2713623 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/package.json +++ b/plugins/scaffolder-backend-module-cookiecutter/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-cookiecutter", - "version": "0.3.18-next.0", + "version": "0.3.19-next.0", "description": "A module for the scaffolder backend that lets you template projects using cookiecutter", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/scaffolder-backend-module-gcp/CHANGELOG.md b/plugins/scaffolder-backend-module-gcp/CHANGELOG.md index ab185367bc..5294344dc7 100644 --- a/plugins/scaffolder-backend-module-gcp/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-gcp/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-scaffolder-backend-module-gcp +## 0.2.16 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-node@0.12.2 + +## 0.2.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + ## 0.2.16-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-gcp/package.json b/plugins/scaffolder-backend-module-gcp/package.json index c9a954831e..bb50ebd277 100644 --- a/plugins/scaffolder-backend-module-gcp/package.json +++ b/plugins/scaffolder-backend-module-gcp/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-gcp", - "version": "0.2.16-next.0", + "version": "0.2.16", "description": "The GCP Bucket module for @backstage/plugin-scaffolder-backend", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/scaffolder-backend-module-gerrit/CHANGELOG.md b/plugins/scaffolder-backend-module-gerrit/CHANGELOG.md index 26696b6452..cc45967b3b 100644 --- a/plugins/scaffolder-backend-module-gerrit/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-scaffolder-backend-module-gerrit +## 0.2.16 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-node@0.12.2 + +## 0.2.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + ## 0.2.16-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-gerrit/package.json b/plugins/scaffolder-backend-module-gerrit/package.json index 07592568ca..62d4ebb286 100644 --- a/plugins/scaffolder-backend-module-gerrit/package.json +++ b/plugins/scaffolder-backend-module-gerrit/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-gerrit", - "version": "0.2.16-next.0", + "version": "0.2.16", "description": "The gerrit module for @backstage/plugin-scaffolder-backend", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/scaffolder-backend-module-gitea/CHANGELOG.md b/plugins/scaffolder-backend-module-gitea/CHANGELOG.md index d3a913d054..46852ad119 100644 --- a/plugins/scaffolder-backend-module-gitea/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-gitea/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-scaffolder-backend-module-gitea +## 0.2.16 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-node@0.12.2 + +## 0.2.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + ## 0.2.16-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-gitea/package.json b/plugins/scaffolder-backend-module-gitea/package.json index 99e2c05f86..21e7d4c98a 100644 --- a/plugins/scaffolder-backend-module-gitea/package.json +++ b/plugins/scaffolder-backend-module-gitea/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-gitea", - "version": "0.2.16-next.0", + "version": "0.2.16", "description": "The gitea module for @backstage/plugin-scaffolder-backend", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/scaffolder-backend-module-github/CHANGELOG.md b/plugins/scaffolder-backend-module-github/CHANGELOG.md index 46ec5e751d..0a636abb22 100644 --- a/plugins/scaffolder-backend-module-github/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-github/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-scaffolder-backend-module-github +## 0.9.3 + +### Patch Changes + +- dab3d3f: Added autocompletion resource `owners` for retrieving GitHub repository owners. +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + - @backstage/plugin-scaffolder-node@0.12.2 + +## 0.9.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-node@1.20.1-next.1 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + ## 0.9.3-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-github/package.json b/plugins/scaffolder-backend-module-github/package.json index f22f9a3741..4f58dc4eee 100644 --- a/plugins/scaffolder-backend-module-github/package.json +++ b/plugins/scaffolder-backend-module-github/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-github", - "version": "0.9.3-next.0", + "version": "0.9.3", "description": "The github module for @backstage/plugin-scaffolder-backend", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/scaffolder-backend-module-github/src/autocomplete/autocomplete.test.ts b/plugins/scaffolder-backend-module-github/src/autocomplete/autocomplete.test.ts index 9b9aaff9c2..8076a4de01 100644 --- a/plugins/scaffolder-backend-module-github/src/autocomplete/autocomplete.test.ts +++ b/plugins/scaffolder-backend-module-github/src/autocomplete/autocomplete.test.ts @@ -31,6 +31,9 @@ const mockOctokit = { listForAuthenticatedUser: jest.fn(), listBranches: jest.fn(), }, + orgs: { + listForAuthenticatedUser: jest.fn(), + }, }, }; jest.mock('octokit', () => ({ @@ -95,6 +98,30 @@ describe('handleAutocompleteRequest', () => { }); }); + it('should return owners', async () => { + const handleAutocompleteRequest = createHandleAutocompleteRequest({ + integrations: mockIntegrations, + }); + + mockOctokit.rest.orgs.listForAuthenticatedUser.mockResolvedValue({ + data: [ + { + login: 'backstage', + }, + ], + }); + + const result = await handleAutocompleteRequest({ + resource: 'owners', + token: 'token', + context: {}, + }); + + expect(result).toEqual({ + results: [{ id: 'backstage' }], + }); + }); + it('should throw an error for invalid resource', async () => { const handleAutocompleteRequest = createHandleAutocompleteRequest({ integrations: mockIntegrations, diff --git a/plugins/scaffolder-backend-module-github/src/autocomplete/autocomplete.ts b/plugins/scaffolder-backend-module-github/src/autocomplete/autocomplete.ts index 35d6b4f930..b3efde9333 100644 --- a/plugins/scaffolder-backend-module-github/src/autocomplete/autocomplete.ts +++ b/plugins/scaffolder-backend-module-github/src/autocomplete/autocomplete.ts @@ -64,6 +64,15 @@ export function createHandleAutocompleteRequest(options: { return { results }; } + case 'owners': { + const orgs = await client.paginate( + client.rest.orgs.listForAuthenticatedUser, + ); + + const results = orgs.map(r => ({ id: r.login })); + + return { results }; + } default: throw new InputError(`Invalid resource: ${resource}`); } diff --git a/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md b/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md index a22e1d71bf..41a8c18bd9 100644 --- a/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-scaffolder-backend-module-gitlab +## 0.11.0 + +### Minor Changes + +- f2d034b: In the `gitlabRepoPush` action, add 'auto' possibility for `commitAction` input. + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-node@0.12.2 + +## 0.11.0-next.1 + +### Minor Changes + +- f2d034b: In the `gitlabRepoPush` action, add 'auto' possibility for `commitAction` input. + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + ## 0.10.1-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-gitlab/package.json b/plugins/scaffolder-backend-module-gitlab/package.json index 21786474e2..a447da9417 100644 --- a/plugins/scaffolder-backend-module-gitlab/package.json +++ b/plugins/scaffolder-backend-module-gitlab/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-gitlab", - "version": "0.10.1-next.0", + "version": "0.11.0", "backstage": { "role": "backend-plugin-module", "pluginId": "scaffolder", diff --git a/plugins/scaffolder-backend-module-notifications/CHANGELOG.md b/plugins/scaffolder-backend-module-notifications/CHANGELOG.md index 584f2bcc7d..c7100f71f9 100644 --- a/plugins/scaffolder-backend-module-notifications/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-notifications/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-scaffolder-backend-module-notifications +## 0.1.17 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-notifications-node@0.2.22 + - @backstage/plugin-scaffolder-node@0.12.2 + +## 0.1.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/plugin-notifications-common@0.2.0 + - @backstage/plugin-notifications-node@0.2.22-next.1 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + ## 0.1.17-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-notifications/package.json b/plugins/scaffolder-backend-module-notifications/package.json index 64bd96badb..89b76a7808 100644 --- a/plugins/scaffolder-backend-module-notifications/package.json +++ b/plugins/scaffolder-backend-module-notifications/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-notifications", - "version": "0.1.17-next.0", + "version": "0.1.17", "description": "The notifications backend module for the scaffolder plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/scaffolder-backend-module-rails/CHANGELOG.md b/plugins/scaffolder-backend-module-rails/CHANGELOG.md index e6e17558b3..48db86578e 100644 --- a/plugins/scaffolder-backend-module-rails/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-rails/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-scaffolder-backend-module-rails +## 0.5.16 + +### Patch Changes + +- 2bae83a: Bumped dev dependencies `@types/node` +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-node@0.12.2 + +## 0.5.16-next.1 + +### Patch Changes + +- 2bae83a: Bumped dev dependencies `@types/node` +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + ## 0.5.16-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-rails/package.json b/plugins/scaffolder-backend-module-rails/package.json index 2ae26dd016..0a778daeff 100644 --- a/plugins/scaffolder-backend-module-rails/package.json +++ b/plugins/scaffolder-backend-module-rails/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-rails", - "version": "0.5.16-next.0", + "version": "0.5.16", "description": "A module for the scaffolder backend that lets you template projects using Rails", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/scaffolder-backend-module-sentry/CHANGELOG.md b/plugins/scaffolder-backend-module-sentry/CHANGELOG.md index 8fbec8e18b..427c5bcfd0 100644 --- a/plugins/scaffolder-backend-module-sentry/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-sentry/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-scaffolder-backend-module-sentry +## 0.2.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-node@0.12.2 + +## 0.2.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + ## 0.2.16-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-sentry/package.json b/plugins/scaffolder-backend-module-sentry/package.json index a012921907..d8f8c2dd31 100644 --- a/plugins/scaffolder-backend-module-sentry/package.json +++ b/plugins/scaffolder-backend-module-sentry/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-sentry", - "version": "0.2.16-next.0", + "version": "0.2.16", "backstage": { "role": "backend-plugin-module", "pluginId": "scaffolder", diff --git a/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md b/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md index 2c436729f9..dba988783c 100644 --- a/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md @@ -1,5 +1,34 @@ # @backstage/plugin-scaffolder-backend-module-yeoman +## 0.4.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/types@1.2.2 + - @backstage/plugin-scaffolder-node@0.12.2 + - @backstage/plugin-scaffolder-node-test-utils@0.3.7-next.0 + +## 0.4.17 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-node@0.12.2 + - @backstage/plugin-scaffolder-node-test-utils@0.3.6 + +## 0.4.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/types@1.2.2 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + - @backstage/plugin-scaffolder-node-test-utils@0.3.6-next.1 + ## 0.4.17-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-yeoman/package.json b/plugins/scaffolder-backend-module-yeoman/package.json index 66e1342a8e..afacdad9a4 100644 --- a/plugins/scaffolder-backend-module-yeoman/package.json +++ b/plugins/scaffolder-backend-module-yeoman/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-yeoman", - "version": "0.4.17-next.0", + "version": "0.4.18-next.0", "backstage": { "role": "backend-plugin-module", "pluginId": "scaffolder", diff --git a/plugins/scaffolder-backend/CHANGELOG.md b/plugins/scaffolder-backend/CHANGELOG.md index e9b0bdc5e7..17776a4b49 100644 --- a/plugins/scaffolder-backend/CHANGELOG.md +++ b/plugins/scaffolder-backend/CHANGELOG.md @@ -1,5 +1,107 @@ # @backstage/plugin-scaffolder-backend +## 3.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-openapi-utils@0.6.5-next.0 + - @backstage/backend-defaults@0.14.1-next.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/integration@1.19.0 + - @backstage/types@1.2.2 + - @backstage/plugin-auth-node@0.6.10 + - @backstage/plugin-bitbucket-cloud-common@0.3.5 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.15 + - @backstage/plugin-catalog-node@1.20.1 + - @backstage/plugin-events-node@0.4.18 + - @backstage/plugin-permission-common@0.9.3 + - @backstage/plugin-permission-node@0.10.7 + - @backstage/plugin-scaffolder-backend-module-azure@0.2.16 + - @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.17 + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.3.0 + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.16 + - @backstage/plugin-scaffolder-backend-module-gerrit@0.2.16 + - @backstage/plugin-scaffolder-backend-module-gitea@0.2.16 + - @backstage/plugin-scaffolder-backend-module-github@0.9.3 + - @backstage/plugin-scaffolder-backend-module-gitlab@0.11.0 + - @backstage/plugin-scaffolder-common@1.7.4 + - @backstage/plugin-scaffolder-node@0.12.2 + +## 3.1.0 + +### Minor Changes + +- a4cd405: Add `defaultEnvironment` config to scaffolder to enable more flexible and custom templates. Now it's possible enable access to default parameters and secrets in templates, improving security and reducing complexity. + +### Patch Changes + +- be5972b: Fixed a bug where config was not passed to NunjucksWorkflowRunner, causing defaultEnvironment to be undefined +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- 2bae83a: Updated `isolated-vm` to `6.0.1` +- 25b560e: Internal change to support new versions of the `logform` library +- 8f4aded: Fixing OpenAPI definition +- 1226647: Updated dependency `esbuild` to `^0.27.0`. +- Updated dependencies + - @backstage/plugin-scaffolder-backend-module-gitlab@0.11.0 + - @backstage/integration@1.19.0 + - @backstage/plugin-auth-node@0.6.10 + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.3.0 + - @backstage/plugin-bitbucket-cloud-common@0.3.5 + - @backstage/backend-defaults@0.14.0 + - @backstage/backend-openapi-utils@0.6.4 + - @backstage/plugin-events-node@0.4.18 + - @backstage/plugin-permission-node@0.10.7 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-backend-module-github@0.9.3 + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.16 + - @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.17 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.15 + - @backstage/plugin-catalog-node@1.20.1 + - @backstage/plugin-scaffolder-backend-module-azure@0.2.16 + - @backstage/plugin-scaffolder-backend-module-gerrit@0.2.16 + - @backstage/plugin-scaffolder-backend-module-gitea@0.2.16 + - @backstage/plugin-scaffolder-common@1.7.4 + - @backstage/plugin-scaffolder-node@0.12.2 + +## 3.1.0-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- 2bae83a: Updated `isolated-vm` to `6.0.1` +- 25b560e: Internal change to support new versions of the `logform` library +- 1226647: Updated dependency `esbuild` to `^0.27.0`. +- Updated dependencies + - @backstage/plugin-scaffolder-backend-module-gitlab@0.11.0-next.1 + - @backstage/backend-defaults@0.14.0-next.1 + - @backstage/backend-openapi-utils@0.6.4-next.1 + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/plugin-permission-node@0.10.7-next.1 + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.16-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-bitbucket-cloud-common@0.3.5-next.0 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.15-next.1 + - @backstage/plugin-catalog-node@1.20.1-next.1 + - @backstage/plugin-permission-common@0.9.3 + - @backstage/plugin-scaffolder-backend-module-azure@0.2.16-next.1 + - @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.17-next.1 + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.16-next.1 + - @backstage/plugin-scaffolder-backend-module-gerrit@0.2.16-next.1 + - @backstage/plugin-scaffolder-backend-module-gitea@0.2.16-next.1 + - @backstage/plugin-scaffolder-backend-module-github@0.9.3-next.1 + - @backstage/plugin-scaffolder-common@1.7.4-next.0 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + ## 3.1.0-next.0 ### Minor Changes diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index c3876a7926..7d26366e6d 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend", - "version": "3.1.0-next.0", + "version": "3.1.1-next.0", "description": "The Backstage backend plugin that helps you create new things", "backstage": { "role": "backend-plugin", diff --git a/plugins/scaffolder-backend/sample-templates/bitbucket-demo/template.yaml b/plugins/scaffolder-backend/sample-templates/bitbucket-demo/template.yaml index 0a7c841d8f..c8f85974ea 100644 --- a/plugins/scaffolder-backend/sample-templates/bitbucket-demo/template.yaml +++ b/plugins/scaffolder-backend/sample-templates/bitbucket-demo/template.yaml @@ -69,7 +69,7 @@ spec: url: https://github.com/backstage/community/tree/main/backstage-community-sessions - id: publish name: Publish - action: publish:bitbucket + action: publish:bitbucketCloud input: description: This is ${{ parameters.name }} repoUrl: ${{ parameters.repoUrl }} @@ -81,10 +81,28 @@ spec: repoContentsUrl: ${{ steps['publish'].output.repoContentsUrl }} catalogInfoPath: '/catalog-info.yaml' + - id: create-pr-file + name: Create PR File + action: fetch:plain + input: + targetPath: ./pr-demo + url: https://github.com/backstage/community/blob/main/README.md + - id: create-pr + name: Create Pull Request + action: publish:bitbucketCloud:pull-request + input: + repoUrl: ${{ parameters.repoUrl }} + title: Test PR for ${{ parameters.name }} + description: This is a test pull request created by the scaffolder template to test OAuth support + sourceBranch: scaffolder-pr-${{ parameters.name }} + targetBranch: master + output: links: - title: Repository url: ${{ steps['publish'].output.remoteUrl }} + - title: Pull Request + url: ${{ steps['create-pr'].output.pullRequestUrl }} - title: Open in catalog icon: catalog entityRef: ${{ steps['register'].output.entityRef }} diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts index 3a15b345db..ef704bc9e0 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts @@ -134,6 +134,7 @@ export class TaskWorker { additionalTemplateFilters, additionalTemplateGlobals, permissions, + config, }); return new TaskWorker({ diff --git a/plugins/scaffolder-common/CHANGELOG.md b/plugins/scaffolder-common/CHANGELOG.md index 1bc44a09c5..5ca131e060 100644 --- a/plugins/scaffolder-common/CHANGELOG.md +++ b/plugins/scaffolder-common/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-scaffolder-common +## 1.7.4 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + ## 1.7.4-next.0 ### Patch Changes diff --git a/plugins/scaffolder-common/package.json b/plugins/scaffolder-common/package.json index 1949f12e18..24898228dc 100644 --- a/plugins/scaffolder-common/package.json +++ b/plugins/scaffolder-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-common", - "version": "1.7.4-next.0", + "version": "1.7.4", "description": "Common functionalities for the scaffolder, to be shared between scaffolder and scaffolder-backend plugin", "backstage": { "role": "common-library", diff --git a/plugins/scaffolder-node-test-utils/CHANGELOG.md b/plugins/scaffolder-node-test-utils/CHANGELOG.md index 91fff5040d..7980a7146e 100644 --- a/plugins/scaffolder-node-test-utils/CHANGELOG.md +++ b/plugins/scaffolder-node-test-utils/CHANGELOG.md @@ -1,5 +1,34 @@ # @backstage/plugin-scaffolder-node-test-utils +## 0.3.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.6.0 + - @backstage/backend-test-utils@1.10.3-next.0 + - @backstage/types@1.2.2 + - @backstage/plugin-scaffolder-node@0.12.2 + +## 0.3.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-test-utils@1.10.2 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-node@0.12.2 + +## 0.3.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-test-utils@1.10.2-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/types@1.2.2 + - @backstage/plugin-scaffolder-node@0.12.2-next.1 + ## 0.3.6-next.0 ### Patch Changes diff --git a/plugins/scaffolder-node-test-utils/package.json b/plugins/scaffolder-node-test-utils/package.json index 3c79f30575..f7b3a4179e 100644 --- a/plugins/scaffolder-node-test-utils/package.json +++ b/plugins/scaffolder-node-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-node-test-utils", - "version": "0.3.6-next.0", + "version": "0.3.7-next.0", "backstage": { "role": "node-library", "pluginId": "scaffolder", diff --git a/plugins/scaffolder-node/CHANGELOG.md b/plugins/scaffolder-node/CHANGELOG.md index a621739d50..dcb7d78184 100644 --- a/plugins/scaffolder-node/CHANGELOG.md +++ b/plugins/scaffolder-node/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-scaffolder-node +## 0.12.2 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-scaffolder-common@1.7.4 + +## 0.12.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-permission-common@0.9.3 + - @backstage/plugin-scaffolder-common@1.7.4-next.0 + ## 0.12.2-next.0 ### Patch Changes diff --git a/plugins/scaffolder-node/package.json b/plugins/scaffolder-node/package.json index 995ae74b4b..ec82ec8ac5 100644 --- a/plugins/scaffolder-node/package.json +++ b/plugins/scaffolder-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-node", - "version": "0.12.2-next.0", + "version": "0.12.2", "description": "The plugin-scaffolder-node module for @backstage/plugin-scaffolder-backend", "backstage": { "role": "node-library", diff --git a/plugins/scaffolder-react/CHANGELOG.md b/plugins/scaffolder-react/CHANGELOG.md index 552035d603..363804954b 100644 --- a/plugins/scaffolder-react/CHANGELOG.md +++ b/plugins/scaffolder-react/CHANGELOG.md @@ -1,5 +1,48 @@ # @backstage/plugin-scaffolder-react +## 1.19.4 + +### Patch Changes + +- fb029b6: Updated luxon types +- 5ca461e: Fixed bug where custom `review.name` values were incorrectly formatted by `startCase`, preserving them exactly as written. +- be21c5c: Updated dependency `@rjsf/utils` to `5.24.13`. + Updated dependency `@rjsf/core` to `5.24.13`. + Updated dependency `@rjsf/material-ui` to `5.24.13`. + Updated dependency `@rjsf/validator-ajv8` to `5.24.13`. +- 9b38f22: Updated dependency `use-immer` to `^0.11.0`. +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/theme@0.7.1 + - @backstage/plugin-permission-react@0.4.39 + - @backstage/plugin-scaffolder-common@1.7.4 + +## 1.19.4-next.2 + +### Patch Changes + +- fb029b6: Updated luxon types +- be21c5c: Updated dependency `@rjsf/utils` to `5.24.13`. + Updated dependency `@rjsf/core` to `5.24.13`. + Updated dependency `@rjsf/material-ui` to `5.24.13`. + Updated dependency `@rjsf/validator-ajv8` to `5.24.13`. +- 9b38f22: Updated dependency `use-immer` to `^0.11.0`. +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2-next.1 + - @backstage/plugin-catalog-react@1.21.4-next.2 + - @backstage/core-components@0.18.4-next.2 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/theme@0.7.1-next.0 + - @backstage/types@1.2.2 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-permission-react@0.4.39-next.0 + - @backstage/plugin-scaffolder-common@1.7.4-next.0 + ## 1.19.4-next.1 ### Patch Changes diff --git a/plugins/scaffolder-react/package.json b/plugins/scaffolder-react/package.json index 81a01f9229..3bad0ad4c7 100644 --- a/plugins/scaffolder-react/package.json +++ b/plugins/scaffolder-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-react", - "version": "1.19.4-next.1", + "version": "1.19.4", "description": "A frontend library that helps other Backstage plugins interact with the Scaffolder", "backstage": { "role": "web-library", diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx index b0746e0672..6a542396de 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx @@ -514,11 +514,12 @@ describe('Stepper', () => { const mockFormData = { firstName: 'John' }; - Object.defineProperty(window, 'location', { - value: { - search: `?formData=${JSON.stringify(mockFormData)}`, - }, - }); + // Use history.replaceState to set the query string (jsdom 27 doesn't allow redefining window.location) + window.history.replaceState( + {}, + '', + `?formData=${JSON.stringify(mockFormData)}`, + ); const { getByRole } = await renderInTestApp( diff --git a/plugins/scaffolder/CHANGELOG.md b/plugins/scaffolder/CHANGELOG.md index 69554368b7..14a27c8d2a 100644 --- a/plugins/scaffolder/CHANGELOG.md +++ b/plugins/scaffolder/CHANGELOG.md @@ -1,5 +1,56 @@ # @backstage/plugin-scaffolder +## 1.35.0 + +### Minor Changes + +- dab3d3f: Added field extension `RepoOwnerPicker` for retrieving GitHub repository owners. + +### Patch Changes + +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- be21c5c: Updated dependency `@rjsf/utils` to `5.24.13`. + Updated dependency `@rjsf/core` to `5.24.13`. + Updated dependency `@rjsf/material-ui` to `5.24.13`. + Updated dependency `@rjsf/validator-ajv8` to `5.24.13`. +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/plugin-scaffolder-react@1.19.4 + - @backstage/core-components@0.18.4 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/integration-react@1.2.13 + - @backstage/plugin-permission-react@0.4.39 + - @backstage/plugin-scaffolder-common@1.7.4 + - @backstage/plugin-techdocs-react@1.3.6 + +## 1.34.4-next.1 + +### Patch Changes + +- be21c5c: Updated dependency `@rjsf/utils` to `5.24.13`. + Updated dependency `@rjsf/core` to `5.24.13`. + Updated dependency `@rjsf/material-ui` to `5.24.13`. + Updated dependency `@rjsf/validator-ajv8` to `5.24.13`. +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2-next.1 + - @backstage/plugin-scaffolder-react@1.19.4-next.2 + - @backstage/integration@1.18.3-next.1 + - @backstage/plugin-catalog-react@1.21.4-next.2 + - @backstage/core-components@0.18.4-next.2 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/errors@1.2.7 + - @backstage/integration-react@1.2.13-next.0 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-common@1.1.7 + - @backstage/plugin-permission-react@0.4.39-next.0 + - @backstage/plugin-scaffolder-common@1.7.4-next.0 + - @backstage/plugin-techdocs-common@0.1.1 + - @backstage/plugin-techdocs-react@1.3.6-next.0 + ## 1.34.4-next.0 ### Patch Changes diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 55302da959..2d6f52eab4 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder", - "version": "1.34.4-next.0", + "version": "1.35.0", "description": "The Backstage plugin that helps you create new things", "backstage": { "role": "frontend-plugin", diff --git a/plugins/scaffolder/report-alpha.api.md b/plugins/scaffolder/report-alpha.api.md index 7c0247cae9..7ffe367327 100644 --- a/plugins/scaffolder/report-alpha.api.md +++ b/plugins/scaffolder/report-alpha.api.md @@ -350,6 +350,21 @@ const _default: OverridableFrontendPlugin< field: () => Promise; }; }>; + 'scaffolder-form-field:scaffolder/repo-owner-picker': OverridableExtensionDefinition<{ + kind: 'scaffolder-form-field'; + name: 'repo-owner-picker'; + config: {}; + configInput: {}; + output: ExtensionDataRef< + () => Promise, + 'scaffolder.form-field-loader', + {} + >; + inputs: {}; + params: { + field: () => Promise; + }; + }>; 'scaffolder-form-field:scaffolder/repo-url-picker': OverridableExtensionDefinition<{ kind: 'scaffolder-form-field'; name: 'repo-url-picker'; @@ -499,6 +514,8 @@ export const scaffolderTranslationRef: TranslationRef< readonly 'fields.repoUrlPicker.repository.title': 'Repositories Available'; readonly 'fields.repoUrlPicker.repository.description': 'The name of the repository'; readonly 'fields.repoUrlPicker.repository.inputTitle': 'Repository'; + readonly 'fields.repoOwnerPicker.title': 'Owner'; + readonly 'fields.repoOwnerPicker.description': 'The owner of the repository'; readonly 'aboutCard.launchTemplate': 'Launch Template'; readonly 'actionsPage.content.emptyState.title': 'No information to display'; readonly 'actionsPage.content.emptyState.description': 'There are no actions installed or there was an issue communicating with backend.'; diff --git a/plugins/scaffolder/report.api.md b/plugins/scaffolder/report.api.md index 2e9c6be1ef..e624b157fa 100644 --- a/plugins/scaffolder/report.api.md +++ b/plugins/scaffolder/report.api.md @@ -391,6 +391,30 @@ export const RepoBranchPickerFieldExtension: FieldExtensionComponent_2< } >; +// @public +export const RepoOwnerPickerFieldExtension: FieldExtensionComponent_2< + string, + { + host?: string | undefined; + requestUserCredentials?: + | { + secretsKey: string; + additionalScopes?: + | { + azure?: string[] | undefined; + github?: string[] | undefined; + gitlab?: string[] | undefined; + bitbucket?: string[] | undefined; + gerrit?: string[] | undefined; + gitea?: string[] | undefined; + } + | undefined; + } + | undefined; + excludedOwners?: string[] | undefined; + } +>; + // @public export const repoPickerValidation: ( value: string, diff --git a/plugins/scaffolder/src/alpha/components/TemplateEditorPage/TemplateEditorBrowser.test.tsx b/plugins/scaffolder/src/alpha/components/TemplateEditorPage/TemplateEditorBrowser.test.tsx index 427f679188..86400fcfde 100644 --- a/plugins/scaffolder/src/alpha/components/TemplateEditorPage/TemplateEditorBrowser.test.tsx +++ b/plugins/scaffolder/src/alpha/components/TemplateEditorPage/TemplateEditorBrowser.test.tsx @@ -20,14 +20,6 @@ import { MockFileSystemAccess } from '../../../lib/filesystem/MockFileSystemAcce import { DirectoryEditorProvider } from './DirectoryEditorContext'; import { TemplateEditorBrowser } from './TemplateEditorBrowser'; -Blob.prototype.text = async function text() { - return new Promise(resolve => { - const reader = new FileReader(); - reader.onload = () => resolve(reader.result as string); - reader.readAsText(this); - }); -}; - describe('TemplateEditorBrowser', () => { it('should render files and expand dirs without exploding', async () => { await renderInTestApp( diff --git a/plugins/scaffolder/src/alpha/extensions.tsx b/plugins/scaffolder/src/alpha/extensions.tsx index 429e6d493a..5215fc0968 100644 --- a/plugins/scaffolder/src/alpha/extensions.tsx +++ b/plugins/scaffolder/src/alpha/extensions.tsx @@ -127,6 +127,14 @@ export const repoBranchPickerFormField = FormFieldBlueprint.make({ }, }); +export const repoOwnerPickerFormField = FormFieldBlueprint.make({ + name: 'repo-owner-picker', + params: { + field: () => + import('./fields/RepoOwnerPicker').then(m => m.RepoOwnerPicker), + }, +}); + export const scaffolderApi = ApiBlueprint.make({ params: defineParams => defineParams({ diff --git a/plugins/scaffolder/src/alpha/fields/RepoOwnerPicker.ts b/plugins/scaffolder/src/alpha/fields/RepoOwnerPicker.ts new file mode 100644 index 0000000000..059d71fb83 --- /dev/null +++ b/plugins/scaffolder/src/alpha/fields/RepoOwnerPicker.ts @@ -0,0 +1,27 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { createFormField } from '@backstage/plugin-scaffolder-react/alpha'; +import { + RepoOwnerPicker as Component, + RepoOwnerPickerFieldSchema, +} from '../../components/fields/RepoOwnerPicker'; + +export const RepoOwnerPicker = createFormField({ + component: Component, + name: 'RepoOwnerPicker', + schema: RepoOwnerPickerFieldSchema, +}); diff --git a/plugins/scaffolder/src/alpha/plugin.tsx b/plugins/scaffolder/src/alpha/plugin.tsx index 5bb744e2ea..502aab0bbc 100644 --- a/plugins/scaffolder/src/alpha/plugin.tsx +++ b/plugins/scaffolder/src/alpha/plugin.tsx @@ -35,6 +35,7 @@ import { ownedEntityPickerFormField, ownerPickerFormField, repoBranchPickerFormField, + repoOwnerPickerFormField, repoUrlPickerFormField, scaffolderApi, scaffolderNavItem, @@ -88,5 +89,6 @@ export default createFrontendPlugin({ myGroupsPickerFormField, ownedEntityPickerFormField, repoBranchPickerFormField, + repoOwnerPickerFormField, ], }); diff --git a/plugins/scaffolder/src/components/fields/RepoOwnerPicker/DefaultRepoOwnerPicker.test.tsx b/plugins/scaffolder/src/components/fields/RepoOwnerPicker/DefaultRepoOwnerPicker.test.tsx new file mode 100644 index 0000000000..2e335a44a3 --- /dev/null +++ b/plugins/scaffolder/src/components/fields/RepoOwnerPicker/DefaultRepoOwnerPicker.test.tsx @@ -0,0 +1,72 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { fireEvent, screen } from '@testing-library/react'; +import { renderInTestApp } from '@backstage/test-utils'; + +import { DefaultRepoOwnerPicker } from './DefaultRepoOwnerPicker'; + +describe('DefaultRepoOwnerPicker', () => { + it('renders an input field', async () => { + const { getByRole } = await renderInTestApp( + , + ); + + expect(getByRole('textbox')).toBeInTheDocument(); + expect(getByRole('textbox')).toHaveValue('owner1'); + }); + + it('input field disabled', async () => { + await renderInTestApp( + , + ); + + const input = screen.getByRole('textbox'); + + // Expect input to be disabled + expect(input).toBeDisabled(); + expect(input).toHaveValue('owner1'); + }); + + it('calls onChange when the input field changes', async () => { + const onChange = jest.fn(); + + const { getByRole } = await renderInTestApp( + , + ); + + const input = getByRole('textbox'); + + fireEvent.change(input, { + target: { value: 'owner2' }, + }); + + expect(onChange).toHaveBeenCalledWith({ owner: 'owner2' }); + }); +}); diff --git a/plugins/scaffolder/src/components/fields/RepoOwnerPicker/DefaultRepoOwnerPicker.tsx b/plugins/scaffolder/src/components/fields/RepoOwnerPicker/DefaultRepoOwnerPicker.tsx new file mode 100644 index 0000000000..48d7da8ba8 --- /dev/null +++ b/plugins/scaffolder/src/components/fields/RepoOwnerPicker/DefaultRepoOwnerPicker.tsx @@ -0,0 +1,62 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import FormControl from '@material-ui/core/FormControl'; +import FormHelperText from '@material-ui/core/FormHelperText'; +import TextField from '@material-ui/core/TextField'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; + +import { BaseRepoOwnerPickerProps } from './types'; +import { scaffolderTranslationRef } from '../../../translation'; + +/** + * The underlying component that is rendered in the form for the `DefaultRepoOwnerPicker` + * field extension. + * + * @public + * + */ +export const DefaultRepoOwnerPicker = ({ + onChange, + state, + rawErrors, + isDisabled, + required, + schema, +}: BaseRepoOwnerPickerProps) => { + const { owner } = state; + + const { t } = useTranslationRef(scaffolderTranslationRef); + + return ( + 0 && !owner} + > + onChange({ owner: e.target.value })} + value={owner} + /> + + {schema?.description ?? t('fields.repoOwnerPicker.description')} + + + ); +}; diff --git a/plugins/scaffolder/src/components/fields/RepoOwnerPicker/GitHubRepoOwnerPicker.test.tsx b/plugins/scaffolder/src/components/fields/RepoOwnerPicker/GitHubRepoOwnerPicker.test.tsx new file mode 100644 index 0000000000..bfc6c76768 --- /dev/null +++ b/plugins/scaffolder/src/components/fields/RepoOwnerPicker/GitHubRepoOwnerPicker.test.tsx @@ -0,0 +1,149 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + ScaffolderApi, + scaffolderApiRef, +} from '@backstage/plugin-scaffolder-react'; +import { GitHubRepoOwnerPicker } from './GitHubRepoOwnerPicker'; +import { act, fireEvent, waitFor, screen } from '@testing-library/react'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; +import userEvent from '@testing-library/user-event'; + +describe('GitHubRepoOwnerPicker', () => { + const scaffolderApiMock: Partial = { + autocomplete: jest + .fn() + .mockResolvedValue({ results: [{ id: 'owner1' }, { id: 'owner2' }] }), + }; + + it('renders an input field', async () => { + const { getByRole } = await renderInTestApp( + + + , + ); + + expect(getByRole('textbox')).toBeInTheDocument(); + expect(getByRole('textbox')).toHaveValue('owner1'); + }); + + it('input field disabled', async () => { + await renderInTestApp( + + + , + ); + + const input = screen.getByRole('textbox'); + + // Expect input to be disabled + expect(input).toBeDisabled(); + expect(input).toHaveValue('owner1'); + }); + + it('calls onChange when the input field changes', async () => { + const onChange = jest.fn(); + + const { getByRole } = await renderInTestApp( + + + , + ); + + const input = getByRole('textbox'); + + act(() => { + input.focus(); + fireEvent.change(input, { + target: { value: 'owner2' }, + }); + input.blur(); + }); + + expect(onChange).toHaveBeenCalledWith({ owner: 'owner2' }); + }); + + it('should populate owners', async () => { + const onChange = jest.fn(); + + const { getByRole, getByText } = await renderInTestApp( + + + , + ); + + // Open the Autocomplete dropdown + const input = getByRole('textbox'); + await userEvent.click(input); + + // Verify that the available owners are shown + await waitFor(() => expect(getByText('owner1')).toBeInTheDocument()); + + // Verify that selecting an option calls onChange + await userEvent.click(getByText('owner1')); + expect(onChange).toHaveBeenCalledWith({ + owner: 'owner1', + }); + }); + + it('should filter out excluded owners', async () => { + const onChange = jest.fn(); + + const { getByRole, getByText } = await renderInTestApp( + + + , + ); + + // Open the Autocomplete dropdown + const input = getByRole('textbox'); + await userEvent.click(input); + + // Verify that the excluded owners are not shown + await waitFor(() => expect(getByText('owner2')).toBeInTheDocument()); + expect(screen.queryByText('owner1')).not.toBeInTheDocument(); + }); +}); diff --git a/plugins/scaffolder/src/components/fields/RepoOwnerPicker/GitHubRepoOwnerPicker.tsx b/plugins/scaffolder/src/components/fields/RepoOwnerPicker/GitHubRepoOwnerPicker.tsx new file mode 100644 index 0000000000..9258ef312d --- /dev/null +++ b/plugins/scaffolder/src/components/fields/RepoOwnerPicker/GitHubRepoOwnerPicker.tsx @@ -0,0 +1,113 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { useApi } from '@backstage/core-plugin-api'; +import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react'; +import FormControl from '@material-ui/core/FormControl'; +import FormHelperText from '@material-ui/core/FormHelperText'; +import TextField from '@material-ui/core/TextField'; +import Autocomplete from '@material-ui/lab/Autocomplete'; +import { useCallback, useState } from 'react'; +import useDebounce from 'react-use/esm/useDebounce'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; + +import { BaseRepoOwnerPickerProps } from './types'; +import { scaffolderTranslationRef } from '../../../translation'; + +/** + * The underlying component that is rendered in the form for the `GitHubRepoOwnerPicker` + * field extension. + * + * @public + * + */ +export const GitHubRepoOwnerPicker = ({ + onChange, + state, + rawErrors, + accessToken, + isDisabled, + required, + schema, + excludedOwners = [], +}: BaseRepoOwnerPickerProps<{ + accessToken?: string; + excludedOwners?: string[]; +}>) => { + const { host, owner } = state; + + const [availableOwners, setAvailableOwners] = useState([]); + + const scaffolderApi = useApi(scaffolderApiRef); + const { t } = useTranslationRef(scaffolderTranslationRef); + + const updateAvailableOwners = useCallback(() => { + if (!scaffolderApi.autocomplete || !accessToken || !host) { + setAvailableOwners([]); + return; + } + + scaffolderApi + .autocomplete({ + token: accessToken, + resource: 'owners', + context: { host }, + provider: 'github', + }) + .then(({ results }) => { + const owners = results + .map(r => r.id) + .filter(id => !excludedOwners.includes(id)); + + setAvailableOwners(owners); + }) + .catch(() => { + setAvailableOwners([]); + }); + }, [host, accessToken, scaffolderApi, excludedOwners]); + + useDebounce(updateAvailableOwners, 500, [updateAvailableOwners]); + + return ( + 0 && !owner} + > + { + onChange({ owner: newValue || '' }); + }} + disabled={isDisabled} + options={availableOwners} + renderInput={params => ( + + )} + freeSolo + autoSelect + /> + + {schema?.description ?? t('fields.repoOwnerPicker.description')} + + + ); +}; diff --git a/plugins/scaffolder/src/components/fields/RepoOwnerPicker/RepoOwnerPicker.test.tsx b/plugins/scaffolder/src/components/fields/RepoOwnerPicker/RepoOwnerPicker.test.tsx new file mode 100644 index 0000000000..c51d74416b --- /dev/null +++ b/plugins/scaffolder/src/components/fields/RepoOwnerPicker/RepoOwnerPicker.test.tsx @@ -0,0 +1,308 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Form } from '@backstage/plugin-scaffolder-react/alpha'; +import validator from '@rjsf/validator-ajv8'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; +import { + scmIntegrationsApiRef, + ScmIntegrationsApi, + scmAuthApiRef, + ScmAuthApi, +} from '@backstage/integration-react'; + +import { + SecretsContextProvider, + scaffolderApiRef, + useTemplateSecrets, + ScaffolderRJSFField, +} from '@backstage/plugin-scaffolder-react'; +import { act, fireEvent, screen } from '@testing-library/react'; +import { RepoOwnerPicker } from './RepoOwnerPicker'; + +describe('RepoOwnerPicker', () => { + const mockIntegrationsApi: Partial = { + byHost: () => ({ type: 'github' }), + }; + + let mockScmAuthApi: Partial; + + beforeEach(() => { + mockScmAuthApi = { + getCredentials: jest.fn().mockResolvedValue({ token: 'abc123' }), + }; + }); + + describe('happy path rendering', () => { + it('should render the repo owner picker with minimal props', async () => { + const onSubmit = jest.fn(); + + const { getByRole, getByText } = await renderInTestApp( + + +
, + }} + onSubmit={onSubmit} + /> +
+
, + ); + + const input = getByRole('textbox'); + const submitButton = getByRole('button'); + + fireEvent.change(input, { target: { value: 'owner1' } }); + + fireEvent.click(submitButton); + + expect(onSubmit).toHaveBeenCalledWith( + expect.objectContaining({ + formData: 'owner1', + }), + expect.anything(), + ); + + expect(getByText('Owner')).toBeInTheDocument(); + expect(getByText('The owner of the repository')).toBeInTheDocument(); + }); + + it('should disable the picker when ui:disabled', async () => { + const onSubmit = jest.fn(); + + await renderInTestApp( + + + , + }} + onSubmit={onSubmit} + /> + + , + ); + + const input = screen.getByRole('textbox'); + + expect(input).toBeDisabled(); + }); + + it('should render properly with title and description', async () => { + const { getByText } = await renderInTestApp( + + + , + }} + /> + + , + ); + + expect(getByText('test title')).toBeInTheDocument(); + expect(getByText('test description')).toBeInTheDocument(); + }); + }); + + describe('requestUserCredentials', () => { + it('should call the scmAuthApi with the correct params', async () => { + const secretsKey = 'testKey'; + + const SecretsComponent = () => { + const { secrets } = useTemplateSecrets(); + const secret = secrets[secretsKey]; + return secret ?
{secret}
: null; + }; + + const { getByText } = await renderInTestApp( + + + , + }} + /> + + + , + ); + + await act(async () => { + // need to wait for the debounce to finish + await new Promise(resolve => setTimeout(resolve, 600)); + }); + + expect(mockScmAuthApi.getCredentials).toHaveBeenCalledWith({ + url: 'https://github.com', + additionalScope: { + repoWrite: true, + customScopes: { + github: ['workflow'], + }, + }, + }); + + expect(getByText('abc123')).toBeInTheDocument(); + }); + + it('should call the scmAuthApi with the correct params if workspace is nested', async () => { + await renderInTestApp( + + + , + }} + /> + + , + ); + + await act(async () => { + // need to wait for the debounce to finish + await new Promise(resolve => setTimeout(resolve, 600)); + }); + + expect(mockScmAuthApi.getCredentials).toHaveBeenCalledWith({ + url: 'https://github.com', + additionalScope: { + repoWrite: true, + }, + }); + }); + + it('should not call the scmAuthApi if secret is available in the state', async () => { + const secretsKey = 'testKey'; + + const SecretsComponent = () => { + const { secrets } = useTemplateSecrets(); + const secret = secrets[secretsKey]; + return secret ?
{secret}
: null; + }; + + const { getByText } = await renderInTestApp( + + + , + }} + /> + + + , + ); + + await act(async () => { + // need to wait for the debounce to finish + await new Promise(resolve => setTimeout(resolve, 600)); + }); + + // as we already have a secret in the state, getCredentials should not be called again. + expect(mockScmAuthApi.getCredentials).toHaveBeenCalledTimes(0); + + expect(getByText('abc123')).toBeInTheDocument(); + }); + }); +}); diff --git a/plugins/scaffolder/src/components/fields/RepoOwnerPicker/RepoOwnerPicker.tsx b/plugins/scaffolder/src/components/fields/RepoOwnerPicker/RepoOwnerPicker.tsx new file mode 100644 index 0000000000..bcb1a0001c --- /dev/null +++ b/plugins/scaffolder/src/components/fields/RepoOwnerPicker/RepoOwnerPicker.tsx @@ -0,0 +1,138 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { useApi } from '@backstage/core-plugin-api'; +import { + scmIntegrationsApiRef, + scmAuthApiRef, +} from '@backstage/integration-react'; +import { useEffect, useState, useCallback, useMemo } from 'react'; +import useDebounce from 'react-use/esm/useDebounce'; +import { useTemplateSecrets } from '@backstage/plugin-scaffolder-react'; + +import { RepoOwnerPickerProps } from './schema'; +import { RepoOwnerPickerState } from './types'; +import { DefaultRepoOwnerPicker } from './DefaultRepoOwnerPicker'; +import { GitHubRepoOwnerPicker } from './GitHubRepoOwnerPicker'; + +/** + * The underlying component that is rendered in the form for the `RepoOwnerPicker` + * field extension. + * + * @public + */ +export const RepoOwnerPicker = (props: RepoOwnerPickerProps) => { + const { uiSchema, onChange, rawErrors, formData, schema, required } = props; + const [state, setState] = useState({ + owner: formData || '', + }); + const excludedOwners = useMemo( + () => uiSchema?.['ui:options']?.excludedOwners ?? [], + [uiSchema], + ); + const { host, owner } = state; + + const integrationApi = useApi(scmIntegrationsApiRef); + const scmAuthApi = useApi(scmAuthApiRef); + + const { secrets, setSecrets } = useTemplateSecrets(); + + useDebounce( + async () => { + const { requestUserCredentials } = uiSchema?.['ui:options'] ?? {}; + + if (!requestUserCredentials || !host) { + return; + } + + // don't show login prompt if secret value is already in state + if (secrets[requestUserCredentials.secretsKey]) { + return; + } + + // 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://${host}`, + additionalScope: { + repoWrite: true, + customScopes: requestUserCredentials.additionalScopes, + }, + }); + + // set the secret using the key provided in the ui:options for use + // in the templating the manifest with ${{ secrets[secretsKey] }} + setSecrets({ [requestUserCredentials.secretsKey]: token }); + }, + 500, + [host, uiSchema], + ); + + useEffect(() => { + if (uiSchema?.['ui:options']?.host) { + const hostUiOption = uiSchema['ui:options'].host; + setState(prevState => ({ ...prevState, host: hostUiOption })); + } + }, [uiSchema]); + + useEffect(() => { + onChange(owner); + }, [owner, onChange]); + + const updateLocalState = useCallback( + (newState: RepoOwnerPickerState) => { + setState(prevState => ({ ...prevState, ...newState })); + }, + [setState], + ); + + const hostType = (host && integrationApi.byHost(host)?.type) ?? null; + + const renderRepoOwnerPicker = () => { + switch (hostType) { + case 'github': + return ( + + ); + default: + return ( + + ); + } + }; + + return renderRepoOwnerPicker(); +}; diff --git a/plugins/scaffolder/src/components/fields/RepoOwnerPicker/index.ts b/plugins/scaffolder/src/components/fields/RepoOwnerPicker/index.ts new file mode 100644 index 0000000000..d93e5e22e5 --- /dev/null +++ b/plugins/scaffolder/src/components/fields/RepoOwnerPicker/index.ts @@ -0,0 +1,22 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { RepoOwnerPicker } from './RepoOwnerPicker'; +export { + RepoOwnerPickerFieldSchema, + type RepoOwnerPickerUiOptions, + RepoOwnerPickerSchema, +} from './schema'; diff --git a/plugins/scaffolder/src/components/fields/RepoOwnerPicker/schema.ts b/plugins/scaffolder/src/components/fields/RepoOwnerPicker/schema.ts new file mode 100644 index 0000000000..7931ca1eec --- /dev/null +++ b/plugins/scaffolder/src/components/fields/RepoOwnerPicker/schema.ts @@ -0,0 +1,86 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { makeFieldSchema } from '@backstage/plugin-scaffolder-react'; + +export const RepoOwnerPickerFieldSchema = makeFieldSchema({ + output: z => z.string(), + uiOptions: z => + z.object({ + host: z.string().optional(), + excludedOwners: z + .array(z.string()) + .optional() + .describe('List of excluded owners'), + requestUserCredentials: z + .object({ + secretsKey: z + .string() + .describe( + 'Key used within the template secrets context to store the credential', + ), + additionalScopes: z + .object({ + gitea: z + .array(z.string()) + .optional() + .describe('Additional Gitea scopes to request'), + gerrit: z + .array(z.string()) + .optional() + .describe('Additional Gerrit scopes to request'), + github: z + .array(z.string()) + .optional() + .describe('Additional GitHub scopes to request'), + gitlab: z + .array(z.string()) + .optional() + .describe('Additional GitLab scopes to request'), + bitbucket: z + .array(z.string()) + .optional() + .describe('Additional BitBucket scopes to request'), + azure: z + .array(z.string()) + .optional() + .describe('Additional Azure scopes to request'), + }) + .optional() + .describe('Additional permission scopes to request'), + }) + .optional() + .describe( + 'If defined will request user credentials to auth against the given SCM platform', + ), + }), +}); + +/** + * The input props that can be specified under `ui:options` for the + * `RepoOwnerPicker` field extension. + */ +export type RepoOwnerPickerUiOptions = NonNullable< + (typeof RepoOwnerPickerFieldSchema.TProps.uiSchema)['ui:options'] +>; + +export type RepoOwnerPickerProps = typeof RepoOwnerPickerFieldSchema.TProps; + +// This has been duplicated from /plugins/scaffolder/src/components/fields/RepoUrlPicker/schema.ts +// NOTE: There is a bug with this failing validation in the custom field explorer due +// to https://github.com/rjsf-team/react-jsonschema-form/issues/675 even if +// requestUserCredentials is not defined +export const RepoOwnerPickerSchema = RepoOwnerPickerFieldSchema.schema; diff --git a/plugins/scaffolder/src/components/fields/RepoOwnerPicker/types.ts b/plugins/scaffolder/src/components/fields/RepoOwnerPicker/types.ts new file mode 100644 index 0000000000..eceed58df5 --- /dev/null +++ b/plugins/scaffolder/src/components/fields/RepoOwnerPicker/types.ts @@ -0,0 +1,31 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { RJSFSchema } from '@rjsf/utils'; + +export interface RepoOwnerPickerState { + host?: string; + owner?: string; +} + +export type BaseRepoOwnerPickerProps = T & { + onChange: (state: RepoOwnerPickerState) => void; + state: RepoOwnerPickerState; + rawErrors: string[]; + isDisabled?: boolean; + required?: boolean; + schema?: RJSFSchema; +}; diff --git a/plugins/scaffolder/src/components/fields/VirtualizedListbox.test.tsx b/plugins/scaffolder/src/components/fields/VirtualizedListbox.test.tsx index 59f311fe88..8a058d5320 100644 --- a/plugins/scaffolder/src/components/fields/VirtualizedListbox.test.tsx +++ b/plugins/scaffolder/src/components/fields/VirtualizedListbox.test.tsx @@ -33,7 +33,7 @@ describe('', () => { aria-expanded="true" class="MuiAutocomplete-root MuiAutocomplete-hasClearIcon MuiAutocomplete-hasPopupIcon" role="combobox" - style="position: relative; height: 18px; width: 100%; overflow: auto; will-change: transform; direction: ltr;" + style="position: relative; height: 18px; width: 100%; overflow: auto; -webkit-overflow-scrolling: touch; will-change: transform; direction: ltr;" >
', () => {
', () => {
', () => {
', () => {
{ expect(screen.getByText('Results per page:')).toBeInTheDocument(); expect(screen.getByText('25')).toBeInTheDocument(); expect(screen.getByText('1-25')).toBeInTheDocument(); - expect(screen.getByLabelText('Next page')).toBeEnabled(); + expect(screen.getByLabelText('Next page')).toBeDisabled(); expect(screen.getByLabelText('Previous page')).toBeDisabled(); }); @@ -176,6 +176,12 @@ describe('SearchPagination', () => { }); it('Set page limit in the context', async () => { + const initialState = { + term: 'a', + types: [], + filters: {}, + }; + await renderInTestApp( { [configApiRef, configApiMock], ]} > - + , @@ -205,7 +211,7 @@ describe('SearchPagination', () => { it('Set page cursor in the context', async () => { const initialState = { - term: '', + term: 'a', types: [], filters: {}, pageCursor: 'MQ==', // page: 1 @@ -253,7 +259,7 @@ describe('SearchPagination', () => { it('Resets page cursor when page limit changes', async () => { const initialState = { - term: '', + term: 'a', types: [], filters: {}, pageCursor: 'Mg==', // page: 2 @@ -280,9 +286,7 @@ describe('SearchPagination', () => { pageCursor: undefined, pageLimit: 10, }), - { - signal: expect.any(AbortSignal), - }, + { signal: expect.any(AbortSignal) }, ); }); }); diff --git a/plugins/search-react/src/components/SearchResultGroup/SearchResultGroup.test.tsx b/plugins/search-react/src/components/SearchResultGroup/SearchResultGroup.test.tsx index cb274be0a0..0f46f15ed4 100644 --- a/plugins/search-react/src/components/SearchResultGroup/SearchResultGroup.test.tsx +++ b/plugins/search-react/src/components/SearchResultGroup/SearchResultGroup.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { screen, waitFor } from '@testing-library/react'; +import { screen, waitFor, fireEvent } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import MenuItem from '@material-ui/core/MenuItem'; @@ -66,7 +66,7 @@ describe('SearchResultGroup', () => { }); it('Renders without exploding', async () => { - query.mockResolvedValueOnce({ + query.mockResolvedValue({ results, }); @@ -96,7 +96,7 @@ describe('SearchResultGroup', () => { }); it('Renders search results from context', async () => { - query.mockResolvedValueOnce({ + query.mockResolvedValue({ results, }); @@ -107,7 +107,9 @@ describe('SearchResultGroup', () => { [analyticsApiRef, analyticsApiMock], ]} > - + } title="Documentation" @@ -128,7 +130,7 @@ describe('SearchResultGroup', () => { }); it('Renders search results using extensions', async () => { - query.mockResolvedValueOnce({ + query.mockResolvedValue({ results, }); @@ -166,7 +168,7 @@ describe('SearchResultGroup', () => { }); it('Defines a default link', async () => { - query.mockResolvedValueOnce({ + query.mockResolvedValue({ results, }); @@ -190,7 +192,7 @@ describe('SearchResultGroup', () => { }); it('Defines a default render result item', async () => { - query.mockResolvedValueOnce({ + query.mockResolvedValue({ results, }); @@ -221,6 +223,10 @@ describe('SearchResultGroup', () => { }); it('Could be customized with no results text', async () => { + query.mockResolvedValue({ + results: [], + }); + await renderInTestApp( { }); it('Could be customized with filters', async () => { - query.mockResolvedValueOnce({ + query.mockResolvedValue({ results, }); @@ -272,7 +278,7 @@ describe('SearchResultGroup', () => { }); it('Could have a text search filter field', async () => { - query.mockResolvedValueOnce({ + query.mockResolvedValue({ results, }); @@ -312,10 +318,10 @@ describe('SearchResultGroup', () => { await userEvent.click(screen.getByText('owner')); - await userEvent.type( - screen.getByRole('textbox'), - '{backspace}{backspace}{backspace}{backspace}techdocs-core', - ); + // Use fireEvent.blur for contentEditable elements since userEvent.type with + // backspace doesn't work properly in jsdom (jsdom limitation, not a bug) + const textbox = screen.getByRole('textbox'); + fireEvent.blur(textbox, { target: { textContent: 'techdocs-core' } }); await waitFor(() => { expect(screen.getByText('techdocs-core')).toBeInTheDocument(); @@ -323,7 +329,7 @@ describe('SearchResultGroup', () => { }); it('Could have a select search filter field', async () => { - query.mockResolvedValueOnce({ + query.mockResolvedValue({ results, }); @@ -376,7 +382,7 @@ describe('SearchResultGroup', () => { }); it('Shows a progress bar when loading results', async () => { - query.mockReturnValueOnce(new Promise(() => {})); + query.mockReturnValue(new Promise(() => {})); await renderInTestApp( { }); it('Does not render result group if no results returned and disableRenderingWithNoResults prop is provided', async () => { - query.mockResolvedValueOnce({ results: [] }); + query.mockResolvedValue({ results: [] }); await renderInTestApp( { }); it('Should render custom component when no results returned', async () => { - query.mockResolvedValueOnce({ results: [] }); + query.mockResolvedValue({ results: [] }); await renderInTestApp( { }); it('Shows an error panel when results rendering fails', async () => { - query.mockRejectedValueOnce(new Error()); + query.mockRejectedValue(new Error()); await renderInTestApp( ( initialValue.pageCursor, ); + const isFirstEmptyMount = useRef(true); const prevTerm = usePrevious(term); const prevFilters = usePrevious(filters); const abortControllerRef = useRef(null); - const result = useAsync(async () => { + const result = useAsync(async (): Promise => { + if (isFirstEmptyMount.current) { + if (!term && !types.length && !Object.keys(filters).length) { + return { + results: [], + numberOfResults: 0, + }; + } + + isFirstEmptyMount.current = false; + } + // Here we cancel the previous request before making a new one if (abortControllerRef.current) { abortControllerRef.current.abort(); diff --git a/plugins/search/CHANGELOG.md b/plugins/search/CHANGELOG.md index 789e9b2603..8ffeceef6a 100644 --- a/plugins/search/CHANGELOG.md +++ b/plugins/search/CHANGELOG.md @@ -1,5 +1,34 @@ # @backstage/plugin-search +## 1.5.1 + +### Patch Changes + +- f3f84f1: Minor extension type updates after frontend API bump +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/plugin-search-react@1.10.1 + - @backstage/core-plugin-api@1.12.1 + +## 1.5.1-next.1 + +### Patch Changes + +- f3f84f1: Minor extension type updates after frontend API bump +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2-next.1 + - @backstage/plugin-catalog-react@1.21.4-next.2 + - @backstage/core-components@0.18.4-next.2 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-search-common@1.2.21 + - @backstage/plugin-search-react@1.10.1-next.0 + ## 1.5.1-next.0 ### Patch Changes diff --git a/plugins/search/package.json b/plugins/search/package.json index 794178d870..35db8a6d35 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search", - "version": "1.5.1-next.0", + "version": "1.5.1", "description": "The Backstage plugin that provides your backstage app with search", "backstage": { "role": "frontend-plugin", diff --git a/plugins/search/report-alpha.api.md b/plugins/search/report-alpha.api.md index 5353fec09e..b129d4ab6c 100644 --- a/plugins/search/report-alpha.api.md +++ b/plugins/search/report-alpha.api.md @@ -264,8 +264,8 @@ export const searchTranslationRef: TranslationRef< readonly 'searchType.tabs.allTitle': 'All'; readonly 'searchType.allResults': 'All Results'; readonly 'searchType.accordion.collapse': 'Collapse'; - readonly 'searchType.accordion.allTitle': 'All'; readonly 'searchType.accordion.numberOfResults': '{{number}} results'; + readonly 'searchType.accordion.allTitle': 'All'; readonly 'sidebarSearchModal.title': 'Search'; } >; diff --git a/plugins/search/src/components/HomePageComponent/HomePageSearchBar.test.tsx b/plugins/search/src/components/HomePageComponent/HomePageSearchBar.test.tsx index e7c47b7d30..270bdbb2eb 100644 --- a/plugins/search/src/components/HomePageComponent/HomePageSearchBar.test.tsx +++ b/plugins/search/src/components/HomePageComponent/HomePageSearchBar.test.tsx @@ -46,12 +46,7 @@ describe('', () => { }, ); - expect(searchApiMock.query).toHaveBeenCalledWith( - expect.objectContaining({ term: '' }), - { - signal: expect.any(AbortSignal), - }, - ); + expect(searchApiMock.query).not.toHaveBeenCalled(); await userEvent.type(screen.getByLabelText('Search'), 'term{enter}'); diff --git a/plugins/search/src/components/SearchModal/SearchModal.test.tsx b/plugins/search/src/components/SearchModal/SearchModal.test.tsx index 8d8e1bb9b9..9424599130 100644 --- a/plugins/search/src/components/SearchModal/SearchModal.test.tsx +++ b/plugins/search/src/components/SearchModal/SearchModal.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { screen } from '@testing-library/react'; +import { screen, waitFor } from '@testing-library/react'; import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils'; import userEvent from '@testing-library/user-event'; import { configApiRef } from '@backstage/core-plugin-api'; @@ -63,7 +63,6 @@ describe('SearchModal', () => { ); expect(screen.getByRole('dialog')).toBeInTheDocument(); - expect(searchApiMock.query).toHaveBeenCalledTimes(1); }); it('Should use parent search context if defined', async () => { @@ -106,15 +105,21 @@ describe('SearchModal', () => { ); expect(screen.getByRole('dialog')).toBeInTheDocument(); - expect(searchApiMock.query).toHaveBeenCalledWith( - { - term: '', - filters: {}, - types: [], - pageCursor: undefined, - }, - { signal: expect.any(AbortSignal) }, - ); + + const input = screen.getByLabelText('Search'); + await userEvent.type(input, 'text'); + + await waitFor(() => { + expect(searchApiMock.query).toHaveBeenCalledWith( + { + term: 'text', + filters: {}, + types: [], + pageCursor: undefined, + }, + { signal: expect.any(AbortSignal) }, + ); + }); }); it('Should render a custom Modal correctly', async () => { @@ -146,7 +151,6 @@ describe('SearchModal', () => { }, ); - expect(searchApiMock.query).toHaveBeenCalledTimes(1); await userEvent.keyboard('{Escape}'); expect(toggleModal).toHaveBeenCalledTimes(1); }); diff --git a/plugins/signals-backend/CHANGELOG.md b/plugins/signals-backend/CHANGELOG.md index 778eedd8e0..ba15a7f165 100644 --- a/plugins/signals-backend/CHANGELOG.md +++ b/plugins/signals-backend/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-signals-backend +## 0.3.11 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-events-node@0.4.18 + - @backstage/plugin-signals-node@0.1.27 + - @backstage/backend-plugin-api@1.6.0 + +## 0.3.11-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/plugin-signals-node@0.1.27-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/types@1.2.2 + ## 0.3.11-next.0 ### Patch Changes diff --git a/plugins/signals-backend/package.json b/plugins/signals-backend/package.json index 16e84637bd..16ff55a7a4 100644 --- a/plugins/signals-backend/package.json +++ b/plugins/signals-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-signals-backend", - "version": "0.3.11-next.0", + "version": "0.3.11", "backstage": { "role": "backend-plugin", "pluginId": "signals", diff --git a/plugins/signals-node/CHANGELOG.md b/plugins/signals-node/CHANGELOG.md index 4d963038a4..89f3cbfc09 100644 --- a/plugins/signals-node/CHANGELOG.md +++ b/plugins/signals-node/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-signals-node +## 0.1.27 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/plugin-events-node@0.4.18 + - @backstage/backend-plugin-api@1.6.0 + +## 0.1.27-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/plugin-events-node@0.4.18-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/config@1.3.6 + - @backstage/types@1.2.2 + ## 0.1.27-next.0 ### Patch Changes diff --git a/plugins/signals-node/package.json b/plugins/signals-node/package.json index 3727d3de12..41df262538 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.27-next.0", + "version": "0.1.27", "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 6938e0271b..d8ad46909e 100644 --- a/plugins/signals-react/CHANGELOG.md +++ b/plugins/signals-react/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-signals-react +## 0.0.18 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.12.1 + ## 0.0.18-next.0 ### Patch Changes diff --git a/plugins/signals-react/package.json b/plugins/signals-react/package.json index fa67692556..debc7647ef 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.18-next.0", + "version": "0.0.18", "description": "Web library for the signals plugin", "backstage": { "role": "web-library", diff --git a/plugins/signals/CHANGELOG.md b/plugins/signals/CHANGELOG.md index 20fadf416f..2e170fd29d 100644 --- a/plugins/signals/CHANGELOG.md +++ b/plugins/signals/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-signals +## 0.0.26 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/theme@0.7.1 + - @backstage/plugin-signals-react@0.0.18 + ## 0.0.26-next.0 ### Patch Changes diff --git a/plugins/signals/package.json b/plugins/signals/package.json index 9a9ae4c9da..6ff62d6943 100644 --- a/plugins/signals/package.json +++ b/plugins/signals/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-signals", - "version": "0.0.26-next.0", + "version": "0.0.26", "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 1f78d1fa4b..21ace9fa17 100644 --- a/plugins/techdocs-addons-test-utils/CHANGELOG.md +++ b/plugins/techdocs-addons-test-utils/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/plugin-techdocs-addons-test-utils +## 2.0.0 + +### Major Changes + +- 8d6709e: **BREAKING**: `TechDocsAddonTester.renderWithEffects()` no longer returns a screen; this means that you can no longer grab assertions such as `getByText` from its return value. + + Newer versions of `@testing-library` recommends using the `screen` export for assertions - and removing this from the addon tester contract allows us to more freely iterate on which underlying version of the testing library is being used. + + One notable effect of this, however, is that the `@testing-library` `screen` does NOT support assertions on the shadow DOM, which techdocs relies on. You will therefore want to add a dependency on [the `shadow-dom-testing-library` package](https://github.com/konnorrogers/shadow-dom-testing-library/) in your tests, and using its `screen` and its dedicated `*Shadow*` methods. As an example, if you keep doing `getByText` you will not get matches inside the shadow DOM - switch to `getByShadowText` instead. + + ```ts + import { screen } from 'shadow-dom-testing-library'; + + // ... render the addon ... + await TechDocsAddonTester.buildAddonsInTechDocs([]) + .withDom(TEST_CONTENT) + .renderWithEffects(); + + expect(screen.getByShadowText('TEST_CONTENT')).toBeInTheDocument(); + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.19.3 + - @backstage/plugin-techdocs@1.16.1 + - @backstage/plugin-catalog@1.32.1 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/plugin-search-react@1.10.1 + - @backstage/test-utils@1.7.14 + - @backstage/core-plugin-api@1.12.1 + - @backstage/integration-react@1.2.13 + - @backstage/plugin-techdocs-react@1.3.6 + ## 2.0.0-next.1 ### Major Changes diff --git a/plugins/techdocs-addons-test-utils/package.json b/plugins/techdocs-addons-test-utils/package.json index 9045f33b03..05ea82584e 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": "2.0.0-next.1", + "version": "2.0.0", "backstage": { "role": "web-library", "pluginId": "techdocs-addons", diff --git a/plugins/techdocs-backend/CHANGELOG.md b/plugins/techdocs-backend/CHANGELOG.md index 97fe3bdab4..7e44ce1c60 100644 --- a/plugins/techdocs-backend/CHANGELOG.md +++ b/plugins/techdocs-backend/CHANGELOG.md @@ -1,5 +1,53 @@ # @backstage/plugin-techdocs-backend +## 2.1.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.14.1-next.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/integration@1.19.0 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-node@1.20.1 + - @backstage/plugin-techdocs-node@1.13.10 + +## 2.1.3 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- 2bae83a: Corrected `ErrorCallback` type to work with Node 22 types +- 592361e: The `techdocs` config is now marked as optional. +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-defaults@0.14.0 + - @backstage/plugin-techdocs-node@1.13.10 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/plugin-catalog-node@1.20.1 + +## 2.1.3-next.2 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- 2bae83a: Corrected `ErrorCallback` type to work with Node 22 types +- Updated dependencies + - @backstage/backend-defaults@0.14.0-next.1 + - @backstage/plugin-techdocs-node@1.13.10-next.1 + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-catalog-node@1.20.1-next.1 + ## 2.1.3-next.1 ### Patch Changes diff --git a/plugins/techdocs-backend/config.d.ts b/plugins/techdocs-backend/config.d.ts index 1520ad70ec..5d3baa940a 100644 --- a/plugins/techdocs-backend/config.d.ts +++ b/plugins/techdocs-backend/config.d.ts @@ -100,7 +100,6 @@ export interface Config { * If account ID is not set and no credentials are set, environment variables or aws config file will be used to authenticate. * @see https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/loading-node-credentials-environment.html * @see https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/loading-node-credentials-shared.html - * @visibility secret */ accountId?: string; /** @@ -141,14 +140,12 @@ export interface Config { * (Optional) AWS Region. * If not set, AWS_REGION environment variable or aws config file will be used. * @see https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/setting-region.html - * @visibility secret */ region?: string; /** * (Optional) AWS Endpoint. * The endpoint URI to send requests to. The default endpoint is built from the configured region. * @see https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#constructor-property - * @visibility secret */ endpoint?: string; /** diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index 9580ed2326..965160f717 100644 --- a/plugins/techdocs-backend/package.json +++ b/plugins/techdocs-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs-backend", - "version": "2.1.3-next.1", + "version": "2.1.4-next.0", "description": "The Backstage backend plugin that renders technical documentation for your components", "backstage": { "role": "backend-plugin", diff --git a/plugins/techdocs-module-addons-contrib/CHANGELOG.md b/plugins/techdocs-module-addons-contrib/CHANGELOG.md index 922e295257..96d9129b4d 100644 --- a/plugins/techdocs-module-addons-contrib/CHANGELOG.md +++ b/plugins/techdocs-module-addons-contrib/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-techdocs-module-addons-contrib +## 1.1.31 + +### Patch Changes + +- 8d6709e: Updated tests to match test-utils change +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/integration-react@1.2.13 + - @backstage/plugin-techdocs-react@1.3.6 + ## 1.1.31-next.1 ### Patch Changes diff --git a/plugins/techdocs-module-addons-contrib/package.json b/plugins/techdocs-module-addons-contrib/package.json index 7d04f6268a..68fd2ede1a 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.31-next.1", + "version": "1.1.31", "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 6a6b95c922..94c0a6e912 100644 --- a/plugins/techdocs-node/CHANGELOG.md +++ b/plugins/techdocs-node/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-techdocs-node +## 1.13.10 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- 703f8c0: There was an issue in the uploading of large size files to the AWS S3. We have modified the logic by adding retry along with multipart uploading functionality. +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/backend-plugin-api@1.6.0 + +## 1.13.10-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- 703f8c0: There was an issue in the uploading of large size files to the AWS S3. We have modified the logic by adding retry along with multipart uploading functionality. +- Updated dependencies + - @backstage/integration@1.18.3-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/errors@1.2.7 + - @backstage/integration-aws-node@0.1.19 + - @backstage/plugin-search-common@1.2.21 + - @backstage/plugin-techdocs-common@0.1.1 + ## 1.13.10-next.0 ### Patch Changes diff --git a/plugins/techdocs-node/package.json b/plugins/techdocs-node/package.json index 4752dc65c5..c5858cdf8f 100644 --- a/plugins/techdocs-node/package.json +++ b/plugins/techdocs-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs-node", - "version": "1.13.10-next.0", + "version": "1.13.10", "description": "Common node.js functionalities for TechDocs, to be shared between techdocs-backend plugin and techdocs-cli", "backstage": { "role": "node-library", diff --git a/plugins/techdocs-react/CHANGELOG.md b/plugins/techdocs-react/CHANGELOG.md index 426ff95859..1763386235 100644 --- a/plugins/techdocs-react/CHANGELOG.md +++ b/plugins/techdocs-react/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-techdocs-react +## 1.3.6 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/core-plugin-api@1.12.1 + ## 1.3.6-next.0 ### Patch Changes diff --git a/plugins/techdocs-react/package.json b/plugins/techdocs-react/package.json index fa8d2c5935..44bed4646f 100644 --- a/plugins/techdocs-react/package.json +++ b/plugins/techdocs-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs-react", - "version": "1.3.6-next.0", + "version": "1.3.6", "description": "Shared frontend utilities for TechDocs and Addons", "backstage": { "role": "web-library", diff --git a/plugins/techdocs/CHANGELOG.md b/plugins/techdocs/CHANGELOG.md index 2aaf6459f0..043bc49b6f 100644 --- a/plugins/techdocs/CHANGELOG.md +++ b/plugins/techdocs/CHANGELOG.md @@ -1,5 +1,48 @@ # @backstage/plugin-techdocs +## 1.16.1 + +### Patch Changes + +- f3f84f1: Minor extension type updates after frontend API bump +- 5c33821: Fixed schema type for additionalAllowedURIProtocols +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- 592361e: The `techdocs` config is now marked as optional. +- Updated dependencies + - @backstage/integration@1.19.0 + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/plugin-search-react@1.10.1 + - @backstage/core-plugin-api@1.12.1 + - @backstage/theme@0.7.1 + - @backstage/integration-react@1.2.13 + - @backstage/plugin-auth-react@0.1.22 + - @backstage/plugin-techdocs-react@1.3.6 + +## 1.16.1-next.2 + +### Patch Changes + +- f3f84f1: Minor extension type updates after frontend API bump +- Updated dependencies + - @backstage/frontend-plugin-api@0.13.2-next.1 + - @backstage/integration@1.18.3-next.1 + - @backstage/plugin-catalog-react@1.21.4-next.2 + - @backstage/core-components@0.18.4-next.2 + - @backstage/catalog-client@1.12.1 + - @backstage/catalog-model@1.7.6 + - @backstage/config@1.3.6 + - @backstage/core-plugin-api@1.12.1-next.0 + - @backstage/errors@1.2.7 + - @backstage/integration-react@1.2.13-next.0 + - @backstage/theme@0.7.1-next.0 + - @backstage/plugin-auth-react@0.1.22-next.0 + - @backstage/plugin-search-common@1.2.21 + - @backstage/plugin-search-react@1.10.1-next.0 + - @backstage/plugin-techdocs-common@0.1.1 + - @backstage/plugin-techdocs-react@1.3.6-next.0 + ## 1.16.1-next.1 ### Patch Changes diff --git a/plugins/techdocs/config.d.ts b/plugins/techdocs/config.d.ts index 584d340fbf..0e9b7abdda 100644 --- a/plugins/techdocs/config.d.ts +++ b/plugins/techdocs/config.d.ts @@ -67,7 +67,7 @@ export interface Config { * @see: https://raw.githubusercontent.com/cure53/DOMPurify/master/src/regexp.ts * @visibility frontend */ - additionalAllowedURIProtocols?: string; + additionalAllowedURIProtocols?: string[]; }; }; } diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 7870dd71f3..2c052582d7 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs", - "version": "1.16.1-next.1", + "version": "1.16.1", "description": "The Backstage plugin that renders technical documentation for your components", "backstage": { "role": "frontend-plugin", diff --git a/plugins/techdocs/src/reader/transformers/handleMetaRedirects.test.ts b/plugins/techdocs/src/reader/transformers/handleMetaRedirects.test.ts index 0be1773846..00180464cf 100644 --- a/plugins/techdocs/src/reader/transformers/handleMetaRedirects.test.ts +++ b/plugins/techdocs/src/reader/transformers/handleMetaRedirects.test.ts @@ -21,21 +21,13 @@ import { screen } from '@testing-library/react'; describe('handleMetaRedirects', () => { const navigate = jest.fn(); - const setUpNewTestShadowDom = async ( - html: string, - rootHref: string, - rootPath: string, - ) => { + const setUpNewTestShadowDom = async (html: string, rootHref: string) => { const entityName = 'testEntity'; - // Mock window.location.href for each test - Object.defineProperty(window, 'location', { - value: { - href: rootHref, - pathname: rootPath, - hostname: 'localhost', - }, - writable: true, - }); + // Use history.replaceState to change location (jsdom 27+ doesn't allow redefining location) + // Jest's jsdom starts at http://localhost/, so replaceState updates the pathname while + // keeping hostname and origin as 'localhost'. + const url = new URL(rootHref); + history.replaceState(null, '', `${url.pathname}${url.search}${url.hash}`); return await createTestShadowDom(html, { preTransformers: [], postTransformers: [handleMetaRedirects(navigate, entityName)], @@ -55,7 +47,6 @@ describe('handleMetaRedirects', () => { await setUpNewTestShadowDom( ``, 'http://localhost/docs/default/component/testEntity/subpath', - '/docs/default/component/testEntity/subpath', ); expect( @@ -73,7 +64,6 @@ describe('handleMetaRedirects', () => { await setUpNewTestShadowDom( ``, 'http://localhost/docs/default/component/testEntity/subpath', - '/docs/default/component/testEntity/subpath', ); expect( @@ -91,7 +81,6 @@ describe('handleMetaRedirects', () => { await setUpNewTestShadowDom( ``, 'http://localhost/docs/default/component/testEntity/subpath', - '/docs/default/component/testEntity/subpath', ); expect( @@ -107,7 +96,6 @@ describe('handleMetaRedirects', () => { await setUpNewTestShadowDom( ``, 'http://localhost/docs/default/component/testEntity/subpath', - '/docs/default/component/testEntity/subpath', ); jest.runAllTimers(); diff --git a/plugins/user-settings-backend/CHANGELOG.md b/plugins/user-settings-backend/CHANGELOG.md index 57d1f676c4..166490f4e9 100644 --- a/plugins/user-settings-backend/CHANGELOG.md +++ b/plugins/user-settings-backend/CHANGELOG.md @@ -1,5 +1,43 @@ # @backstage/plugin-user-settings-backend +## 0.3.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.14.1-next.0 + - @backstage/backend-plugin-api@1.6.0 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-auth-node@0.6.10 + - @backstage/plugin-signals-node@0.1.27 + - @backstage/plugin-user-settings-common@0.0.1 + +## 0.3.9 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/plugin-auth-node@0.6.10 + - @backstage/backend-defaults@0.14.0 + - @backstage/plugin-signals-node@0.1.27 + - @backstage/backend-plugin-api@1.6.0 + +## 0.3.9-next.1 + +### Patch Changes + +- de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0 +- Updated dependencies + - @backstage/backend-defaults@0.14.0-next.1 + - @backstage/plugin-auth-node@0.6.10-next.1 + - @backstage/plugin-signals-node@0.1.27-next.1 + - @backstage/backend-plugin-api@1.6.0-next.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.2 + - @backstage/plugin-user-settings-common@0.0.1 + ## 0.3.9-next.0 ### Patch Changes diff --git a/plugins/user-settings-backend/package.json b/plugins/user-settings-backend/package.json index 4a744fca45..53689197fc 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.3.9-next.0", + "version": "0.3.10-next.0", "description": "The Backstage backend plugin to manage user settings", "backstage": { "role": "backend-plugin", diff --git a/plugins/user-settings/CHANGELOG.md b/plugins/user-settings/CHANGELOG.md index e28fb0427b..08368f5a3c 100644 --- a/plugins/user-settings/CHANGELOG.md +++ b/plugins/user-settings/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-user-settings +## 0.8.30 + +### Patch Changes + +- d02db50: Remove unnecessary use of `compatWrapper` and `convertLegacyRouteRef`(s) for the new frontend system. +- Updated dependencies + - @backstage/core-app-api@1.19.3 + - @backstage/frontend-plugin-api@0.13.2 + - @backstage/core-components@0.18.4 + - @backstage/plugin-catalog-react@1.21.4 + - @backstage/core-plugin-api@1.12.1 + - @backstage/theme@0.7.1 + - @backstage/plugin-signals-react@0.0.18 + ## 0.8.30-next.0 ### Patch Changes diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index ce73f21d5e..a920c248e7 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.30-next.0", + "version": "0.8.30", "description": "A Backstage plugin that provides a settings page", "backstage": { "role": "frontend-plugin", diff --git a/yarn.lock b/yarn.lock index 593cb10fd0..c9db21a76e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,6 +12,13 @@ __metadata: languageName: node linkType: hard +"@acemir/cssom@npm:^0.9.28": + version: 0.9.28 + resolution: "@acemir/cssom@npm:0.9.28" + checksum: 10/429faa2af7bffdcf3311e984f6b8ced77bf58d936e0e9a22c2fc892a84e54d2c8cbd71ae3a979ef54241509ac7c866cb880d919e3e713e64c865a1cd4ede3a1f + languageName: node + linkType: hard + "@adobe/css-tools@npm:^4.4.0": version: 4.4.0 resolution: "@adobe/css-tools@npm:4.4.0" @@ -263,6 +270,52 @@ __metadata: languageName: node linkType: hard +"@asamuzakjp/css-color@npm:^3.2.0": + version: 3.2.0 + resolution: "@asamuzakjp/css-color@npm:3.2.0" + dependencies: + "@csstools/css-calc": "npm:^2.1.3" + "@csstools/css-color-parser": "npm:^3.0.9" + "@csstools/css-parser-algorithms": "npm:^3.0.4" + "@csstools/css-tokenizer": "npm:^3.0.3" + lru-cache: "npm:^10.4.3" + checksum: 10/870f661460173174fef8bfebea0799ba26566f3aa7b307e5adabb7aae84fed2da68e40080104ed0c83b43c5be632ee409e65396af13bfe948a3ef4c2c729ecd9 + languageName: node + linkType: hard + +"@asamuzakjp/css-color@npm:^4.1.0": + version: 4.1.0 + resolution: "@asamuzakjp/css-color@npm:4.1.0" + dependencies: + "@csstools/css-calc": "npm:^2.1.4" + "@csstools/css-color-parser": "npm:^3.1.0" + "@csstools/css-parser-algorithms": "npm:^3.0.5" + "@csstools/css-tokenizer": "npm:^3.0.4" + lru-cache: "npm:^11.2.2" + checksum: 10/e76b57fff34b958e224662d2afb19d23bc6c95d6ea40055e23a8f7417ae79904b7741655bbe6a883c09d5ee68ebb20e9313036aed3680fe85e383e0527397566 + languageName: node + linkType: hard + +"@asamuzakjp/dom-selector@npm:^6.7.6": + version: 6.7.6 + resolution: "@asamuzakjp/dom-selector@npm:6.7.6" + dependencies: + "@asamuzakjp/nwsapi": "npm:^2.3.9" + bidi-js: "npm:^1.0.3" + css-tree: "npm:^3.1.0" + is-potential-custom-element-name: "npm:^1.0.1" + lru-cache: "npm:^11.2.4" + checksum: 10/91a479f5f59a3b1b23f46407d874882c05b50e72316e57af105c88603fb1008120c46c7fe7504c5be556ea4c9a68ee10aee43433bd8d34f000b9aaf6dcae4d5c + languageName: node + linkType: hard + +"@asamuzakjp/nwsapi@npm:^2.3.9": + version: 2.3.9 + resolution: "@asamuzakjp/nwsapi@npm:2.3.9" + checksum: 10/95a6d1c102e1117fe818da087fcc5b914d23e0699855991bae50b891435dd1945ad7d384198f8bcf616207fd85b7ec32e3db6b96e9309d84c6903b8dc4151e34 + languageName: node + linkType: hard + "@asyncapi/avro-schema-parser@npm:^3.0.24": version: 3.0.24 resolution: "@asyncapi/avro-schema-parser@npm:3.0.24" @@ -314,25 +367,25 @@ __metadata: languageName: node linkType: hard -"@asyncapi/protobuf-schema-parser@npm:^3.5.1": - version: 3.5.1 - resolution: "@asyncapi/protobuf-schema-parser@npm:3.5.1" +"@asyncapi/protobuf-schema-parser@npm:^3.6.0": + version: 3.6.0 + resolution: "@asyncapi/protobuf-schema-parser@npm:3.6.0" dependencies: "@asyncapi/parser": "npm:^3.4.0" "@types/protocol-buffers-schema": "npm:^3.4.3" protobufjs: "npm:^7.4.0" - checksum: 10/dbef0c14080f0894e2d2ca1f5f233485e3cce3f37bf82e3412be50322bd16366812ab933f35e38c35ee453a29ae20e2d8a811a6921fc5631cb5caf0b59fd839a + checksum: 10/595b5daf8a6162a5c67ad86b95657064b29a2a2f34223b825a22496969d2cebf64ba1c23336cfc323e1e0ae6a42e8418aa66eea06d0479bfc6b679250fdb5833 languageName: node linkType: hard "@asyncapi/react-component@npm:^2.3.3": - version: 2.6.3 - resolution: "@asyncapi/react-component@npm:2.6.3" + version: 2.6.5 + resolution: "@asyncapi/react-component@npm:2.6.5" dependencies: "@asyncapi/avro-schema-parser": "npm:^3.0.24" "@asyncapi/openapi-schema-parser": "npm:^3.0.24" "@asyncapi/parser": "npm:^3.3.0" - "@asyncapi/protobuf-schema-parser": "npm:^3.5.1" + "@asyncapi/protobuf-schema-parser": "npm:^3.6.0" highlight.js: "npm:^10.7.2" isomorphic-dompurify: "npm:^2.14.0" marked: "npm:^4.0.14" @@ -342,7 +395,7 @@ __metadata: peerDependencies: react: ">=18.0.0" react-dom: ">=18.0.0" - checksum: 10/7105385f8f806200638f10b799ff1a5d1838041d20d14c6e64b1e1a411933727b91cd3957c2057bc7946524be01c8ab7bb03946886534b15f4767c277da38445 + checksum: 10/3af09244a8bf59aefadc0dcf7203865a964af014869b3e9f952be9655127fcca5d151c252b15b1b8acbf266ef239a70ac50b588d1040a876694b5345964560e7 languageName: node linkType: hard @@ -2238,7 +2291,7 @@ __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.24.2, @babel/code-frame@npm:^7.27.1, @babel/code-frame@npm:^7.8.3": +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.16.0, @babel/code-frame@npm:^7.16.7, @babel/code-frame@npm:^7.27.1, @babel/code-frame@npm:^7.8.3": version: 7.27.1 resolution: "@babel/code-frame@npm:7.27.1" dependencies: @@ -2256,39 +2309,39 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.24.7, @babel/core@npm:^7.28.0": - version: 7.28.4 - resolution: "@babel/core@npm:7.28.4" +"@babel/core@npm:^7.23.9, @babel/core@npm:^7.24.7, @babel/core@npm:^7.27.4, @babel/core@npm:^7.28.0": + version: 7.28.5 + resolution: "@babel/core@npm:7.28.5" dependencies: "@babel/code-frame": "npm:^7.27.1" - "@babel/generator": "npm:^7.28.3" + "@babel/generator": "npm:^7.28.5" "@babel/helper-compilation-targets": "npm:^7.27.2" "@babel/helper-module-transforms": "npm:^7.28.3" "@babel/helpers": "npm:^7.28.4" - "@babel/parser": "npm:^7.28.4" + "@babel/parser": "npm:^7.28.5" "@babel/template": "npm:^7.27.2" - "@babel/traverse": "npm:^7.28.4" - "@babel/types": "npm:^7.28.4" + "@babel/traverse": "npm:^7.28.5" + "@babel/types": "npm:^7.28.5" "@jridgewell/remapping": "npm:^2.3.5" convert-source-map: "npm:^2.0.0" debug: "npm:^4.1.0" gensync: "npm:^1.0.0-beta.2" json5: "npm:^2.2.3" semver: "npm:^6.3.1" - checksum: 10/0593295241fac9be567145ef16f3858d34fc91390a9438c6d47476be9823af4cc0488c851c59702dd46b968e9fd46d17ddf0105ea30195ca85f5a66b4044c519 + checksum: 10/2f1e224125179f423f4300d605a0c5a3ef315003281a63b1744405b2605ee2a2ffc5b1a8349aa4f262c72eca31c7e1802377ee04ad2b852a2c88f8ace6cac324 languageName: node linkType: hard -"@babel/generator@npm:^7.28.3, @babel/generator@npm:^7.7.2": - version: 7.28.3 - resolution: "@babel/generator@npm:7.28.3" +"@babel/generator@npm:^7.27.5, @babel/generator@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/generator@npm:7.28.5" dependencies: - "@babel/parser": "npm:^7.28.3" - "@babel/types": "npm:^7.28.2" + "@babel/parser": "npm:^7.28.5" + "@babel/types": "npm:^7.28.5" "@jridgewell/gen-mapping": "npm:^0.3.12" "@jridgewell/trace-mapping": "npm:^0.3.28" jsesc: "npm:^3.0.2" - checksum: 10/d00d1e6b51059e47594aab7920b88ec6fcef6489954a9172235ab57ad2e91b39c95376963a6e2e4cc7e8b88fa4f931018f71f9ab32bbc9c0bc0de35a0231f26c + checksum: 10/ae618f0a17a6d76c3983e1fd5d9c2f5fdc07703a119efdb813a7d9b8ad4be0a07d4c6f0d718440d2de01a68e321f64e2d63c77fc5d43ae47ae143746ef28ac1f languageName: node linkType: hard @@ -2380,10 +2433,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.24.7, @babel/helper-plugin-utils@npm:^7.24.8, @babel/helper-plugin-utils@npm:^7.25.9, @babel/helper-plugin-utils@npm:^7.8.0": - version: 7.25.9 - resolution: "@babel/helper-plugin-utils@npm:7.25.9" - checksum: 10/e347d87728b1ab10b6976d46403941c8f9008c045ea6d99997a7ffca7b852dc34b6171380f7b17edf94410e0857ff26f3a53d8618f11d73744db86e8ca9b8c64 +"@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.24.7, @babel/helper-plugin-utils@npm:^7.24.8, @babel/helper-plugin-utils@npm:^7.27.1, @babel/helper-plugin-utils@npm:^7.8.0": + version: 7.27.1 + resolution: "@babel/helper-plugin-utils@npm:7.27.1" + checksum: 10/96136c2428888e620e2ec493c25888f9ceb4a21099dcf3dd4508ea64b58cdedbd5a9fb6c7b352546de84d6c24edafe482318646932a22c449ebd16d16c22d864 languageName: node linkType: hard @@ -2427,10 +2480,10 @@ __metadata: languageName: node linkType: hard -"@babel/helper-validator-identifier@npm:^7.24.7, @babel/helper-validator-identifier@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-validator-identifier@npm:7.27.1" - checksum: 10/75041904d21bdc0cd3b07a8ac90b11d64cd3c881e89cb936fa80edd734bf23c35e6bd1312611e8574c4eab1f3af0f63e8a5894f4699e9cfdf70c06fcf4252320 +"@babel/helper-validator-identifier@npm:^7.24.7, @babel/helper-validator-identifier@npm:^7.27.1, @babel/helper-validator-identifier@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/helper-validator-identifier@npm:7.28.5" + checksum: 10/8e5d9b0133702cfacc7f368bf792f0f8ac0483794877c6dca5fcb73810ee138e27527701826fb58a40a004f3a5ec0a2f3c3dd5e326d262530b119918f3132ba7 languageName: node linkType: hard @@ -2463,14 +2516,14 @@ __metadata: 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.24.7, @babel/parser@npm:^7.26.7, @babel/parser@npm:^7.27.2, @babel/parser@npm:^7.27.5, @babel/parser@npm:^7.28.3, @babel/parser@npm:^7.28.4": - version: 7.28.4 - resolution: "@babel/parser@npm:7.28.4" +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.24.7, @babel/parser@npm:^7.26.7, @babel/parser@npm:^7.27.2, @babel/parser@npm:^7.27.5, @babel/parser@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/parser@npm:7.28.5" dependencies: - "@babel/types": "npm:^7.28.4" + "@babel/types": "npm:^7.28.5" bin: parser: ./bin/babel-parser.js - checksum: 10/f54c46213ef180b149f6a17ea765bf40acc1aebe2009f594e2a283aec69a190c6dda1fdf24c61a258dbeb903abb8ffb7a28f1a378f8ab5d333846ce7b7e23bf1 + checksum: 10/8d9bfb437af6c97a7f6351840b9ac06b4529ba79d6d3def24d6c2996ab38ff7f1f9d301e868ca84a93a3050fadb3d09dbc5105b24634cd281671ac11eebe8df7 languageName: node linkType: hard @@ -2496,7 +2549,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-class-properties@npm:^7.8.3": +"@babel/plugin-syntax-class-properties@npm:^7.12.13": version: 7.12.13 resolution: "@babel/plugin-syntax-class-properties@npm:7.12.13" dependencies: @@ -2507,6 +2560,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-syntax-class-static-block@npm:^7.14.5": + version: 7.14.5 + resolution: "@babel/plugin-syntax-class-static-block@npm:7.14.5" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.14.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/3e80814b5b6d4fe17826093918680a351c2d34398a914ce6e55d8083d72a9bdde4fbaf6a2dcea0e23a03de26dc2917ae3efd603d27099e2b98380345703bf948 + languageName: node + linkType: hard + "@babel/plugin-syntax-flow@npm:^7.24.7": version: 7.24.7 resolution: "@babel/plugin-syntax-flow@npm:7.24.7" @@ -2518,7 +2582,18 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-import-meta@npm:^7.8.3": +"@babel/plugin-syntax-import-attributes@npm:^7.24.7": + version: 7.27.1 + resolution: "@babel/plugin-syntax-import-attributes@npm:7.27.1" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/97973982fff1bbf86b3d1df13380567042887c50e2ae13a400d02a8ff2c9742a60a75e279bfb73019e1cd9710f04be5e6ab81f896e6678dcfcec8b135e8896cf + languageName: node + linkType: hard + +"@babel/plugin-syntax-import-meta@npm:^7.10.4": version: 7.10.4 resolution: "@babel/plugin-syntax-import-meta@npm:7.10.4" dependencies: @@ -2540,18 +2615,18 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-jsx@npm:^7.24.7, @babel/plugin-syntax-jsx@npm:^7.7.2": - version: 7.24.7 - resolution: "@babel/plugin-syntax-jsx@npm:7.24.7" +"@babel/plugin-syntax-jsx@npm:^7.24.7, @babel/plugin-syntax-jsx@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/plugin-syntax-jsx@npm:7.27.1" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.27.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10/a93516ae5b34868ab892a95315027d4e5e38e8bd1cfca6158f2974b0901cbb32bbe64ea10ad5b25f919ddc40c6d8113c4823372909c9c9922170c12b0b1acecb + checksum: 10/c6d1324cff286a369aa95d99b8abd21dd07821b5d3affd5fe7d6058c84cff9190743287826463ee57a7beecd10fa1e4bc99061df532ee14e188c1c8937b13e3a languageName: node linkType: hard -"@babel/plugin-syntax-logical-assignment-operators@npm:^7.8.3": +"@babel/plugin-syntax-logical-assignment-operators@npm:^7.10.4": version: 7.10.4 resolution: "@babel/plugin-syntax-logical-assignment-operators@npm:7.10.4" dependencies: @@ -2573,7 +2648,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-numeric-separator@npm:^7.8.3": +"@babel/plugin-syntax-numeric-separator@npm:^7.10.4": version: 7.10.4 resolution: "@babel/plugin-syntax-numeric-separator@npm:7.10.4" dependencies: @@ -2617,7 +2692,18 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-top-level-await@npm:^7.8.3": +"@babel/plugin-syntax-private-property-in-object@npm:^7.14.5": + version: 7.14.5 + resolution: "@babel/plugin-syntax-private-property-in-object@npm:7.14.5" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.14.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/b317174783e6e96029b743ccff2a67d63d38756876e7e5d0ba53a322e38d9ca452c13354a57de1ad476b4c066dbae699e0ca157441da611117a47af88985ecda + languageName: node + linkType: hard + +"@babel/plugin-syntax-top-level-await@npm:^7.14.5": version: 7.14.5 resolution: "@babel/plugin-syntax-top-level-await@npm:7.14.5" dependencies: @@ -2628,14 +2714,14 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-typescript@npm:^7.24.7, @babel/plugin-syntax-typescript@npm:^7.7.2": - version: 7.25.9 - resolution: "@babel/plugin-syntax-typescript@npm:7.25.9" +"@babel/plugin-syntax-typescript@npm:^7.24.7, @babel/plugin-syntax-typescript@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/plugin-syntax-typescript@npm:7.27.1" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.9" + "@babel/helper-plugin-utils": "npm:^7.27.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10/0e9821e8ba7d660c36c919654e4144a70546942ae184e85b8102f2322451eae102cbfadbcadd52ce077a2b44b400ee52394c616feab7b5b9f791b910e933fd33 + checksum: 10/87836f7e32af624c2914c73cd6b9803cf324e07d43f61dbb973c6a86f75df725e12540d91fac7141c14b697aa9268fd064220998daced156e96ac3062d7afb41 languageName: node linkType: hard @@ -2780,14 +2866,14 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.18.6, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.20.6, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.23.9, @babel/runtime@npm:^7.26.0, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.4.4, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.0, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": +"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.18.6, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.20.6, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.23.9, @babel/runtime@npm:^7.26.0, @babel/runtime@npm:^7.28.4, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.4.4, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.0, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": version: 7.28.4 resolution: "@babel/runtime@npm:7.28.4" checksum: 10/6c9a70452322ea80b3c9b2a412bcf60771819213a67576c8cec41e88a95bb7bf01fc983754cda35dc19603eef52df22203ccbf7777b9d6316932f9fb77c25163 languageName: node linkType: hard -"@babel/template@npm:^7.27.2, @babel/template@npm:^7.3.3": +"@babel/template@npm:^7.27.2": version: 7.27.2 resolution: "@babel/template@npm:7.27.2" dependencies: @@ -2798,28 +2884,28 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.24.7, @babel/traverse@npm:^7.24.8, @babel/traverse@npm:^7.25.0, @babel/traverse@npm:^7.25.4, @babel/traverse@npm:^7.27.1, @babel/traverse@npm:^7.28.0, @babel/traverse@npm:^7.28.3, @babel/traverse@npm:^7.28.4, @babel/traverse@npm:^7.4.5": - version: 7.28.4 - resolution: "@babel/traverse@npm:7.28.4" +"@babel/traverse@npm:^7.24.7, @babel/traverse@npm:^7.24.8, @babel/traverse@npm:^7.25.0, @babel/traverse@npm:^7.25.4, @babel/traverse@npm:^7.27.1, @babel/traverse@npm:^7.28.0, @babel/traverse@npm:^7.28.3, @babel/traverse@npm:^7.28.5, @babel/traverse@npm:^7.4.5": + version: 7.28.5 + resolution: "@babel/traverse@npm:7.28.5" dependencies: "@babel/code-frame": "npm:^7.27.1" - "@babel/generator": "npm:^7.28.3" + "@babel/generator": "npm:^7.28.5" "@babel/helper-globals": "npm:^7.28.0" - "@babel/parser": "npm:^7.28.4" + "@babel/parser": "npm:^7.28.5" "@babel/template": "npm:^7.27.2" - "@babel/types": "npm:^7.28.4" + "@babel/types": "npm:^7.28.5" debug: "npm:^4.3.1" - checksum: 10/c3099364b7b1c36bcd111099195d4abeef16499e5defb1e56766b754e8b768c252e856ed9041665158aa1b31215fc6682632756803c8fa53405381ec08c4752b + checksum: 10/1fce426f5ea494913c40f33298ce219708e703f71cac7ac045ebde64b5a7b17b9275dfa4e05fb92c3f123136913dff62c8113172f4a5de66dab566123dbe7437 languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.24.7, @babel/types@npm:^7.24.8, @babel/types@npm:^7.27.1, @babel/types@npm:^7.28.2, @babel/types@npm:^7.28.4, @babel/types@npm:^7.3.3": - version: 7.28.4 - resolution: "@babel/types@npm:7.28.4" +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.24.7, @babel/types@npm:^7.24.8, @babel/types@npm:^7.27.1, @babel/types@npm:^7.27.3, @babel/types@npm:^7.28.2, @babel/types@npm:^7.28.4, @babel/types@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/types@npm:7.28.5" dependencies: "@babel/helper-string-parser": "npm:^7.27.1" - "@babel/helper-validator-identifier": "npm:^7.27.1" - checksum: 10/db50bf257aafa5d845ad16dae0587f57d596e4be4cbb233ea539976a4c461f9fbcc0bf3d37adae3f8ce5dcb4001462aa608f3558161258b585f6ce6ce21a2e45 + "@babel/helper-validator-identifier": "npm:^7.28.5" + checksum: 10/4256bb9fb2298c4f9b320bde56e625b7091ea8d2433d98dcf524d4086150da0b6555aabd7d0725162670614a9ac5bf036d1134ca13dedc9707f988670f1362d7 languageName: node linkType: hard @@ -3212,6 +3298,7 @@ __metadata: "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" "@backstage/types": "workspace:^" + "@jest/environment-jsdom-abstract": "npm:^30.0.0" "@manypkg/get-packages": "npm:^1.1.3" "@module-federation/enhanced": "npm:^0.9.0" "@octokit/request": "npm:^8.0.0" @@ -3226,16 +3313,16 @@ __metadata: "@spotify/eslint-config-base": "npm:^15.0.0" "@spotify/eslint-config-react": "npm:^15.0.0" "@spotify/eslint-config-typescript": "npm:^15.0.0" - "@swc/core": "npm:^1.3.46" - "@swc/helpers": "npm:^0.5.0" - "@swc/jest": "npm:^0.2.22" + "@swc/core": "npm:^1.15.6" + "@swc/helpers": "npm:^0.5.17" + "@swc/jest": "npm:^0.2.39" "@types/cross-spawn": "npm:^6.0.2" "@types/ejs": "npm:^3.1.3" "@types/express": "npm:^4.17.6" "@types/fs-extra": "npm:^11.0.0" "@types/http-proxy": "npm:^1.17.4" "@types/inquirer": "npm:^8.1.3" - "@types/jest": "npm:^29.5.11" + "@types/jest": "npm:^30.0.0" "@types/node": "npm:^22.13.14" "@types/npm-packlist": "npm:^3.0.0" "@types/recursive-readdir": "npm:^2.2.0" @@ -3285,11 +3372,9 @@ __metadata: handlebars: "npm:^4.7.3" html-webpack-plugin: "npm:^5.6.3" inquirer: "npm:^8.2.0" - jest: "npm:^29.7.0" - jest-cli: "npm:^29.7.0" + jest: "npm:^30.2.0" jest-css-modules: "npm:^2.1.0" - jest-environment-jsdom: "npm:^29.0.2" - jest-runtime: "npm:^29.0.2" + jsdom: "npm:^27.1.0" json-schema: "npm:^0.4.0" lodash: "npm:^4.17.21" mini-css-extract-plugin: "npm:^2.4.2" @@ -3332,16 +3417,22 @@ __metadata: zod: "npm:^3.22.4" zod-validation-error: "npm:^3.4.0" peerDependencies: + "@jest/environment-jsdom-abstract": ^30.0.0 "@module-federation/enhanced": ^0.9.0 "@pmmmwh/react-refresh-webpack-plugin": ^0.6.0 esbuild-loader: ^4.0.0 eslint-webpack-plugin: ^4.2.0 fork-ts-checker-webpack-plugin: ^9.0.0 + jest: ^29.0.0 || ^30.0.0 + jest-environment-jsdom: "*" + jsdom: ^27.1.0 mini-css-extract-plugin: ^2.4.2 terser-webpack-plugin: ^5.1.3 webpack: ~5.103.0 webpack-dev-server: ^5.0.0 peerDependenciesMeta: + "@jest/environment-jsdom-abstract": + optional: true "@module-federation/enhanced": optional: true "@pmmmwh/react-refresh-webpack-plugin": @@ -3352,6 +3443,10 @@ __metadata: optional: true fork-ts-checker-webpack-plugin: optional: true + jest-environment-jsdom: + optional: true + jsdom: + optional: true mini-css-extract-plugin: optional: true terser-webpack-plugin: @@ -3403,7 +3498,7 @@ __metadata: json-schema-traverse: "npm:^1.0.0" lodash: "npm:^4.17.21" minimist: "npm:^1.2.5" - msw: "npm:^1.0.0" + msw: "npm:^2.0.0" typescript-json-schema: "npm:^0.67.0" yaml: "npm:^2.0.0" zen-observable: "npm:^0.10.0" @@ -3819,19 +3914,16 @@ __metadata: dependencies: "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" - "@backstage/core-components": "workspace:^" "@backstage/errors": "workspace:^" "@backstage/frontend-app-api": "workspace:^" "@backstage/frontend-test-utils": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/types": "workspace:^" "@backstage/version-bridge": "workspace:^" - "@material-ui/core": "npm:^4.12.4" "@testing-library/jest-dom": "npm:^6.0.0" "@testing-library/react": "npm:^16.0.0" "@types/react": "npm:^18.0.0" history: "npm:^5.3.0" - lodash: "npm:^4.17.21" react: "npm:^18.0.2" react-dom: "npm:^18.0.2" react-router-dom: "npm:^6.3.0" @@ -5321,6 +5413,7 @@ __metadata: resolution: "@backstage/plugin-catalog-unprocessed-entities@workspace:plugins/catalog-unprocessed-entities" dependencies: "@backstage/cli": "workspace:^" + "@backstage/core-compat-api": "workspace:^" "@backstage/core-components": "workspace:^" "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" @@ -5520,6 +5613,7 @@ __metadata: resolution: "@backstage/plugin-devtools@workspace:plugins/devtools" dependencies: "@backstage/cli": "workspace:^" + "@backstage/core-compat-api": "workspace:^" "@backstage/core-components": "workspace:^" "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" @@ -5532,7 +5626,9 @@ __metadata: "@material-ui/icons": "npm:^4.9.1" "@material-ui/lab": "npm:^4.0.0-alpha.57" "@testing-library/jest-dom": "npm:^6.0.0" + "@types/lodash": "npm:^4.14.151" "@types/react": "npm:^18.0.0" + lodash: "npm:^4.17.21" react: "npm:^18.0.2" react-dom: "npm:^18.0.2" react-json-view: "npm:^1.21.3" @@ -5730,7 +5826,7 @@ __metadata: content-type: "npm:^1.0.5" cross-fetch: "npm:^4.0.0" express: "npm:^4.22.0" - msw: "npm:^1.0.0" + msw: "npm:^2.0.0" uri-template: "npm:^2.0.0" languageName: unknown linkType: soft @@ -5747,7 +5843,7 @@ __metadata: "@opentelemetry/api": "npm:^1.9.0" "@opentelemetry/core": "npm:^1.29.0" "@types/express": "npm:^4.17.6" - eventsource: "npm:^3.0.6" + eventsource: "npm:^4.0.0" express: "npm:^4.22.0" http-proxy-middleware: "npm:^3.0.3" wait-for-expect: "npm:^3.0.2" @@ -5978,7 +6074,7 @@ __metadata: kubernetes-models: "npm:^4.3.1" lodash: "npm:^4.17.21" luxon: "npm:^3.0.0" - msw: "npm:^1.3.1" + msw: "npm:^2.0.0" react: "npm:^18.0.2" react-dom: "npm:^18.0.2" react-router-dom: "npm:^6.3.0" @@ -6040,7 +6136,8 @@ __metadata: "@backstage/errors": "workspace:^" "@backstage/plugin-catalog-node": "workspace:^" "@backstage/types": "workspace:^" - "@modelcontextprotocol/sdk": "npm:^1.12.3" + "@cfworker/json-schema": "npm:^4.1.1" + "@modelcontextprotocol/sdk": "npm:^1.24.3" "@types/express": "npm:^4.17.6" express: "npm:^4.22.0" express-promise-router: "npm:^4.1.0" @@ -6118,7 +6215,7 @@ __metadata: "@backstage/plugin-notifications-node": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/types": "workspace:^" - "@faker-js/faker": "npm:^8.4.1" + "@faker-js/faker": "npm:^10.0.0" "@opentelemetry/api": "npm:^1.9.0" "@slack/bolt": "npm:^3.21.4" "@slack/types": "npm:^2.14.0" @@ -7875,7 +7972,7 @@ __metadata: "@types/react-dom": "npm:^18.0.0" chalk: "npm:^5.4.1" clsx: "npm:^2.1.1" - eslint-plugin-storybook: "npm:^9.1.7" + eslint-plugin-storybook: "npm:^10.1.9" glob: "npm:^11.0.1" globals: "npm:^15.11.0" lightningcss: "npm:^1.29.1" @@ -7884,7 +7981,7 @@ __metadata: react-aria-components: "npm:^1.13.0" react-dom: "npm:^18.0.2" react-router-dom: "npm:^6.3.0" - storybook: "npm:^9.1.7" + storybook: "npm:^10.1.10" peerDependencies: "@types/react": ^17.0.0 || ^18.0.0 react: ^17.0.0 || ^18.0.0 @@ -7950,11 +8047,18 @@ __metadata: languageName: node linkType: hard -"@changesets/apply-release-plan@npm:^7.0.12": - version: 7.0.12 - resolution: "@changesets/apply-release-plan@npm:7.0.12" +"@cfworker/json-schema@npm:^4.1.1": + version: 4.1.1 + resolution: "@cfworker/json-schema@npm:4.1.1" + checksum: 10/62fd08bb2e6b4f0fe7c2b8f8c19f17f94b6a34feba7f455f228898ab435eda8aae082fcf6b0fe8a235a72e0ec0041922fdcd4c526acc32d45084272f000c1af9 + languageName: node + linkType: hard + +"@changesets/apply-release-plan@npm:^7.0.14": + version: 7.0.14 + resolution: "@changesets/apply-release-plan@npm:7.0.14" dependencies: - "@changesets/config": "npm:^3.1.1" + "@changesets/config": "npm:^3.1.2" "@changesets/get-version-range-type": "npm:^0.4.0" "@changesets/git": "npm:^3.0.4" "@changesets/should-skip-package": "npm:^0.1.2" @@ -7967,7 +8071,7 @@ __metadata: prettier: "npm:^2.7.1" resolve-from: "npm:^5.0.0" semver: "npm:^7.5.3" - checksum: 10/3ce05caa73b7b96a8a6be943507591925c44b22f209da001fb9d83df1d7a4569659e889373f5f7a208a121b3cf7bc17788969b8849bddaf13c27d6720e4e1c47 + checksum: 10/7735783734bddd6d628e3a18c6de253685504c18f580636979fe558dda88501c8e4bda28c34a2f9da96f80fae0d1228271857d86fff6045226ce04b18d8b98b6 languageName: node linkType: hard @@ -7995,28 +8099,28 @@ __metadata: linkType: hard "@changesets/cli@npm:^2.14.0": - version: 2.29.5 - resolution: "@changesets/cli@npm:2.29.5" + version: 2.29.8 + resolution: "@changesets/cli@npm:2.29.8" dependencies: - "@changesets/apply-release-plan": "npm:^7.0.12" + "@changesets/apply-release-plan": "npm:^7.0.14" "@changesets/assemble-release-plan": "npm:^6.0.9" "@changesets/changelog-git": "npm:^0.2.1" - "@changesets/config": "npm:^3.1.1" + "@changesets/config": "npm:^3.1.2" "@changesets/errors": "npm:^0.2.0" "@changesets/get-dependents-graph": "npm:^2.1.3" - "@changesets/get-release-plan": "npm:^4.0.13" + "@changesets/get-release-plan": "npm:^4.0.14" "@changesets/git": "npm:^3.0.4" "@changesets/logger": "npm:^0.1.1" "@changesets/pre": "npm:^2.0.2" - "@changesets/read": "npm:^0.6.5" + "@changesets/read": "npm:^0.6.6" "@changesets/should-skip-package": "npm:^0.1.2" "@changesets/types": "npm:^6.1.0" "@changesets/write": "npm:^0.4.0" + "@inquirer/external-editor": "npm:^1.0.2" "@manypkg/get-packages": "npm:^1.1.3" ansi-colors: "npm:^4.1.3" ci-info: "npm:^3.7.0" enquirer: "npm:^2.4.1" - external-editor: "npm:^3.1.0" fs-extra: "npm:^7.0.1" mri: "npm:^1.2.0" p-limit: "npm:^2.2.0" @@ -8028,13 +8132,13 @@ __metadata: term-size: "npm:^2.1.0" bin: changeset: bin.js - checksum: 10/f401da29025d7bcc07b732bb09a9627f785bfc21c7c2005861d11ffea732bc14d33394fc2fcae50cc5f2b710f6080c5babe2fa90d432de5fdb47ae6afc147936 + checksum: 10/1169d97d7d0b86fdeb778aadc1ffa3e46c840345c97b4cdbe90e5fc0168d0d0870001d66f6676537716a2d22c147a84e8a120f1298156419dc6a662681861af5 languageName: node linkType: hard -"@changesets/config@npm:^3.1.1": - version: 3.1.1 - resolution: "@changesets/config@npm:3.1.1" +"@changesets/config@npm:^3.1.2": + version: 3.1.2 + resolution: "@changesets/config@npm:3.1.2" dependencies: "@changesets/errors": "npm:^0.2.0" "@changesets/get-dependents-graph": "npm:^2.1.3" @@ -8043,7 +8147,7 @@ __metadata: "@manypkg/get-packages": "npm:^1.1.3" fs-extra: "npm:^7.0.1" micromatch: "npm:^4.0.8" - checksum: 10/9500e02b68801f052478b3e10523bd3a39b9e5e989e718832832537c9da965580f496262c2bc3f6e23a4e6fb4303f730a69dcbf2041f68d2fa7bd03dd1f82db0 + checksum: 10/c35626240c0af83433808216be48cc39dd0b27d20a7d3bbb95c0da0044a08207986678dae97f081cc524abf8351e0303890794a28e8c67f17036bd88013b2576 languageName: node linkType: hard @@ -8068,17 +8172,17 @@ __metadata: languageName: node linkType: hard -"@changesets/get-release-plan@npm:^4.0.13": - version: 4.0.13 - resolution: "@changesets/get-release-plan@npm:4.0.13" +"@changesets/get-release-plan@npm:^4.0.14": + version: 4.0.14 + resolution: "@changesets/get-release-plan@npm:4.0.14" dependencies: "@changesets/assemble-release-plan": "npm:^6.0.9" - "@changesets/config": "npm:^3.1.1" + "@changesets/config": "npm:^3.1.2" "@changesets/pre": "npm:^2.0.2" - "@changesets/read": "npm:^0.6.5" + "@changesets/read": "npm:^0.6.6" "@changesets/types": "npm:^6.1.0" "@manypkg/get-packages": "npm:^1.1.3" - checksum: 10/9983fae5a68012c4c418ddd62f2fb3d325363f21160252ff7b868503a1a2effb8fdd32e4a0289b72653afc3605ce19d163ff69205c942a0004efb571a5f78fd0 + checksum: 10/0b54f4e34dc27aa9df928488bf84f3d6a2b516701985d06b49306d45b87b48e642aef3de751f9517de4c1b88011b5826975aa85f8ba596da1f9681a5d1699093 languageName: node linkType: hard @@ -8111,13 +8215,13 @@ __metadata: languageName: node linkType: hard -"@changesets/parse@npm:^0.4.1": - version: 0.4.1 - resolution: "@changesets/parse@npm:0.4.1" +"@changesets/parse@npm:^0.4.2": + version: 0.4.2 + resolution: "@changesets/parse@npm:0.4.2" dependencies: "@changesets/types": "npm:^6.1.0" - js-yaml: "npm:^3.13.1" - checksum: 10/2973ab8f38592a80efea589e148e5bdfd6ed3af86aa9206f941b5b3955f68464bf70a5965349f642667c708ebae60e4266be538328cd27075cace3f7cc1022e3 + js-yaml: "npm:^4.1.1" + checksum: 10/d45d7f5d7a0aeede197935f16bb459479c8d0b16ebe89ceaf4bd58b307ef1be696bcc5d5fc33d5b64a80dec946b49f6107af32d57d91967e6b3f9013a0d53740 languageName: node linkType: hard @@ -8133,18 +8237,18 @@ __metadata: languageName: node linkType: hard -"@changesets/read@npm:^0.6.5": - version: 0.6.5 - resolution: "@changesets/read@npm:0.6.5" +"@changesets/read@npm:^0.6.6": + version: 0.6.6 + resolution: "@changesets/read@npm:0.6.6" dependencies: "@changesets/git": "npm:^3.0.4" "@changesets/logger": "npm:^0.1.1" - "@changesets/parse": "npm:^0.4.1" + "@changesets/parse": "npm:^0.4.2" "@changesets/types": "npm:^6.1.0" fs-extra: "npm:^7.0.1" p-filter: "npm:^2.1.0" picocolors: "npm:^1.1.0" - checksum: 10/fec0ac28801e0560fae0eb1d21250dd2a48aaff67bddd1b446a960afd761690d5873dca6eff369d43763bec61f1023d38a38876d5824e316e6de622dc52a24f3 + checksum: 10/3ac0cf24159b0e0fea4339d0a01c57459a6b7796f868dca7db65727c3dd33ead38b78f224b677cf7b50bb7b96fa3d0b155843e800a524b435a772c9ed21fa914 languageName: node linkType: hard @@ -8214,8 +8318,8 @@ __metadata: linkType: hard "@codemirror/language@npm:^6.0.0": - version: 6.11.2 - resolution: "@codemirror/language@npm:6.11.2" + version: 6.11.3 + resolution: "@codemirror/language@npm:6.11.3" dependencies: "@codemirror/state": "npm:^6.0.0" "@codemirror/view": "npm:^6.23.0" @@ -8223,16 +8327,16 @@ __metadata: "@lezer/highlight": "npm:^1.0.0" "@lezer/lr": "npm:^1.0.0" style-mod: "npm:^4.0.0" - checksum: 10/6ecccc48ad4390fca94525eefd0f4c904effad285e1d1de0db3764f08fd33299e5e453ab4d9ff8c33b4baeeb95f4a78660152ab64255fd19eccd31142410f6ed + checksum: 10/8538a2835c1de6ca2d520ff66449185f2ea3a93e7d69382d9db3b4db6460f4c46b44f19724458c50230abfa87cf2c225834d39c3fe3119c48370db6b3de0b772 languageName: node linkType: hard "@codemirror/legacy-modes@npm:^6.1.0": - version: 6.5.1 - resolution: "@codemirror/legacy-modes@npm:6.5.1" + version: 6.5.2 + resolution: "@codemirror/legacy-modes@npm:6.5.2" dependencies: "@codemirror/language": "npm:^6.0.0" - checksum: 10/585de2a47a4ac10b3f96ef1616c849167cc6bae2a337a58a9a85c094cb95c4c27b8429c6bf2edf6a072946eb65b8169d090333003592c0b1ad0a51bc5a438c2a + checksum: 10/b10c6e876f9cac4946c3a4ab0a49a637a08fc2c39a06392261a652c6a68f654e4525d472b649bf171426e916920ef68ec0e5fb81c2bc244ce5143a915fce0338 languageName: node linkType: hard @@ -8280,14 +8384,14 @@ __metadata: linkType: hard "@codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.23.0": - version: 6.38.1 - resolution: "@codemirror/view@npm:6.38.1" + version: 6.38.8 + resolution: "@codemirror/view@npm:6.38.8" dependencies: "@codemirror/state": "npm:^6.5.0" crelt: "npm:^1.0.6" style-mod: "npm:^4.1.0" w3c-keyname: "npm:^2.2.4" - checksum: 10/e0c5a365608749dd096ba7a930c8393f316bf4c2cacd1465a47a057d0a9f9868ff372a0bb6eb696c926f88411139f79a97a05f8c884bcc380145445cc61e68c8 + checksum: 10/81b1508015a378e4719d0239254173f0c5cd340c2abf96eb488fe5fb474bdb37ec1f010b9890ced774accd7aeb9443e7337cb6a89544b954273e5ddabece7cea languageName: node linkType: hard @@ -8307,23 +8411,78 @@ __metadata: languageName: node linkType: hard -"@dabh/diagnostics@npm:^2.0.2": - version: 2.0.2 - resolution: "@dabh/diagnostics@npm:2.0.2" +"@csstools/color-helpers@npm:^5.1.0": + version: 5.1.0 + resolution: "@csstools/color-helpers@npm:5.1.0" + checksum: 10/0138b3d5ccbe77aeccf6721fd008a53523c70e932f0c82dca24a1277ca780447e1d8357da47512ebf96358476f8764de57002f3e491920d67e69202f5a74c383 + languageName: node + linkType: hard + +"@csstools/css-calc@npm:^2.1.3, @csstools/css-calc@npm:^2.1.4": + version: 2.1.4 + resolution: "@csstools/css-calc@npm:2.1.4" + peerDependencies: + "@csstools/css-parser-algorithms": ^3.0.5 + "@csstools/css-tokenizer": ^3.0.4 + checksum: 10/06975b650c0f44c60eeb7afdb3fd236f2dd607b2c622e0bc908d3f54de39eb84e0692833320d03dac04bd6c1ab0154aa3fa0dd442bd9e5f917cf14d8e2ba8d74 + languageName: node + linkType: hard + +"@csstools/css-color-parser@npm:^3.0.9, @csstools/css-color-parser@npm:^3.1.0": + version: 3.1.0 + resolution: "@csstools/css-color-parser@npm:3.1.0" dependencies: - colorspace: "npm:1.1.x" + "@csstools/color-helpers": "npm:^5.1.0" + "@csstools/css-calc": "npm:^2.1.4" + peerDependencies: + "@csstools/css-parser-algorithms": ^3.0.5 + "@csstools/css-tokenizer": ^3.0.4 + checksum: 10/4741095fdc4501e8e7ada4ed14fbf9dbbe6fea9b989818790ebca15657c29c62defbebacf18592cde2aa638a1d098bbe86d742d2c84ba932fbc00fac51cb8805 + languageName: node + linkType: hard + +"@csstools/css-parser-algorithms@npm:^3.0.4, @csstools/css-parser-algorithms@npm:^3.0.5": + version: 3.0.5 + resolution: "@csstools/css-parser-algorithms@npm:3.0.5" + peerDependencies: + "@csstools/css-tokenizer": ^3.0.4 + checksum: 10/e93083b5cb36a3c1e7a47ce10cf62961d05bd1e4c608bb3ee50186ff740157ab0ec16a3956f7b86251efd10703034d849693201eea858ae904848c68d2d46ada + languageName: node + linkType: hard + +"@csstools/css-syntax-patches-for-csstree@npm:1.0.14": + version: 1.0.14 + resolution: "@csstools/css-syntax-patches-for-csstree@npm:1.0.14" + peerDependencies: + postcss: ^8.4 + checksum: 10/c783d5db307552f483d95266452a7765ca138a9e64f12d013c63e960c9c8abbf82c899a34028af1f5ad714e0e94edd97b1aa31784923c1d7d1756d775c3c1d0a + languageName: node + linkType: hard + +"@csstools/css-tokenizer@npm:^3.0.3, @csstools/css-tokenizer@npm:^3.0.4": + version: 3.0.4 + resolution: "@csstools/css-tokenizer@npm:3.0.4" + checksum: 10/eb6c84c086312f6bb8758dfe2c85addd7475b0927333c5e39a4d59fb210b9810f8c346972046f95e60a721329cffe98895abe451e51de753ad1ca7a8c24ec65f + languageName: node + linkType: hard + +"@dabh/diagnostics@npm:^2.0.8": + version: 2.0.8 + resolution: "@dabh/diagnostics@npm:2.0.8" + dependencies: + "@so-ric/colorspace": "npm:^1.1.6" enabled: "npm:2.0.x" kuler: "npm:^2.0.0" - checksum: 10/d0c7ae32da9fc6061272ef56cf2c5af9c255e034783b68cfe3b0d47e806145d0723e6f5743e4c9fc0abae73658ca309498572688da2fbcfc56c16a8671dbe707 + checksum: 10/ac2267a4ee1874f608493f21d386ea29f0acac6716124e26e3e48e01ce5706b095585a14adce1bee14b6567d3b8fdd0c5a0bbb7ab0e15c9a743d55eb02f093ce languageName: node linkType: hard "@dagrejs/dagre@npm:^1.1.4": - version: 1.1.5 - resolution: "@dagrejs/dagre@npm:1.1.5" + version: 1.1.8 + resolution: "@dagrejs/dagre@npm:1.1.8" dependencies: "@dagrejs/graphlib": "npm:2.2.4" - checksum: 10/c00abd1e04d19f90ad8dfa0a4e16365371bc4309affead3827a1b39f6b0b946643b8af0b1e5519011deca3fda4c7471b27e9ebb03423309a94f95ac0b881ac4f + checksum: 10/648f60b8d6c05ec3367d1c7a4f2da32b7c26273e40234ce37bace606cd1e4f882ef7947452a0f0df4b34f1bbbc9f3cbae29f0f6af19fbffb8bc9f5e9b97fc3e8 languageName: node linkType: hard @@ -8386,14 +8545,14 @@ __metadata: linkType: hard "@elastic/elasticsearch@npm:^7.13.0": - version: 7.17.0 - resolution: "@elastic/elasticsearch@npm:7.17.0" + version: 7.17.14 + resolution: "@elastic/elasticsearch@npm:7.17.14" dependencies: debug: "npm:^4.3.1" hpagent: "npm:^0.1.1" ms: "npm:^2.1.3" secure-json-parse: "npm:^2.4.0" - checksum: 10/d54330ce50b4951b7b9db15349413b4961040fb0b73a09d3f07cef5cb2873fd22af17307e07b6c8b1b1e0844e76e9aeb78ce1e01d67a940e3190763a875648be + checksum: 10/ef26489eb8db667f0a6c2be4641e9b388bc5badd2ab7791eb82dffa138653642678f7e6ab2741b914747e95e0d43bf9daa0821bc509318c14cb40869cc9ebbc9 languageName: node linkType: hard @@ -8405,37 +8564,37 @@ __metadata: linkType: hard "@electric-sql/pglite@npm:^0.3.0": - version: 0.3.7 - resolution: "@electric-sql/pglite@npm:0.3.7" - checksum: 10/e76b99a06bdba55c3249f2e4fc17fce043460509943b73c14c2ad558854ff4cc752ccb8d438cd7340866b76b3031e3bc37085032decfbaaf871dcd9d07d732df + version: 0.3.14 + resolution: "@electric-sql/pglite@npm:0.3.14" + checksum: 10/7cd072cd6a5c4314b47e7d26cc2ac191fcca5ba204f3bb1908bdb34746e51315cbde3e53646020d6a7c19c087d7845d2908850d9f4312285be10b3aefe28d621 languageName: node linkType: hard -"@emnapi/core@npm:^1.4.5": - version: 1.4.5 - resolution: "@emnapi/core@npm:1.4.5" +"@emnapi/core@npm:^1.4.3, @emnapi/core@npm:^1.5.0, @emnapi/core@npm:^1.7.1": + version: 1.7.1 + resolution: "@emnapi/core@npm:1.7.1" dependencies: - "@emnapi/wasi-threads": "npm:1.0.4" + "@emnapi/wasi-threads": "npm:1.1.0" tslib: "npm:^2.4.0" - checksum: 10/412322102dc861e8aa78123ae20560ac980362a220c736fe59ddea3228d490757780ea4cdc3bd54903a5ca2a92085f119e42f2c07f60e2aec2c0b8a69ea094c0 + checksum: 10/260841f6dd2a7823a964d9de6da3a5e6f565dac8d21a5bd8f6215b87c45c22a4dc371b9ad877961579ee3cca8a76e55e3dd033ae29cba1998999cda6d794bdab languageName: node linkType: hard -"@emnapi/runtime@npm:^1.4.5": - version: 1.4.5 - resolution: "@emnapi/runtime@npm:1.4.5" +"@emnapi/runtime@npm:^1.4.3, @emnapi/runtime@npm:^1.5.0, @emnapi/runtime@npm:^1.7.1": + version: 1.7.1 + resolution: "@emnapi/runtime@npm:1.7.1" dependencies: tslib: "npm:^2.4.0" - checksum: 10/1d6f406ff116d2363e60aef3ed49eb8d577387f4941abea508ba376900d8831609d5cce92a58076b1a9613f8e83c75c2e3fea71e4fbcdbe06019876144c2559b + checksum: 10/6fc83f938e3c70e32e84c1fbe5cab6cb9340b8107cee4048384ad5b8f2998a06502b4bed342acaf6e44f473f2c14c4ab1e3fd5083bd7823fc63abfca9eff0175 languageName: node linkType: hard -"@emnapi/wasi-threads@npm:1.0.4": - version: 1.0.4 - resolution: "@emnapi/wasi-threads@npm:1.0.4" +"@emnapi/wasi-threads@npm:1.1.0": + version: 1.1.0 + resolution: "@emnapi/wasi-threads@npm:1.1.0" dependencies: tslib: "npm:^2.4.0" - checksum: 10/86688f416095b59d8d3e5ea2d8b5574a7c180257fe0c067c7a492f3de2cf5ebc2c8b00af17d6341c7555c614266d3987f332015d7ce6e88b234a9a314e66f396 + checksum: 10/0d557e75262d2f4c95cb2a456ba0785ef61f919ce488c1d76e5e3acfd26e00c753ef928cd80068363e0c166ba8cc0141305daf0f81aad5afcd421f38f11e0f4e languageName: node linkType: hard @@ -8458,7 +8617,7 @@ __metadata: languageName: node linkType: hard -"@emotion/cache@npm:^11.13.5": +"@emotion/cache@npm:^11.13.5, @emotion/cache@npm:^11.14.0": version: 11.14.0 resolution: "@emotion/cache@npm:11.14.0" dependencies: @@ -8518,14 +8677,14 @@ __metadata: linkType: hard "@emotion/react@npm:^11.10.5": - version: 11.13.5 - resolution: "@emotion/react@npm:11.13.5" + version: 11.14.0 + resolution: "@emotion/react@npm:11.14.0" dependencies: "@babel/runtime": "npm:^7.18.3" "@emotion/babel-plugin": "npm:^11.13.5" - "@emotion/cache": "npm:^11.13.5" + "@emotion/cache": "npm:^11.14.0" "@emotion/serialize": "npm:^1.3.3" - "@emotion/use-insertion-effect-with-fallbacks": "npm:^1.1.0" + "@emotion/use-insertion-effect-with-fallbacks": "npm:^1.2.0" "@emotion/utils": "npm:^1.4.2" "@emotion/weak-memoize": "npm:^0.4.0" hoist-non-react-statics: "npm:^3.3.1" @@ -8534,7 +8693,7 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 10/c85bde9c6144be6f243e44d6834b16df8151b91c5136ea28d9d917155d64d1bbfba000ae98866fd9f5089546f0b0655c20b9e4280cdc5ccf39acc4a2fde37a39 + checksum: 10/3356c1d66f37f4e7abf88a2be843f6023b794b286c9c99a0aaf1cd1b2b7c50f8d80a2ef77183da737de70150f638e698ff4a2a38ab2d922f868615f1d5761c37 languageName: node linkType: hard @@ -8559,14 +8718,14 @@ __metadata: linkType: hard "@emotion/styled@npm:^11.10.5": - version: 11.13.5 - resolution: "@emotion/styled@npm:11.13.5" + version: 11.14.1 + resolution: "@emotion/styled@npm:11.14.1" dependencies: "@babel/runtime": "npm:^7.18.3" "@emotion/babel-plugin": "npm:^11.13.5" "@emotion/is-prop-valid": "npm:^1.3.0" "@emotion/serialize": "npm:^1.3.3" - "@emotion/use-insertion-effect-with-fallbacks": "npm:^1.1.0" + "@emotion/use-insertion-effect-with-fallbacks": "npm:^1.2.0" "@emotion/utils": "npm:^1.4.2" peerDependencies: "@emotion/react": ^11.0.0-rc.0 @@ -8574,7 +8733,7 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 10/cf6c47f9e9292b817aaec4e34cedc996727318018b621525576a1f541cfb3ecf2443729bfba503d4467d8183ca7732fe817bd7202386f4206a9d218e6e2202d8 + checksum: 10/b20ffaaac76e16538051da8d417f1da75f47f0974000edf0999f39f309b23ee0a91ba7dc1d5f60c4017d29fadfed48631ae4a8f697e3662a88318c667d072117 languageName: node linkType: hard @@ -8599,12 +8758,12 @@ __metadata: languageName: node linkType: hard -"@emotion/use-insertion-effect-with-fallbacks@npm:^1.1.0": - version: 1.1.0 - resolution: "@emotion/use-insertion-effect-with-fallbacks@npm:1.1.0" +"@emotion/use-insertion-effect-with-fallbacks@npm:^1.2.0": + version: 1.2.0 + resolution: "@emotion/use-insertion-effect-with-fallbacks@npm:1.2.0" peerDependencies: react: ">=16.8.0" - checksum: 10/33a10f44a873b3f5ccd2a1a3d13c2f34ed628f5a2be1ccf28540a86535a14d3a930afcbef209d48346a22ec60ff48f43c86ee9c846b9480d23a55a17145da66c + checksum: 10/2374999db8d53ef661d61ed1026c42a849632e4f03826f7eba0314c1d92ae342161d737f5045453aa46dd4008e13ccefeba68d3165b667dfad8e5784fcb0c643 languageName: node linkType: hard @@ -8622,13 +8781,6 @@ __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/aix-ppc64@npm:0.25.8": version: 0.25.8 resolution: "@esbuild/aix-ppc64@npm:0.25.8" @@ -8643,13 +8795,6 @@ __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-arm64@npm:0.25.8": version: 0.25.8 resolution: "@esbuild/android-arm64@npm:0.25.8" @@ -8664,13 +8809,6 @@ __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-arm@npm:0.25.8": version: 0.25.8 resolution: "@esbuild/android-arm@npm:0.25.8" @@ -8685,13 +8823,6 @@ __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/android-x64@npm:0.25.8": version: 0.25.8 resolution: "@esbuild/android-x64@npm:0.25.8" @@ -8706,13 +8837,6 @@ __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-arm64@npm:0.25.8": version: 0.25.8 resolution: "@esbuild/darwin-arm64@npm:0.25.8" @@ -8727,13 +8851,6 @@ __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/darwin-x64@npm:0.25.8": version: 0.25.8 resolution: "@esbuild/darwin-x64@npm:0.25.8" @@ -8748,13 +8865,6 @@ __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-arm64@npm:0.25.8": version: 0.25.8 resolution: "@esbuild/freebsd-arm64@npm:0.25.8" @@ -8769,13 +8879,6 @@ __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/freebsd-x64@npm:0.25.8": version: 0.25.8 resolution: "@esbuild/freebsd-x64@npm:0.25.8" @@ -8790,13 +8893,6 @@ __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-arm64@npm:0.25.8": version: 0.25.8 resolution: "@esbuild/linux-arm64@npm:0.25.8" @@ -8811,13 +8907,6 @@ __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-arm@npm:0.25.8": version: 0.25.8 resolution: "@esbuild/linux-arm@npm:0.25.8" @@ -8832,13 +8921,6 @@ __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-ia32@npm:0.25.8": version: 0.25.8 resolution: "@esbuild/linux-ia32@npm:0.25.8" @@ -8853,13 +8935,6 @@ __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-loong64@npm:0.25.8": version: 0.25.8 resolution: "@esbuild/linux-loong64@npm:0.25.8" @@ -8874,13 +8949,6 @@ __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-mips64el@npm:0.25.8": version: 0.25.8 resolution: "@esbuild/linux-mips64el@npm:0.25.8" @@ -8895,13 +8963,6 @@ __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-ppc64@npm:0.25.8": version: 0.25.8 resolution: "@esbuild/linux-ppc64@npm:0.25.8" @@ -8916,13 +8977,6 @@ __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-riscv64@npm:0.25.8": version: 0.25.8 resolution: "@esbuild/linux-riscv64@npm:0.25.8" @@ -8937,13 +8991,6 @@ __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-s390x@npm:0.25.8": version: 0.25.8 resolution: "@esbuild/linux-s390x@npm:0.25.8" @@ -8958,13 +9005,6 @@ __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/linux-x64@npm:0.25.8": version: 0.25.8 resolution: "@esbuild/linux-x64@npm:0.25.8" @@ -8993,13 +9033,6 @@ __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/netbsd-x64@npm:0.25.8": version: 0.25.8 resolution: "@esbuild/netbsd-x64@npm:0.25.8" @@ -9028,13 +9061,6 @@ __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/openbsd-x64@npm:0.25.8": version: 0.25.8 resolution: "@esbuild/openbsd-x64@npm:0.25.8" @@ -9063,13 +9089,6 @@ __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/sunos-x64@npm:0.25.8": version: 0.25.8 resolution: "@esbuild/sunos-x64@npm:0.25.8" @@ -9084,13 +9103,6 @@ __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-arm64@npm:0.25.8": version: 0.25.8 resolution: "@esbuild/win32-arm64@npm:0.25.8" @@ -9105,13 +9117,6 @@ __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-ia32@npm:0.25.8": version: 0.25.8 resolution: "@esbuild/win32-ia32@npm:0.25.8" @@ -9126,13 +9131,6 @@ __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 - "@esbuild/win32-x64@npm:0.25.8": version: 0.25.8 resolution: "@esbuild/win32-x64@npm:0.25.8" @@ -9196,10 +9194,10 @@ __metadata: languageName: node linkType: hard -"@faker-js/faker@npm:^8.4.1": - version: 8.4.1 - resolution: "@faker-js/faker@npm:8.4.1" - checksum: 10/5983c2ea64f26055ad6648de748878e11ebe2fb751e3c7435ae141cdffabc2dccfe4c4f49da69a3d2add71e21b415c683ac5fba196fab0d5ed6779fbec436c80 +"@faker-js/faker@npm:^10.0.0": + version: 10.1.0 + resolution: "@faker-js/faker@npm:10.1.0" + checksum: 10/3332795debec5793dfaea79e740ed44bd7d94fb43cea8b1bd5d59af19f15c4a9533fa696cfebf024a9bba5d9d1a8a28cde40a92670c03cc11170a3025e551e65 languageName: node linkType: hard @@ -9306,16 +9304,16 @@ __metadata: languageName: node linkType: hard -"@gerrit0/mini-shiki@npm:^3.9.0": - version: 3.9.1 - resolution: "@gerrit0/mini-shiki@npm:3.9.1" +"@gerrit0/mini-shiki@npm:^3.17.0": + version: 3.17.1 + resolution: "@gerrit0/mini-shiki@npm:3.17.1" dependencies: - "@shikijs/engine-oniguruma": "npm:^3.9.1" - "@shikijs/langs": "npm:^3.9.1" - "@shikijs/themes": "npm:^3.9.1" - "@shikijs/types": "npm:^3.9.1" + "@shikijs/engine-oniguruma": "npm:^3.17.1" + "@shikijs/langs": "npm:^3.17.1" + "@shikijs/themes": "npm:^3.17.1" + "@shikijs/types": "npm:^3.17.1" "@shikijs/vscode-textmate": "npm:^10.0.2" - checksum: 10/4ef9c7f24866d2d1e802df085698140fd359d144eafc081d9599b8be73f3606fc1c1870ec5ce240e201a7a34cd959e15cff322469d211cfb299e34733e65c1ed + checksum: 10/efcf8bea95911dc645c76b90aba2ed0898efa42ec068774c77f5272343aa421dbb72b08f7ce40df90f3223e56c21af185021a81b43a34bd73be248100dc3a21c languageName: node linkType: hard @@ -9386,14 +9384,14 @@ __metadata: linkType: hard "@google-cloud/cloud-sql-connector@npm:^1.4.0": - version: 1.8.2 - resolution: "@google-cloud/cloud-sql-connector@npm:1.8.2" + version: 1.8.5 + resolution: "@google-cloud/cloud-sql-connector@npm:1.8.5" dependencies: - "@googleapis/sqladmin": "npm:^31.0.0" - gaxios: "npm:^7.0.0" - google-auth-library: "npm:^10.0.0" + "@googleapis/sqladmin": "npm:^31.1.0" + gaxios: "npm:^7.1.3" + google-auth-library: "npm:^10.5.0" p-throttle: "npm:^7.0.0" - checksum: 10/a9e8113f6b252e93ebdac2901c47584fa2c50d4ff0ad7ce1e1beb8ac8c710b24543927b2231eeb0f74eb467e122ec313ba3fb845d6f5878d35760eb3021aa6ec + checksum: 10/38be5d2a32d68d2c3ef8b56c94c9eda299266a742fa2beecb9e907f27117bf1af25af5881195fa21da167b12dfdd22f55662086e90448b8c02824875eeb2cc85 languageName: node linkType: hard @@ -9407,15 +9405,15 @@ __metadata: linkType: hard "@google-cloud/firestore@npm:^7.0.0": - version: 7.11.3 - resolution: "@google-cloud/firestore@npm:7.11.3" + version: 7.11.6 + resolution: "@google-cloud/firestore@npm:7.11.6" dependencies: "@opentelemetry/api": "npm:^1.3.0" fast-deep-equal: "npm:^3.1.1" functional-red-black-tree: "npm:^1.0.1" google-gax: "npm:^4.3.3" protobufjs: "npm:^7.2.6" - checksum: 10/1d512e236b315daeb1cf562988a4b200e75abb7ba64a0d2be71815deae5662e81ca501a7dfaf9b9e81396e0d1f84f6f5b063da0029a98be9d7dfbc0afc2d06e0 + checksum: 10/89a421a0400be8aa862829c970a32b72d9dd23accacc14b31ff231203ebaa5764288ca098fa1e74b9b6e03e82af0f9ca7e7a38d323e63e3df7d2a1545022f444 languageName: node linkType: hard @@ -9443,7 +9441,7 @@ __metadata: languageName: node linkType: hard -"@google-cloud/promisify@npm:^4.0.0, @google-cloud/promisify@npm:~4.0.0": +"@google-cloud/promisify@npm:<4.1.0, @google-cloud/promisify@npm:~4.0.0": version: 4.0.0 resolution: "@google-cloud/promisify@npm:4.0.0" checksum: 10/c5de81321b3a5c567edcbe0b941fb32644611147f3ba22f20575918c225a979988a99bc2ebda05ac914fa8714b0a54c69be72c3f46c7a64c3b19db7d7fba8d04 @@ -9473,12 +9471,12 @@ __metadata: linkType: hard "@google-cloud/storage@npm:^7.0.0": - version: 7.14.0 - resolution: "@google-cloud/storage@npm:7.14.0" + version: 7.18.0 + resolution: "@google-cloud/storage@npm:7.18.0" dependencies: "@google-cloud/paginator": "npm:^5.0.0" "@google-cloud/projectify": "npm:^4.0.0" - "@google-cloud/promisify": "npm:^4.0.0" + "@google-cloud/promisify": "npm:<4.1.0" abort-controller: "npm:^3.0.0" async-retry: "npm:^1.3.3" duplexify: "npm:^4.1.3" @@ -9491,11 +9489,11 @@ __metadata: retry-request: "npm:^7.0.0" teeny-request: "npm:^9.0.0" uuid: "npm:^8.0.0" - checksum: 10/0726fde2697da696637fab91ebd756354a58c1331f6a0b9ecc5011de4aae72cd9e1fe3e9564aee15c6a2118e45ed0ae8c3ac9685c6581db6107080f906a949e9 + checksum: 10/29ca208cf88770dd60ac7868ec69bffa43e3cba03cbb49dd7064593f777e66181a8cba6f1993f36193f009be07bc02129d0ecac9f9f09f8a8b6a8d90a9e5ba86 languageName: node linkType: hard -"@googleapis/sqladmin@npm:^31.0.0": +"@googleapis/sqladmin@npm:^31.1.0": version: 31.1.0 resolution: "@googleapis/sqladmin@npm:31.1.0" dependencies: @@ -10010,7 +10008,7 @@ __metadata: languageName: node linkType: hard -"@inquirer/external-editor@npm:^1.0.0": +"@inquirer/external-editor@npm:^1.0.0, @inquirer/external-editor@npm:^1.0.2": version: 1.0.3 resolution: "@inquirer/external-editor@npm:1.0.3" dependencies: @@ -10054,7 +10052,6 @@ __metadata: "@backstage/version-bridge": "workspace:^" "@testing-library/jest-dom": "npm:^6.0.0" "@testing-library/react": "npm:^16.0.0" - zod: "npm:^3.22.4" languageName: unknown linkType: soft @@ -10289,10 +10286,10 @@ __metadata: languageName: node linkType: hard -"@istanbuljs/schema@npm:^0.1.2": - version: 0.1.2 - resolution: "@istanbuljs/schema@npm:0.1.2" - checksum: 10/e4a7fffc72fb2cfe2edfee8a09f68b2da18b1ab328a29d8be2933681f9e36103f0b083a5ae07129f4de26296eb7c2a1cc144cfea6cdb47f871a69766947144d3 +"@istanbuljs/schema@npm:^0.1.2, @istanbuljs/schema@npm:^0.1.3": + version: 0.1.3 + resolution: "@istanbuljs/schema@npm:0.1.3" + checksum: 10/a9b1e49acdf5efc2f5b2359f2df7f90c5c725f2656f16099e8b2cd3a000619ecca9fc48cf693ba789cf0fd989f6e0df6a22bc05574be4223ecdbb7997d04384b languageName: node linkType: hard @@ -10305,161 +10302,214 @@ __metadata: languageName: node linkType: hard -"@jest/console@npm:^29.7.0": - version: 29.7.0 - resolution: "@jest/console@npm:29.7.0" +"@jest/console@npm:30.2.0": + version: 30.2.0 + resolution: "@jest/console@npm:30.2.0" dependencies: - "@jest/types": "npm:^29.6.3" + "@jest/types": "npm:30.2.0" "@types/node": "npm:*" - chalk: "npm:^4.0.0" - jest-message-util: "npm:^29.7.0" - jest-util: "npm:^29.7.0" + chalk: "npm:^4.1.2" + jest-message-util: "npm:30.2.0" + jest-util: "npm:30.2.0" slash: "npm:^3.0.0" - checksum: 10/4a80c750e8a31f344233cb9951dee9b77bf6b89377cb131f8b3cde07ff218f504370133a5963f6a786af4d2ce7f85642db206ff7a15f99fe58df4c38ac04899e + checksum: 10/7cda9793962afa5c7fcfdde0ff5012694683b17941ee3c6a55ea9fd9a02f1c51ec4b4c767b867e1226f85a26af1d0f0d72c6a344e34c5bc4300312ebffd6e50b languageName: node linkType: hard -"@jest/core@npm:^29.7.0": - version: 29.7.0 - resolution: "@jest/core@npm:29.7.0" +"@jest/core@npm:30.2.0": + version: 30.2.0 + resolution: "@jest/core@npm:30.2.0" dependencies: - "@jest/console": "npm:^29.7.0" - "@jest/reporters": "npm:^29.7.0" - "@jest/test-result": "npm:^29.7.0" - "@jest/transform": "npm:^29.7.0" - "@jest/types": "npm:^29.6.3" + "@jest/console": "npm:30.2.0" + "@jest/pattern": "npm:30.0.1" + "@jest/reporters": "npm:30.2.0" + "@jest/test-result": "npm:30.2.0" + "@jest/transform": "npm:30.2.0" + "@jest/types": "npm:30.2.0" "@types/node": "npm:*" - ansi-escapes: "npm:^4.2.1" - chalk: "npm:^4.0.0" - ci-info: "npm:^3.2.0" - exit: "npm:^0.1.2" - graceful-fs: "npm:^4.2.9" - jest-changed-files: "npm:^29.7.0" - jest-config: "npm:^29.7.0" - jest-haste-map: "npm:^29.7.0" - jest-message-util: "npm:^29.7.0" - jest-regex-util: "npm:^29.6.3" - jest-resolve: "npm:^29.7.0" - jest-resolve-dependencies: "npm:^29.7.0" - jest-runner: "npm:^29.7.0" - jest-runtime: "npm:^29.7.0" - jest-snapshot: "npm:^29.7.0" - jest-util: "npm:^29.7.0" - jest-validate: "npm:^29.7.0" - jest-watcher: "npm:^29.7.0" - micromatch: "npm:^4.0.4" - pretty-format: "npm:^29.7.0" + ansi-escapes: "npm:^4.3.2" + chalk: "npm:^4.1.2" + ci-info: "npm:^4.2.0" + exit-x: "npm:^0.2.2" + graceful-fs: "npm:^4.2.11" + jest-changed-files: "npm:30.2.0" + jest-config: "npm:30.2.0" + jest-haste-map: "npm:30.2.0" + jest-message-util: "npm:30.2.0" + jest-regex-util: "npm:30.0.1" + jest-resolve: "npm:30.2.0" + jest-resolve-dependencies: "npm:30.2.0" + jest-runner: "npm:30.2.0" + jest-runtime: "npm:30.2.0" + jest-snapshot: "npm:30.2.0" + jest-util: "npm:30.2.0" + jest-validate: "npm:30.2.0" + jest-watcher: "npm:30.2.0" + micromatch: "npm:^4.0.8" + pretty-format: "npm:30.2.0" slash: "npm:^3.0.0" - strip-ansi: "npm:^6.0.0" peerDependencies: node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 peerDependenciesMeta: node-notifier: optional: true - checksum: 10/ab6ac2e562d083faac7d8152ec1cc4eccc80f62e9579b69ed40aedf7211a6b2d57024a6cd53c4e35fd051c39a236e86257d1d99ebdb122291969a0a04563b51e + checksum: 10/6763bb1efd937778f009821cd94c3705d3c31a156258a224b8745c1e0887976683f5413745ffb361b526f0fa2692e36aaa963aa197cc77ba932cff9d6d28af9d languageName: node linkType: hard -"@jest/create-cache-key-function@npm:^29.7.0": - version: 29.7.0 - resolution: "@jest/create-cache-key-function@npm:29.7.0" +"@jest/create-cache-key-function@npm:^30.0.0": + version: 30.2.0 + resolution: "@jest/create-cache-key-function@npm:30.2.0" dependencies: - "@jest/types": "npm:^29.6.3" - checksum: 10/061ef63b13ec8c8e5d08e4456f03b5cf8c7f9c1cab4fed8402e1479153cafce6eea80420e308ef62027abb7e29b825fcfa06551856bd021d98e92e381bf91723 + "@jest/types": "npm:30.2.0" + checksum: 10/7a2dd0efe747c1b2e61825e51ace11e42f278203fae37a3b9462c8d2132394978682ed7094f5ce3d9f5a9e5f2855e6d1d933e5f3ac5165b127c36591f3d98d85 languageName: node linkType: hard -"@jest/environment@npm:^29.7.0": - version: 29.7.0 - resolution: "@jest/environment@npm:29.7.0" +"@jest/diff-sequences@npm:30.0.1": + version: 30.0.1 + resolution: "@jest/diff-sequences@npm:30.0.1" + checksum: 10/0ddb7c7ba92d6057a2ee51a9cfc2155b77cca707fe959167466ea02dcb0687018cc3c22b9622f25f3a417d6ad370e2d4dcfedf9f1410dc9c02954a7484423cc7 + languageName: node + linkType: hard + +"@jest/environment-jsdom-abstract@npm:^30.0.0": + version: 30.2.0 + resolution: "@jest/environment-jsdom-abstract@npm:30.2.0" dependencies: - "@jest/fake-timers": "npm:^29.7.0" - "@jest/types": "npm:^29.6.3" + "@jest/environment": "npm:30.2.0" + "@jest/fake-timers": "npm:30.2.0" + "@jest/types": "npm:30.2.0" + "@types/jsdom": "npm:^21.1.7" "@types/node": "npm:*" - jest-mock: "npm:^29.7.0" - checksum: 10/90b5844a9a9d8097f2cf107b1b5e57007c552f64315da8c1f51217eeb0a9664889d3f145cdf8acf23a84f4d8309a6675e27d5b059659a004db0ea9546d1c81a8 + jest-mock: "npm:30.2.0" + jest-util: "npm:30.2.0" + peerDependencies: + canvas: ^3.0.0 + jsdom: "*" + peerDependenciesMeta: + canvas: + optional: true + checksum: 10/65a9c8504f213f4d125956383ffe6c4e566cfb0ff2fe67783adf9ebde33f772339e61fdd98ddc2bbae3029e3356d2386abedb9d101aa95d6fd51fabac38bebe0 languageName: node linkType: hard -"@jest/expect-utils@npm:^29.7.0": - version: 29.7.0 - resolution: "@jest/expect-utils@npm:29.7.0" +"@jest/environment@npm:30.2.0": + version: 30.2.0 + resolution: "@jest/environment@npm:30.2.0" dependencies: - jest-get-type: "npm:^29.6.3" - checksum: 10/ef8d379778ef574a17bde2801a6f4469f8022a46a5f9e385191dc73bb1fc318996beaed4513fbd7055c2847227a1bed2469977821866534593a6e52a281499ee - languageName: node - linkType: hard - -"@jest/expect@npm:^29.7.0": - version: 29.7.0 - resolution: "@jest/expect@npm:29.7.0" - dependencies: - expect: "npm:^29.7.0" - jest-snapshot: "npm:^29.7.0" - checksum: 10/fea6c3317a8da5c840429d90bfe49d928e89c9e89fceee2149b93a11b7e9c73d2f6e4d7cdf647163da938fc4e2169e4490be6bae64952902bc7a701033fd4880 - languageName: node - linkType: hard - -"@jest/fake-timers@npm:^29.7.0": - version: 29.7.0 - resolution: "@jest/fake-timers@npm:29.7.0" - dependencies: - "@jest/types": "npm:^29.6.3" - "@sinonjs/fake-timers": "npm:^10.0.2" + "@jest/fake-timers": "npm:30.2.0" + "@jest/types": "npm:30.2.0" "@types/node": "npm:*" - jest-message-util: "npm:^29.7.0" - jest-mock: "npm:^29.7.0" - jest-util: "npm:^29.7.0" - checksum: 10/9b394e04ffc46f91725ecfdff34c4e043eb7a16e1d78964094c9db3fde0b1c8803e45943a980e8c740d0a3d45661906de1416ca5891a538b0660481a3a828c27 + jest-mock: "npm:30.2.0" + checksum: 10/e168a4ff328980eb9fde5e43aea80807fd0b2dbd4579ae8f68a03415a1e58adf5661db298054fa2351c7cb2b5a74bf67b8ab996656cf5927d0b0d0b6e2c2966b languageName: node linkType: hard -"@jest/globals@npm:^29.7.0": - version: 29.7.0 - resolution: "@jest/globals@npm:29.7.0" +"@jest/expect-utils@npm:30.2.0": + version: 30.2.0 + resolution: "@jest/expect-utils@npm:30.2.0" dependencies: - "@jest/environment": "npm:^29.7.0" - "@jest/expect": "npm:^29.7.0" - "@jest/types": "npm:^29.6.3" - jest-mock: "npm:^29.7.0" - checksum: 10/97dbb9459135693ad3a422e65ca1c250f03d82b2a77f6207e7fa0edd2c9d2015fbe4346f3dc9ebff1678b9d8da74754d4d440b7837497f8927059c0642a22123 + "@jest/get-type": "npm:30.1.0" + checksum: 10/f2442f1bceb3411240d0f16fd0074377211b4373d3b8b2dc28929e861b6527a6deb403a362c25afa511d933cda4dfbdc98d4a08eeb51ee4968f7cb0299562349 languageName: node linkType: hard -"@jest/reporters@npm:^29.7.0": - version: 29.7.0 - resolution: "@jest/reporters@npm:29.7.0" +"@jest/expect@npm:30.2.0": + version: 30.2.0 + resolution: "@jest/expect@npm:30.2.0" + dependencies: + expect: "npm:30.2.0" + jest-snapshot: "npm:30.2.0" + checksum: 10/d950d95a64d5c6a39d56171dabb8dbe59423096231bb4f21d8ee0019878e6626701ac9d782803dc2589e2799ed39704031f818533f8a3e571b57032eafa85d12 + languageName: node + linkType: hard + +"@jest/fake-timers@npm:30.2.0": + version: 30.2.0 + resolution: "@jest/fake-timers@npm:30.2.0" + dependencies: + "@jest/types": "npm:30.2.0" + "@sinonjs/fake-timers": "npm:^13.0.0" + "@types/node": "npm:*" + jest-message-util: "npm:30.2.0" + jest-mock: "npm:30.2.0" + jest-util: "npm:30.2.0" + checksum: 10/c2df66576ba8049b07d5f239777243e21fcdaa09a446be1e55fac709d6273e2a926c1562e0372c3013142557ed9d386381624023549267a667b6e1b656e37fe6 + languageName: node + linkType: hard + +"@jest/get-type@npm:30.1.0": + version: 30.1.0 + resolution: "@jest/get-type@npm:30.1.0" + checksum: 10/e2a95fbb49ce2d15547db8af5602626caf9b05f62a5e583b4a2de9bd93a2bfe7175f9bbb2b8a5c3909ce261d467b6991d7265bb1d547cb60e7e97f571f361a70 + languageName: node + linkType: hard + +"@jest/globals@npm:30.2.0": + version: 30.2.0 + resolution: "@jest/globals@npm:30.2.0" + dependencies: + "@jest/environment": "npm:30.2.0" + "@jest/expect": "npm:30.2.0" + "@jest/types": "npm:30.2.0" + jest-mock: "npm:30.2.0" + checksum: 10/d4a331d3847cebb3acefe120350d8a6bb5517c1403de7cd2b4dc67be425f37ba0511beee77d6837b4da2d93a25a06d6f829ad7837da365fae45e1da57523525c + languageName: node + linkType: hard + +"@jest/pattern@npm:30.0.1": + version: 30.0.1 + resolution: "@jest/pattern@npm:30.0.1" + dependencies: + "@types/node": "npm:*" + jest-regex-util: "npm:30.0.1" + checksum: 10/afd03b4d3eadc9c9970cf924955dee47984a7e767901fe6fa463b17b246f0ddeec07b3e82c09715c54bde3c8abb92074160c0d79967bd23778724f184e7f5b7b + languageName: node + linkType: hard + +"@jest/reporters@npm:30.2.0": + version: 30.2.0 + resolution: "@jest/reporters@npm:30.2.0" dependencies: "@bcoe/v8-coverage": "npm:^0.2.3" - "@jest/console": "npm:^29.7.0" - "@jest/test-result": "npm:^29.7.0" - "@jest/transform": "npm:^29.7.0" - "@jest/types": "npm:^29.6.3" - "@jridgewell/trace-mapping": "npm:^0.3.18" + "@jest/console": "npm:30.2.0" + "@jest/test-result": "npm:30.2.0" + "@jest/transform": "npm:30.2.0" + "@jest/types": "npm:30.2.0" + "@jridgewell/trace-mapping": "npm:^0.3.25" "@types/node": "npm:*" - chalk: "npm:^4.0.0" - collect-v8-coverage: "npm:^1.0.0" - exit: "npm:^0.1.2" - glob: "npm:^7.1.3" - graceful-fs: "npm:^4.2.9" + chalk: "npm:^4.1.2" + collect-v8-coverage: "npm:^1.0.2" + exit-x: "npm:^0.2.2" + glob: "npm:^10.3.10" + graceful-fs: "npm:^4.2.11" istanbul-lib-coverage: "npm:^3.0.0" istanbul-lib-instrument: "npm:^6.0.0" istanbul-lib-report: "npm:^3.0.0" - istanbul-lib-source-maps: "npm:^4.0.0" + istanbul-lib-source-maps: "npm:^5.0.0" istanbul-reports: "npm:^3.1.3" - jest-message-util: "npm:^29.7.0" - jest-util: "npm:^29.7.0" - jest-worker: "npm:^29.7.0" + jest-message-util: "npm:30.2.0" + jest-util: "npm:30.2.0" + jest-worker: "npm:30.2.0" slash: "npm:^3.0.0" - string-length: "npm:^4.0.1" - strip-ansi: "npm:^6.0.0" + string-length: "npm:^4.0.2" v8-to-istanbul: "npm:^9.0.1" peerDependencies: node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 peerDependenciesMeta: node-notifier: optional: true - checksum: 10/a17d1644b26dea14445cedd45567f4ba7834f980be2ef74447204e14238f121b50d8b858fde648083d2cd8f305f81ba434ba49e37a5f4237a6f2a61180cc73dc + checksum: 10/3848b59bf740c10c4e5c234dcc41c54adbd74932bf05d1d1582d09d86e9baa86ddaf3c43903505fd042ba1203c2889a732137d08058ce9dc0069ba33b5d5373d + languageName: node + linkType: hard + +"@jest/schemas@npm:30.0.5": + version: 30.0.5 + resolution: "@jest/schemas@npm:30.0.5" + dependencies: + "@sinclair/typebox": "npm:^0.34.0" + checksum: 10/40df4db55d4aeed09d1c7e19caf23788309cea34490a1c5d584c913494195e698b9967e996afc27226cac6d76e7512fe73ae6b9584480695c60dd18a5459cdba languageName: node linkType: hard @@ -10472,61 +10522,88 @@ __metadata: languageName: node linkType: hard -"@jest/source-map@npm:^29.6.3": - version: 29.6.3 - resolution: "@jest/source-map@npm:29.6.3" +"@jest/snapshot-utils@npm:30.2.0": + version: 30.2.0 + resolution: "@jest/snapshot-utils@npm:30.2.0" dependencies: - "@jridgewell/trace-mapping": "npm:^0.3.18" - callsites: "npm:^3.0.0" - graceful-fs: "npm:^4.2.9" - checksum: 10/bcc5a8697d471396c0003b0bfa09722c3cd879ad697eb9c431e6164e2ea7008238a01a07193dfe3cbb48b1d258eb7251f6efcea36f64e1ebc464ea3c03ae2deb + "@jest/types": "npm:30.2.0" + chalk: "npm:^4.1.2" + graceful-fs: "npm:^4.2.11" + natural-compare: "npm:^1.4.0" + checksum: 10/6b30ab2b0682117e3ce775e70b5be1eb01e1ea53a74f12ac7090cd1a5f37e9b795cd8de83853afa7b4b799c96b1c482499aa993ca2034ea0679525d32b7f9625 languageName: node linkType: hard -"@jest/test-result@npm:^29.7.0": - version: 29.7.0 - resolution: "@jest/test-result@npm:29.7.0" +"@jest/source-map@npm:30.0.1": + version: 30.0.1 + resolution: "@jest/source-map@npm:30.0.1" dependencies: - "@jest/console": "npm:^29.7.0" - "@jest/types": "npm:^29.6.3" - "@types/istanbul-lib-coverage": "npm:^2.0.0" - collect-v8-coverage: "npm:^1.0.0" - checksum: 10/c073ab7dfe3c562bff2b8fee6cc724ccc20aa96bcd8ab48ccb2aa309b4c0c1923a9e703cea386bd6ae9b71133e92810475bb9c7c22328fc63f797ad3324ed189 + "@jridgewell/trace-mapping": "npm:^0.3.25" + callsites: "npm:^3.1.0" + graceful-fs: "npm:^4.2.11" + checksum: 10/161b27cdf8d9d80fd99374d55222b90478864c6990514be6ebee72b7184a034224c9aceed12c476f3a48d48601bf8ed2e0c047a5a81bd907dc192ebe71365ed4 languageName: node linkType: hard -"@jest/test-sequencer@npm:^29.7.0": - version: 29.7.0 - resolution: "@jest/test-sequencer@npm:29.7.0" +"@jest/test-result@npm:30.2.0": + version: 30.2.0 + resolution: "@jest/test-result@npm:30.2.0" dependencies: - "@jest/test-result": "npm:^29.7.0" - graceful-fs: "npm:^4.2.9" - jest-haste-map: "npm:^29.7.0" + "@jest/console": "npm:30.2.0" + "@jest/types": "npm:30.2.0" + "@types/istanbul-lib-coverage": "npm:^2.0.6" + collect-v8-coverage: "npm:^1.0.2" + checksum: 10/f58f79c3c3ba6dd15325e05b0b5a300777cd8cc38327f622608b6fe849b1073ee9633e33d1e5d7ef5b97a1ce71543d0ad92674b7a279f53033143e8dd7c22959 + languageName: node + linkType: hard + +"@jest/test-sequencer@npm:30.2.0": + version: 30.2.0 + resolution: "@jest/test-sequencer@npm:30.2.0" + dependencies: + "@jest/test-result": "npm:30.2.0" + graceful-fs: "npm:^4.2.11" + jest-haste-map: "npm:30.2.0" slash: "npm:^3.0.0" - checksum: 10/4420c26a0baa7035c5419b0892ff8ffe9a41b1583ec54a10db3037cd46a7e29dd3d7202f8aa9d376e9e53be5f8b1bc0d16e1de6880a6d319b033b01dc4c8f639 + checksum: 10/7923964b27048b2233858b32aa1b34d4dd9e404311626d944a706bcdcaa0b1585f43f2ffa3fa893ecbf133566f31ba2b79ab5eaaaf674b8558c6c7029ecbea5e languageName: node linkType: hard -"@jest/transform@npm:^29.7.0": - version: 29.7.0 - resolution: "@jest/transform@npm:29.7.0" +"@jest/transform@npm:30.2.0": + version: 30.2.0 + resolution: "@jest/transform@npm:30.2.0" dependencies: - "@babel/core": "npm:^7.11.6" - "@jest/types": "npm:^29.6.3" - "@jridgewell/trace-mapping": "npm:^0.3.18" - babel-plugin-istanbul: "npm:^6.1.1" - chalk: "npm:^4.0.0" + "@babel/core": "npm:^7.27.4" + "@jest/types": "npm:30.2.0" + "@jridgewell/trace-mapping": "npm:^0.3.25" + babel-plugin-istanbul: "npm:^7.0.1" + chalk: "npm:^4.1.2" convert-source-map: "npm:^2.0.0" fast-json-stable-stringify: "npm:^2.1.0" - graceful-fs: "npm:^4.2.9" - jest-haste-map: "npm:^29.7.0" - jest-regex-util: "npm:^29.6.3" - jest-util: "npm:^29.7.0" - micromatch: "npm:^4.0.4" - pirates: "npm:^4.0.4" + graceful-fs: "npm:^4.2.11" + jest-haste-map: "npm:30.2.0" + jest-regex-util: "npm:30.0.1" + jest-util: "npm:30.2.0" + micromatch: "npm:^4.0.8" + pirates: "npm:^4.0.7" slash: "npm:^3.0.0" - write-file-atomic: "npm:^4.0.2" - checksum: 10/30f42293545ab037d5799c81d3e12515790bb58513d37f788ce32d53326d0d72ebf5b40f989e6896739aa50a5f77be44686e510966370d58511d5ad2637c68c1 + write-file-atomic: "npm:^5.0.1" + checksum: 10/c75d72d524c2a50ea6c05778a9b76a6e48bc228a3390896a6edd4416f7b4954ee0a07e229ed7b4949ce8889324b70034c784751e3fc455a25648bd8dcad17d0d + languageName: node + linkType: hard + +"@jest/types@npm:30.2.0": + version: 30.2.0 + resolution: "@jest/types@npm:30.2.0" + dependencies: + "@jest/pattern": "npm:30.0.1" + "@jest/schemas": "npm:30.0.5" + "@types/istanbul-lib-coverage": "npm:^2.0.6" + "@types/istanbul-reports": "npm:^3.0.4" + "@types/node": "npm:*" + "@types/yargs": "npm:^17.0.33" + chalk: "npm:^4.1.2" + checksum: 10/f50fcaea56f873a51d19254ab16762f2ea8ca88e3e08da2e496af5da2b67c322915a4fcd0153803cc05063ffe87ebef2ab4330e0a1b06ab984a26c916cbfc26b languageName: node linkType: hard @@ -10544,12 +10621,11 @@ __metadata: languageName: node linkType: hard -"@joshwooding/vite-plugin-react-docgen-typescript@npm:0.6.1": - version: 0.6.1 - resolution: "@joshwooding/vite-plugin-react-docgen-typescript@npm:0.6.1" +"@joshwooding/vite-plugin-react-docgen-typescript@npm:^0.6.3": + version: 0.6.3 + resolution: "@joshwooding/vite-plugin-react-docgen-typescript@npm:0.6.3" dependencies: - glob: "npm:^10.0.0" - magic-string: "npm:^0.30.0" + glob: "npm:^11.1.0" react-docgen-typescript: "npm:^2.2.2" peerDependencies: typescript: ">= 4.3.x" @@ -10557,7 +10633,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10/a82b6005378ccda13250fcfeaa04ec2ba17d1c2923b5bba5907d5b2fd658c661b29c1215eb1c0fe305b390bee89ec77c684aa68506262734c3bb3cd76d8a6963 + checksum: 10/8a0f2c52b99e0dff4eeee574cf373b794e5398ee3c6b4d272378ccfe3b7dc2f3dc647d446716998ee2d88ee26df617e7b10da949702edcb625ee49e93b7daa95 languageName: node linkType: hard @@ -10615,13 +10691,13 @@ __metadata: languageName: node linkType: hard -"@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.18, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25, @jridgewell/trace-mapping@npm:^0.3.28, @jridgewell/trace-mapping@npm:^0.3.9": - version: 0.3.30 - resolution: "@jridgewell/trace-mapping@npm:0.3.30" +"@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.23, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25, @jridgewell/trace-mapping@npm:^0.3.28, @jridgewell/trace-mapping@npm:^0.3.9": + version: 0.3.31 + resolution: "@jridgewell/trace-mapping@npm:0.3.31" dependencies: "@jridgewell/resolve-uri": "npm:^3.1.0" "@jridgewell/sourcemap-codec": "npm:^1.4.14" - checksum: 10/f9fabe1122058f4fedc242bdc43fcaacb6b222c6fb712b7904c37704dcb16e50e07ca137ff99043da44292b18a8720296ff97f7703e960678b8ef51d0db4d250 + checksum: 10/da0283270e691bdb5543806077548532791608e52386cfbbf3b9e8fb00457859d1bd01d512851161c886eb3a2f3ce6fd9bcf25db8edf3bddedd275bd4a88d606 languageName: node linkType: hard @@ -10756,18 +10832,19 @@ __metadata: linkType: hard "@keyv/redis@npm:^4.0.1": - version: 4.4.1 - resolution: "@keyv/redis@npm:4.4.1" + version: 4.6.0 + resolution: "@keyv/redis@npm:4.6.0" dependencies: "@redis/client": "npm:^1.6.0" cluster-key-slot: "npm:^1.1.2" + hookified: "npm:^1.10.0" peerDependencies: keyv: ^5.3.4 - checksum: 10/85bf5830d5a19f45fbba864f7eb830cff0059f3f7c59c711a65b439821008a3321a94fb06c4d1f09295f0f233422586458652d266696c0925b5c8d1d695700ec + checksum: 10/c2619b4a8607fbc1cf159d695e827e7eba29859f342e017bf32e049eb62d40a61160671aec52c4f4ad6726fcee21c551193f3dd81846c0e98d1e0206d076e6fd languageName: node linkType: hard -"@keyv/serialize@npm:^1.0.3": +"@keyv/serialize@npm:^1.0.3, @keyv/serialize@npm:^1.1.1": version: 1.1.1 resolution: "@keyv/serialize@npm:1.1.1" checksum: 10/e3b2cb1377863342acedd5ff785af3e69269bee9b44707c617d1c8bc14eeb5ac763159d6455903ffe92f143c2238e1e783c4f113f9c8910eacccf172894472da @@ -10775,15 +10852,15 @@ __metadata: linkType: hard "@keyv/valkey@npm:^1.0.1": - version: 1.0.8 - resolution: "@keyv/valkey@npm:1.0.8" + version: 1.0.11 + resolution: "@keyv/valkey@npm:1.0.11" dependencies: iovalkey: "npm:^0.3.3" - checksum: 10/bca81d5603dab9f5f5c1759c25961c5c3e837b3de56775436a8a4b851c08acdb8689bd7db58d3c6bcd0ceead84241f4276b5f7638317ba75bbb2cb4c4ac71c02 + checksum: 10/c12b08590c0e95e008bdf0649a1f91983af69c94e31c52a81dc5473328efc25a4a9c7e435208a4a0c38e4a77a0b0f28945c81e0c34baaaa1bd0283014bea85ac languageName: node linkType: hard -"@kubernetes-models/apimachinery@npm:^2.0.0, @kubernetes-models/apimachinery@npm:^2.0.2": +"@kubernetes-models/apimachinery@npm:^2.0.0, @kubernetes-models/apimachinery@npm:^2.2.0": version: 2.2.0 resolution: "@kubernetes-models/apimachinery@npm:2.2.0" dependencies: @@ -10854,7 +10931,7 @@ __metadata: languageName: node linkType: hard -"@lezer/common@npm:^1.0.0, @lezer/common@npm:^1.1.0": +"@lezer/common@npm:^1.0.0, @lezer/common@npm:^1.1.0, @lezer/common@npm:^1.3.0": version: 1.4.0 resolution: "@lezer/common@npm:1.4.0" checksum: 10/8d0626835b8567115923772619d887c212c1e965e0ae2a230e3ae8e6734e0ded3bf4ca3a1eb4aa0af6a7f0cbb4892fa04de399916192fd98a99db8bf0f18da63 @@ -10862,20 +10939,20 @@ __metadata: linkType: hard "@lezer/highlight@npm:^1.0.0": - version: 1.0.0 - resolution: "@lezer/highlight@npm:1.0.0" + version: 1.2.3 + resolution: "@lezer/highlight@npm:1.2.3" dependencies: - "@lezer/common": "npm:^1.0.0" - checksum: 10/ed362dd4c27218bd941807f14ee691f1ad73613f96041538f5d2cc06521490a346a74044f32da573c1c6529bea2f5c190064c4bca92918732cb580c298880947 + "@lezer/common": "npm:^1.3.0" + checksum: 10/8f787d464f8a036f117a0b23e73ac034d224a57d72501c6559089098a28f127c9e495b90ac7d132acc86199e0b64d4c038f75f9293a37c7c61add52fa1acdb4e languageName: node linkType: hard "@lezer/lr@npm:^1.0.0": - version: 1.0.0 - resolution: "@lezer/lr@npm:1.0.0" + version: 1.4.4 + resolution: "@lezer/lr@npm:1.4.4" dependencies: "@lezer/common": "npm:^1.0.0" - checksum: 10/c1c60beef143008b5fbc64a6713be7656b51c858b83f9199cdafb439fc4028f35544990dd7b1fc3d89a518eecb10c90f5f3bdf6804f0a4429dfddb9210275add + checksum: 10/3485153107863075fc9c813977dd1a26b43114624e440e33c9e906d5afc6ec6b236b19439196b5baf7dd2d4c34f10642aa280250758ed3d60de5cad54590b1f2 languageName: node linkType: hard @@ -11206,9 +11283,9 @@ __metadata: linkType: hard "@microsoft/microsoft-graph-types@npm:^2.6.0": - version: 2.40.0 - resolution: "@microsoft/microsoft-graph-types@npm:2.40.0" - checksum: 10/40938d73867b13e78388e94f26ddde9433b325b546076783ebc6756af5b99ce52d126767fcb5eee1ee53730909111503388c868333dbd3dddf94d38679500fb4 + version: 2.43.1 + resolution: "@microsoft/microsoft-graph-types@npm:2.43.1" + checksum: 10/d24bf4230f3eaae6d93aee217c9d54693a45431287ec83cf9031a0b7335c3c6bc0119f24ee658dfb0092db11a62db29df313b39c3315bd98418b285618b01795 languageName: node linkType: hard @@ -11231,22 +11308,33 @@ __metadata: languageName: node linkType: hard -"@modelcontextprotocol/sdk@npm:^1.12.3": - version: 1.13.1 - resolution: "@modelcontextprotocol/sdk@npm:1.13.1" +"@modelcontextprotocol/sdk@npm:^1.24.3": + version: 1.24.3 + resolution: "@modelcontextprotocol/sdk@npm:1.24.3" dependencies: - ajv: "npm:^6.12.6" + ajv: "npm:^8.17.1" + ajv-formats: "npm:^3.0.1" content-type: "npm:^1.0.5" cors: "npm:^2.8.5" cross-spawn: "npm:^7.0.5" eventsource: "npm:^3.0.2" + eventsource-parser: "npm:^3.0.0" express: "npm:^5.0.1" express-rate-limit: "npm:^7.5.0" + jose: "npm:^6.1.1" pkce-challenge: "npm:^5.0.0" raw-body: "npm:^3.0.0" - zod: "npm:^3.23.8" - zod-to-json-schema: "npm:^3.24.1" - checksum: 10/b516d72e1cd14c67c8a2e5cb95fcc1c03c50be989850e3e963a7ed11000acb604e65efeaad47ea93c847130536ee51859a8d34e6dbe99d408e1a24224592e57f + zod: "npm:^3.25 || ^4.0" + zod-to-json-schema: "npm:^3.25.0" + peerDependencies: + "@cfworker/json-schema": ^4.1.1 + zod: ^3.25 || ^4.0 + peerDependenciesMeta: + "@cfworker/json-schema": + optional: true + zod: + optional: false + checksum: 10/661aea493ee06674edc0d1409d5ff6e53053da2c3eb27d28ecdd5aa212d9d6bac8c00bec1cd18c1065f2d5774afef34e3cdcd19643056f954c14f611fee8cbc4 languageName: node linkType: hard @@ -11336,10 +11424,10 @@ __metadata: languageName: node linkType: hard -"@module-federation/error-codes@npm:0.17.1": - version: 0.17.1 - resolution: "@module-federation/error-codes@npm:0.17.1" - checksum: 10/5f5f02a90a423479c84e4ff4398a3a9e31b66bd545e7c978ecb8a417f33162b86e749356baab14c006e741c9cebae549335a4c99e94ce7ef54210269fdf74f7f +"@module-federation/error-codes@npm:0.21.6": + version: 0.21.6 + resolution: "@module-federation/error-codes@npm:0.21.6" + checksum: 10/6ded1ecab780f1f9ec46a59adb200e75cdf11580d70aa79dd75d71fbbf276615690da277ea67aa1ceb5bc88386f5708cc1d2ba5526be5c9ff02397a6123e36bf languageName: node linkType: hard @@ -11407,13 +11495,13 @@ __metadata: languageName: node linkType: hard -"@module-federation/runtime-core@npm:0.17.1": - version: 0.17.1 - resolution: "@module-federation/runtime-core@npm:0.17.1" +"@module-federation/runtime-core@npm:0.21.6": + version: 0.21.6 + resolution: "@module-federation/runtime-core@npm:0.21.6" dependencies: - "@module-federation/error-codes": "npm:0.17.1" - "@module-federation/sdk": "npm:0.17.1" - checksum: 10/b0c945379bde13af84ceb833e3bfe3c8cf11fd265af0ad7640a1506017529458f408a4a3f1bd0f4b5983da71438913d5c25ed25e20908eb1f789bd1483616650 + "@module-federation/error-codes": "npm:0.21.6" + "@module-federation/sdk": "npm:0.21.6" + checksum: 10/85efa2042d6f3a7cf0e4971b991472d4339d88f6f15684afb6d451f19ed934e225b2510c86b7bb4d2c5f64253ed7b0175f08c17f95bfc2b9929930a8a03fff1e languageName: node linkType: hard @@ -11427,13 +11515,13 @@ __metadata: languageName: node linkType: hard -"@module-federation/runtime-tools@npm:0.17.1": - version: 0.17.1 - resolution: "@module-federation/runtime-tools@npm:0.17.1" +"@module-federation/runtime-tools@npm:0.21.6": + version: 0.21.6 + resolution: "@module-federation/runtime-tools@npm:0.21.6" dependencies: - "@module-federation/runtime": "npm:0.17.1" - "@module-federation/webpack-bundler-runtime": "npm:0.17.1" - checksum: 10/2e183e357b644dbe015d0e51df3fe601852ca79ffe3a30c582eee7a2050d7600eb3253f5de15e476c60741d0a1dd70add1ade7b5a3537cd2ee12bfee286284ea + "@module-federation/runtime": "npm:0.21.6" + "@module-federation/webpack-bundler-runtime": "npm:0.21.6" + checksum: 10/36e7ccab948e11f310e87397a1a2185b56064e5691e553b34173686e2bc7372ec710e5ad48c026eb28c85b168765788b743aa2111513f3b57118b47636312dd1 languageName: node linkType: hard @@ -11447,14 +11535,14 @@ __metadata: languageName: node linkType: hard -"@module-federation/runtime@npm:0.17.1": - version: 0.17.1 - resolution: "@module-federation/runtime@npm:0.17.1" +"@module-federation/runtime@npm:0.21.6": + version: 0.21.6 + resolution: "@module-federation/runtime@npm:0.21.6" dependencies: - "@module-federation/error-codes": "npm:0.17.1" - "@module-federation/runtime-core": "npm:0.17.1" - "@module-federation/sdk": "npm:0.17.1" - checksum: 10/f5405968dff4fa2cf510127701ec1722105f44298fd09eafeecead450b7bb95a05450749157fe2fc39caf6241bec9e45caa9a55375b48e7f195db84799a8df0c + "@module-federation/error-codes": "npm:0.21.6" + "@module-federation/runtime-core": "npm:0.21.6" + "@module-federation/sdk": "npm:0.21.6" + checksum: 10/93fd9bb284630933cab7e4bc070d648b56272f3636038c05eec7d1e3eeb189be3ccebe5f8ecc450197ee992d2616ed282d54e673ec0acd63adee4faddf80b144 languageName: node linkType: hard @@ -11469,10 +11557,10 @@ __metadata: languageName: node linkType: hard -"@module-federation/sdk@npm:0.17.1": - version: 0.17.1 - resolution: "@module-federation/sdk@npm:0.17.1" - checksum: 10/daaaa49ed900c00a69641130cf673ad5d5b8623d82fb4bd03a67c839a6da760a0a5ae29b836ba66eeb95ee5392e558588ffd987a2c00b05c2b0a7c5039ed042d +"@module-federation/sdk@npm:0.21.6": + version: 0.21.6 + resolution: "@module-federation/sdk@npm:0.21.6" + checksum: 10/effc4aa932e2f06742bda8f02aaec84e138f5512b50f18c38b051490020b20d3d8edf7ece853fccffc1f78a0b43dec78e69bf02150e7e2801d5ce03c3ee367b9 languageName: node linkType: hard @@ -11494,13 +11582,13 @@ __metadata: languageName: node linkType: hard -"@module-federation/webpack-bundler-runtime@npm:0.17.1": - version: 0.17.1 - resolution: "@module-federation/webpack-bundler-runtime@npm:0.17.1" +"@module-federation/webpack-bundler-runtime@npm:0.21.6": + version: 0.21.6 + resolution: "@module-federation/webpack-bundler-runtime@npm:0.21.6" dependencies: - "@module-federation/runtime": "npm:0.17.1" - "@module-federation/sdk": "npm:0.17.1" - checksum: 10/72e5030529dbc53df6271fa78bdb63976d0601fe9fde5105f8a7325e0fa296bc35277b9b084e52995cd314b89e12d33f8b869c1d63a13231c2948d4c741e72fd + "@module-federation/runtime": "npm:0.21.6" + "@module-federation/sdk": "npm:0.21.6" + checksum: 10/a5ceb72ee3867acad5d7d3c654eb568068b1d5288f60ce9301bdc9f56effa5a4c26a732a2cec7176a81b87139566cd51dd8dfbc6112da05d47b870fa3ad3ba1f languageName: node linkType: hard @@ -11606,8 +11694,8 @@ __metadata: linkType: hard "@mswjs/interceptors@npm:^0.39.1": - version: 0.39.2 - resolution: "@mswjs/interceptors@npm:0.39.2" + version: 0.39.6 + resolution: "@mswjs/interceptors@npm:0.39.6" dependencies: "@open-draft/deferred-promise": "npm:^2.2.0" "@open-draft/logger": "npm:^0.3.0" @@ -11615,26 +11703,26 @@ __metadata: is-node-process: "npm:^1.2.0" outvariant: "npm:^1.4.3" strict-event-emitter: "npm:^0.5.1" - checksum: 10/faaa95d636363a197f125c32066457fa74d5063d8ccae4c9c0e0510179060d92b1faf8640df45a0623e0bf42a30d610c83364a58e0eb0ca412c87b2e835936c1 + checksum: 10/c87d3edf08353bde825c87b151b24d538070540ab419206cef1774c932e888af0f920183182fb7c94c3eee42068da5a0a5855853fded8514f33c870921ef37ec languageName: node linkType: hard -"@mui/core-downloads-tracker@npm:^5.16.14": - version: 5.16.14 - resolution: "@mui/core-downloads-tracker@npm:5.16.14" - checksum: 10/a25658362a69a89f35cdc12ded01b998b7f02df43648029f2523813fc7f259cc85f62bd1877059359d462e7c163e82308bd4cc74fa2d35651d302c5d8bbbc7f4 +"@mui/core-downloads-tracker@npm:^5.18.0": + version: 5.18.0 + resolution: "@mui/core-downloads-tracker@npm:5.18.0" + checksum: 10/065b46739d2bd84b880ad2f6a0a2062d60e3a296ce18ff380cad22ab5b2cb3de396755f322f4bea3a422ffffe1a9244536fc3c9623056ff3873c996e6664b1b9 languageName: node linkType: hard "@mui/material@npm:^5.12.2": - version: 5.16.14 - resolution: "@mui/material@npm:5.16.14" + version: 5.18.0 + resolution: "@mui/material@npm:5.18.0" dependencies: "@babel/runtime": "npm:^7.23.9" - "@mui/core-downloads-tracker": "npm:^5.16.14" - "@mui/system": "npm:^5.16.14" - "@mui/types": "npm:^7.2.15" - "@mui/utils": "npm:^5.16.14" + "@mui/core-downloads-tracker": "npm:^5.18.0" + "@mui/system": "npm:^5.18.0" + "@mui/types": "npm:~7.2.15" + "@mui/utils": "npm:^5.17.1" "@popperjs/core": "npm:^2.11.8" "@types/react-transition-group": "npm:^4.4.10" clsx: "npm:^2.1.0" @@ -11655,11 +11743,11 @@ __metadata: optional: true "@types/react": optional: true - checksum: 10/4fe36ebe4d5f65e420895d114db81c0b8a5061e39bc18cdbebf6204953dae34cdc04af9827b65eb136e5a6853f4500a736ed3d52cce4ea37057a749eca5c3fad + checksum: 10/4b72e07c76c7c4b1076db82ef42a06dfab7d73d73f0d272019b2e0b200fc25c27bb295a8672577e1094168054159bed387cf9af74fec30e98aead7d97fad0a57 languageName: node linkType: hard -"@mui/private-theming@npm:^5.16.14, @mui/private-theming@npm:^5.17.1": +"@mui/private-theming@npm:^5.17.1": version: 5.17.1 resolution: "@mui/private-theming@npm:5.17.1" dependencies: @@ -11699,14 +11787,14 @@ __metadata: linkType: hard "@mui/styles@npm:^5.14.18": - version: 5.16.14 - resolution: "@mui/styles@npm:5.16.14" + version: 5.18.0 + resolution: "@mui/styles@npm:5.18.0" dependencies: "@babel/runtime": "npm:^7.23.9" "@emotion/hash": "npm:^0.9.1" - "@mui/private-theming": "npm:^5.16.14" - "@mui/types": "npm:^7.2.15" - "@mui/utils": "npm:^5.16.14" + "@mui/private-theming": "npm:^5.17.1" + "@mui/types": "npm:~7.2.15" + "@mui/utils": "npm:^5.17.1" clsx: "npm:^2.1.0" csstype: "npm:^3.1.3" hoist-non-react-statics: "npm:^3.3.2" @@ -11725,11 +11813,11 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 10/53036720e7cd928c32d23c771679ce155be47e4bd5595a13abe33a4e5cf1378809f9b93609ea6307479e5a02ad82c6ca71699f74fd70c7a7993471c765e2f004 + checksum: 10/b02cc02f7c8eafe0bd5b8bc1121ee0cee50bb48e876b652313aad4c61ae466c411423e8e82f603a386ecf569c537ecfa92b6c7dabd0c798d6727e935df7fa1e6 languageName: node linkType: hard -"@mui/system@npm:^5.16.14": +"@mui/system@npm:^5.16.14, @mui/system@npm:^5.18.0": version: 5.18.0 resolution: "@mui/system@npm:5.18.0" dependencies: @@ -11757,7 +11845,7 @@ __metadata: languageName: node linkType: hard -"@mui/types@npm:^7.2.15, @mui/types@npm:~7.2.15": +"@mui/types@npm:~7.2.15": version: 7.2.24 resolution: "@mui/types@npm:7.2.24" peerDependencies: @@ -11769,7 +11857,7 @@ __metadata: languageName: node linkType: hard -"@mui/utils@npm:^5.14.15, @mui/utils@npm:^5.16.14, @mui/utils@npm:^5.17.1": +"@mui/utils@npm:^5.14.15, @mui/utils@npm:^5.17.1": version: 5.17.1 resolution: "@mui/utils@npm:5.17.1" dependencies: @@ -11796,35 +11884,57 @@ __metadata: languageName: node linkType: hard -"@napi-rs/wasm-runtime@npm:^1.0.1": - version: 1.0.1 - resolution: "@napi-rs/wasm-runtime@npm:1.0.1" +"@napi-rs/wasm-runtime@npm:1.0.7": + version: 1.0.7 + resolution: "@napi-rs/wasm-runtime@npm:1.0.7" dependencies: - "@emnapi/core": "npm:^1.4.5" - "@emnapi/runtime": "npm:^1.4.5" - "@tybys/wasm-util": "npm:^0.10.0" - checksum: 10/8ed2a1f1246ecbef04b73e06c994f635ebb8c7b929620f28859c49cb7e373adee4fd1b9529bab286171c0ef0f668331d683bcf30ab193e5bf05a04b4e07cd56a + "@emnapi/core": "npm:^1.5.0" + "@emnapi/runtime": "npm:^1.5.0" + "@tybys/wasm-util": "npm:^0.10.1" + checksum: 10/6bc32d32d486d07b83220a9b7b2b715e39acacbacef0011ebca05c00b41d80a0535123da10fea7a7d6d7e206712bb50dc50ac3cf88b770754d44378570fb5c05 languageName: node linkType: hard -"@nestjs/axios@npm:4.0.0": - version: 4.0.0 - resolution: "@nestjs/axios@npm:4.0.0" +"@napi-rs/wasm-runtime@npm:^0.2.11": + version: 0.2.12 + resolution: "@napi-rs/wasm-runtime@npm:0.2.12" + dependencies: + "@emnapi/core": "npm:^1.4.3" + "@emnapi/runtime": "npm:^1.4.3" + "@tybys/wasm-util": "npm:^0.10.0" + checksum: 10/5fd518182427980c28bc724adf06c5f32f9a8915763ef560b5f7d73607d30cd15ac86d0cbd2eb80d4cfab23fc80d0876d89ca36a9daadcb864bc00917c94187c + languageName: node + linkType: hard + +"@napi-rs/wasm-runtime@npm:^1.1.0": + version: 1.1.0 + resolution: "@napi-rs/wasm-runtime@npm:1.1.0" + dependencies: + "@emnapi/core": "npm:^1.7.1" + "@emnapi/runtime": "npm:^1.7.1" + "@tybys/wasm-util": "npm:^0.10.1" + checksum: 10/87c7ab4685527aa4820320020e2af5879b99d88e94b42cdc3690646722536f14656667392975a9576bf411a3804a464949fadbc343a646a2c2a8b2f10d921f6c + languageName: node + linkType: hard + +"@nestjs/axios@npm:4.0.1": + version: 4.0.1 + resolution: "@nestjs/axios@npm:4.0.1" peerDependencies: "@nestjs/common": ^10.0.0 || ^11.0.0 axios: ^1.3.1 rxjs: ^7.0.0 - checksum: 10/9a61ac8a2fdbf304961696148945ba9e19c0ed73256767b0a643bbafe77106b2f738cb2f35f2fc63bff09a8abcd18365d2f8c772484e2fdd70b455bceb7b5822 + checksum: 10/0cc741e4fbfc39920afbb6c58050e0dbfecc8e2f7b249d879802a5b03b65df3714e828970e2bf12283d3d27e1f1ab7ca5ec62b5698dc50f105680e100a0a33f6 languageName: node linkType: hard -"@nestjs/common@npm:11.1.3": - version: 11.1.3 - resolution: "@nestjs/common@npm:11.1.3" +"@nestjs/common@npm:11.1.9": + version: 11.1.9 + resolution: "@nestjs/common@npm:11.1.9" dependencies: - file-type: "npm:21.0.0" + file-type: "npm:21.1.0" iterare: "npm:1.2.1" - load-esm: "npm:1.0.2" + load-esm: "npm:1.0.3" tslib: "npm:2.8.1" uid: "npm:2.0.2" peerDependencies: @@ -11837,18 +11947,18 @@ __metadata: optional: true class-validator: optional: true - checksum: 10/b1c9699cdf9cee96ed0178e5eed3b1829c210bbdbd703bb9e1e0def2c7456273d73329635439b16164e43de8a8d54dd5b7d1dd5dba65417d746bd731b8c5d685 + checksum: 10/996a13749f9ade78202b49421e64edf81be9df65b1b1bb4149d2adb8cbdbdf7033deafc2b89b8123ea0b647ea13d325a2aed4efa19b5b59a1e8d01dd4e554a76 languageName: node linkType: hard -"@nestjs/core@npm:11.1.3": - version: 11.1.3 - resolution: "@nestjs/core@npm:11.1.3" +"@nestjs/core@npm:11.1.9": + version: 11.1.9 + resolution: "@nestjs/core@npm:11.1.9" dependencies: "@nuxt/opencollective": "npm:0.4.1" fast-safe-stringify: "npm:2.1.1" iterare: "npm:1.2.1" - path-to-regexp: "npm:8.2.0" + path-to-regexp: "npm:8.3.0" tslib: "npm:2.8.1" uid: "npm:2.0.2" peerDependencies: @@ -11865,7 +11975,7 @@ __metadata: optional: true "@nestjs/websockets": optional: true - checksum: 10/b46a9f877170f7e96429da5970684525277bcb341f3a24032b6748ad503b5c7164b77410daf9c0f3ca99b5f6b99985d5eb739501cfc01c941218397f32f2d095 + checksum: 10/2adc7440898574fc3715e0a5ea2a4faeae52bd13431a449645963d9aff0c06ac748cf2e439af29736406154634d033d0795b06069cc9cc9114ee29b167578b9d languageName: node linkType: hard @@ -11886,16 +11996,6 @@ __metadata: languageName: node linkType: hard -"@nodelib/fs.scandir@npm:4.0.1": - version: 4.0.1 - resolution: "@nodelib/fs.scandir@npm:4.0.1" - dependencies: - "@nodelib/fs.stat": "npm:4.0.0" - run-parallel: "npm:^1.2.0" - checksum: 10/44b2b2b34e48ca88ee004413f5033db31cd6d5ecf8c7bbef0e33b6672d603f3e23b57d5fbb1bd5f83f8992df58381be6600006d92a903f085e698a37bdfe3c89 - languageName: node - linkType: hard - "@nodelib/fs.stat@npm:2.0.5, @nodelib/fs.stat@npm:^2.0.2": version: 2.0.5 resolution: "@nodelib/fs.stat@npm:2.0.5" @@ -11903,23 +12003,6 @@ __metadata: languageName: node linkType: hard -"@nodelib/fs.stat@npm:4.0.0": - version: 4.0.0 - resolution: "@nodelib/fs.stat@npm:4.0.0" - checksum: 10/1f87199fdab938d2ed6f5e10debc006f7965081e2cd147ed3d2333049a030cad1949bd76556a5f5364f062c3e1edcc3d0981189b065336fc92c503ead463f4e1 - languageName: node - linkType: hard - -"@nodelib/fs.walk@npm:3.0.1": - version: 3.0.1 - resolution: "@nodelib/fs.walk@npm:3.0.1" - dependencies: - "@nodelib/fs.scandir": "npm:4.0.1" - fastq: "npm:^1.15.0" - checksum: 10/7b76a0139dec52e3f2a3a0bb4f13dbf72a6b79d8076ec4b5deea9e75bd1b79d7abda53776f93b5aefda9a5e40f0e31f49f6e35bf5460a402f0aee7bcf3b26d85 - languageName: node - linkType: hard - "@nodelib/fs.walk@npm:^1.2.3, @nodelib/fs.walk@npm:^1.2.8": version: 1.2.8 resolution: "@nodelib/fs.walk@npm:1.2.8" @@ -12893,30 +12976,29 @@ __metadata: linkType: hard "@openapitools/openapi-generator-cli@npm:^2.4.26, @openapitools/openapi-generator-cli@npm:^2.7.0": - version: 2.20.5 - resolution: "@openapitools/openapi-generator-cli@npm:2.20.5" + version: 2.25.2 + resolution: "@openapitools/openapi-generator-cli@npm:2.25.2" dependencies: - "@nestjs/axios": "npm:4.0.0" - "@nestjs/common": "npm:11.1.3" - "@nestjs/core": "npm:11.1.3" + "@nestjs/axios": "npm:4.0.1" + "@nestjs/common": "npm:11.1.9" + "@nestjs/core": "npm:11.1.9" "@nuxtjs/opencollective": "npm:0.3.2" - axios: "npm:1.9.0" + axios: "npm:1.13.2" chalk: "npm:4.1.2" commander: "npm:8.3.0" - compare-versions: "npm:4.1.4" - concurrently: "npm:6.5.1" + compare-versions: "npm:6.1.1" + concurrently: "npm:9.2.1" console.table: "npm:0.10.0" - fs-extra: "npm:11.3.0" - glob: "npm:11.0.3" - inquirer: "npm:8.2.6" - lodash: "npm:4.17.21" + fs-extra: "npm:11.3.2" + glob: "npm:13.0.0" + inquirer: "npm:8.2.7" proxy-agent: "npm:6.5.0" reflect-metadata: "npm:0.2.2" rxjs: "npm:7.8.2" tslib: "npm:2.8.1" bin: openapi-generator-cli: main.js - checksum: 10/76e40b238074c8bf09c99c70222cd80aa1d8be8b9abe6c400542f1bd46c3058238247085835a08a57bb0a43dceeff40b3cb8c4ea736692d040c1d29c48bd1db7 + checksum: 10/8a6e2990f4816aadb8ac6f390aeb169fe2f842f8874417dd288ea4b177af9238a7af59c699953e644d17eeb6c5d712faf63ce3bf9419e429e71504e2033de7b6 languageName: node linkType: hard @@ -13992,6 +14074,148 @@ __metadata: languageName: node linkType: hard +"@oxc-resolver/binding-android-arm-eabi@npm:11.14.2": + version: 11.14.2 + resolution: "@oxc-resolver/binding-android-arm-eabi@npm:11.14.2" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@oxc-resolver/binding-android-arm64@npm:11.14.2": + version: 11.14.2 + resolution: "@oxc-resolver/binding-android-arm64@npm:11.14.2" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@oxc-resolver/binding-darwin-arm64@npm:11.14.2": + version: 11.14.2 + resolution: "@oxc-resolver/binding-darwin-arm64@npm:11.14.2" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@oxc-resolver/binding-darwin-x64@npm:11.14.2": + version: 11.14.2 + resolution: "@oxc-resolver/binding-darwin-x64@npm:11.14.2" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@oxc-resolver/binding-freebsd-x64@npm:11.14.2": + version: 11.14.2 + resolution: "@oxc-resolver/binding-freebsd-x64@npm:11.14.2" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@oxc-resolver/binding-linux-arm-gnueabihf@npm:11.14.2": + version: 11.14.2 + resolution: "@oxc-resolver/binding-linux-arm-gnueabihf@npm:11.14.2" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@oxc-resolver/binding-linux-arm-musleabihf@npm:11.14.2": + version: 11.14.2 + resolution: "@oxc-resolver/binding-linux-arm-musleabihf@npm:11.14.2" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@oxc-resolver/binding-linux-arm64-gnu@npm:11.14.2": + version: 11.14.2 + resolution: "@oxc-resolver/binding-linux-arm64-gnu@npm:11.14.2" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@oxc-resolver/binding-linux-arm64-musl@npm:11.14.2": + version: 11.14.2 + resolution: "@oxc-resolver/binding-linux-arm64-musl@npm:11.14.2" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@oxc-resolver/binding-linux-ppc64-gnu@npm:11.14.2": + version: 11.14.2 + resolution: "@oxc-resolver/binding-linux-ppc64-gnu@npm:11.14.2" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@oxc-resolver/binding-linux-riscv64-gnu@npm:11.14.2": + version: 11.14.2 + resolution: "@oxc-resolver/binding-linux-riscv64-gnu@npm:11.14.2" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@oxc-resolver/binding-linux-riscv64-musl@npm:11.14.2": + version: 11.14.2 + resolution: "@oxc-resolver/binding-linux-riscv64-musl@npm:11.14.2" + conditions: os=linux & cpu=riscv64 & libc=musl + languageName: node + linkType: hard + +"@oxc-resolver/binding-linux-s390x-gnu@npm:11.14.2": + version: 11.14.2 + resolution: "@oxc-resolver/binding-linux-s390x-gnu@npm:11.14.2" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@oxc-resolver/binding-linux-x64-gnu@npm:11.14.2": + version: 11.14.2 + resolution: "@oxc-resolver/binding-linux-x64-gnu@npm:11.14.2" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@oxc-resolver/binding-linux-x64-musl@npm:11.14.2": + version: 11.14.2 + resolution: "@oxc-resolver/binding-linux-x64-musl@npm:11.14.2" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@oxc-resolver/binding-openharmony-arm64@npm:11.14.2": + version: 11.14.2 + resolution: "@oxc-resolver/binding-openharmony-arm64@npm:11.14.2" + conditions: os=openharmony & cpu=arm64 + languageName: node + linkType: hard + +"@oxc-resolver/binding-wasm32-wasi@npm:11.14.2": + version: 11.14.2 + resolution: "@oxc-resolver/binding-wasm32-wasi@npm:11.14.2" + dependencies: + "@napi-rs/wasm-runtime": "npm:^1.1.0" + conditions: cpu=wasm32 + languageName: node + linkType: hard + +"@oxc-resolver/binding-win32-arm64-msvc@npm:11.14.2": + version: 11.14.2 + resolution: "@oxc-resolver/binding-win32-arm64-msvc@npm:11.14.2" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@oxc-resolver/binding-win32-ia32-msvc@npm:11.14.2": + version: 11.14.2 + resolution: "@oxc-resolver/binding-win32-ia32-msvc@npm:11.14.2" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@oxc-resolver/binding-win32-x64-msvc@npm:11.14.2": + version: 11.14.2 + resolution: "@oxc-resolver/binding-win32-x64-msvc@npm:11.14.2" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@paralleldrive/cuid2@npm:^2.2.2": version: 2.2.2 resolution: "@paralleldrive/cuid2@npm:2.2.2" @@ -14008,14 +14232,21 @@ __metadata: languageName: node linkType: hard +"@pkgr/core@npm:^0.2.9": + version: 0.2.9 + resolution: "@pkgr/core@npm:0.2.9" + checksum: 10/bb2fb86977d63f836f8f5b09015d74e6af6488f7a411dcd2bfdca79d76b5a681a9112f41c45bdf88a9069f049718efc6f3900d7f1de66a2ec966068308ae517f + languageName: node + linkType: hard + "@playwright/test@npm:^1.32.3": - version: 1.54.2 - resolution: "@playwright/test@npm:1.54.2" + version: 1.57.0 + resolution: "@playwright/test@npm:1.57.0" dependencies: - playwright: "npm:1.54.2" + playwright: "npm:1.57.0" bin: playwright: cli.js - checksum: 10/33d6c0780ef6cca12c008cae166ba06978ae975138a1654e14cd8691ad7826dbbc03e492ed42c65889c44ca893d0fd47d8ae4dc8d824020d7f767260b395dc6b + checksum: 10/07f5ba4841b2db1dea70d821004c5156b692488e13523c096ce3487d30f95f34ccf30ba6467ece60c86faac27ae382213b7eacab48a695550981b2e811e5e579 languageName: node linkType: hard @@ -16444,11 +16675,11 @@ __metadata: linkType: hard "@remixicon/react@npm:^4.6.0": - version: 4.6.0 - resolution: "@remixicon/react@npm:4.6.0" + version: 4.7.0 + resolution: "@remixicon/react@npm:4.7.0" peerDependencies: react: ">=18.2.0" - checksum: 10/d92c8131734062fca8d82d55dd8f3f4e28cb72c5eefda528c8aba5f3298f0c847342eecdbd7787d6da5af21b699d735f6cf27f151f0c982c1c9f06a78b235c94 + checksum: 10/9ecee093dd4aec3744bcc7562eddb987bf9c7c059787dfecfbcc25a64c2f4833dc815dff715aa2a7f75011d65f877b3751a401d19cf2d725b5bcc685587d37f4 languageName: node linkType: hard @@ -16583,7 +16814,7 @@ __metadata: languageName: node linkType: hard -"@rollup/pluginutils@npm:^5.0.1, @rollup/pluginutils@npm:^5.0.2, @rollup/pluginutils@npm:^5.0.5, @rollup/pluginutils@npm:^5.1.0": +"@rollup/pluginutils@npm:^5.0.1, @rollup/pluginutils@npm:^5.0.2, @rollup/pluginutils@npm:^5.1.0": version: 5.2.0 resolution: "@rollup/pluginutils@npm:5.2.0" dependencies: @@ -16599,232 +16830,246 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-android-arm-eabi@npm:4.46.2": - version: 4.46.2 - resolution: "@rollup/rollup-android-arm-eabi@npm:4.46.2" +"@rollup/rollup-android-arm-eabi@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-android-arm-eabi@npm:4.53.3" conditions: os=android & cpu=arm languageName: node linkType: hard -"@rollup/rollup-android-arm64@npm:4.46.2": - version: 4.46.2 - resolution: "@rollup/rollup-android-arm64@npm:4.46.2" +"@rollup/rollup-android-arm64@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-android-arm64@npm:4.53.3" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-darwin-arm64@npm:4.46.2": - version: 4.46.2 - resolution: "@rollup/rollup-darwin-arm64@npm:4.46.2" +"@rollup/rollup-darwin-arm64@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-darwin-arm64@npm:4.53.3" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-darwin-x64@npm:4.46.2": - version: 4.46.2 - resolution: "@rollup/rollup-darwin-x64@npm:4.46.2" +"@rollup/rollup-darwin-x64@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-darwin-x64@npm:4.53.3" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@rollup/rollup-freebsd-arm64@npm:4.46.2": - version: 4.46.2 - resolution: "@rollup/rollup-freebsd-arm64@npm:4.46.2" +"@rollup/rollup-freebsd-arm64@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-freebsd-arm64@npm:4.53.3" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-freebsd-x64@npm:4.46.2": - version: 4.46.2 - resolution: "@rollup/rollup-freebsd-x64@npm:4.46.2" +"@rollup/rollup-freebsd-x64@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-freebsd-x64@npm:4.53.3" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@rollup/rollup-linux-arm-gnueabihf@npm:4.46.2": - version: 4.46.2 - resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.46.2" +"@rollup/rollup-linux-arm-gnueabihf@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.53.3" conditions: os=linux & cpu=arm & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-arm-musleabihf@npm:4.46.2": - version: 4.46.2 - resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.46.2" +"@rollup/rollup-linux-arm-musleabihf@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.53.3" conditions: os=linux & cpu=arm & libc=musl languageName: node linkType: hard -"@rollup/rollup-linux-arm64-gnu@npm:4.46.2": - version: 4.46.2 - resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.46.2" +"@rollup/rollup-linux-arm64-gnu@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.53.3" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-arm64-musl@npm:4.46.2": - version: 4.46.2 - resolution: "@rollup/rollup-linux-arm64-musl@npm:4.46.2" +"@rollup/rollup-linux-arm64-musl@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-linux-arm64-musl@npm:4.53.3" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@rollup/rollup-linux-loongarch64-gnu@npm:4.46.2": - version: 4.46.2 - resolution: "@rollup/rollup-linux-loongarch64-gnu@npm:4.46.2" +"@rollup/rollup-linux-loong64-gnu@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-linux-loong64-gnu@npm:4.53.3" conditions: os=linux & cpu=loong64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-ppc64-gnu@npm:4.46.2": - version: 4.46.2 - resolution: "@rollup/rollup-linux-ppc64-gnu@npm:4.46.2" +"@rollup/rollup-linux-ppc64-gnu@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-linux-ppc64-gnu@npm:4.53.3" conditions: os=linux & cpu=ppc64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-riscv64-gnu@npm:4.46.2": - version: 4.46.2 - resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.46.2" +"@rollup/rollup-linux-riscv64-gnu@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.53.3" conditions: os=linux & cpu=riscv64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-riscv64-musl@npm:4.46.2": - version: 4.46.2 - resolution: "@rollup/rollup-linux-riscv64-musl@npm:4.46.2" +"@rollup/rollup-linux-riscv64-musl@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-linux-riscv64-musl@npm:4.53.3" conditions: os=linux & cpu=riscv64 & libc=musl languageName: node linkType: hard -"@rollup/rollup-linux-s390x-gnu@npm:4.46.2": - version: 4.46.2 - resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.46.2" +"@rollup/rollup-linux-s390x-gnu@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.53.3" conditions: os=linux & cpu=s390x & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-x64-gnu@npm:4.46.2": - version: 4.46.2 - resolution: "@rollup/rollup-linux-x64-gnu@npm:4.46.2" +"@rollup/rollup-linux-x64-gnu@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.53.3" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-x64-musl@npm:4.46.2": - version: 4.46.2 - resolution: "@rollup/rollup-linux-x64-musl@npm:4.46.2" +"@rollup/rollup-linux-x64-musl@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-linux-x64-musl@npm:4.53.3" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@rollup/rollup-win32-arm64-msvc@npm:4.46.2": - version: 4.46.2 - resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.46.2" +"@rollup/rollup-openharmony-arm64@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-openharmony-arm64@npm:4.53.3" + conditions: os=openharmony & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-win32-arm64-msvc@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.53.3" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-win32-ia32-msvc@npm:4.46.2": - version: 4.46.2 - resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.46.2" +"@rollup/rollup-win32-ia32-msvc@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.53.3" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@rollup/rollup-win32-x64-msvc@npm:4.46.2": - version: 4.46.2 - resolution: "@rollup/rollup-win32-x64-msvc@npm:4.46.2" +"@rollup/rollup-win32-x64-gnu@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-win32-x64-gnu@npm:4.53.3" conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"@rspack/binding-darwin-arm64@npm:1.4.11": - version: 1.4.11 - resolution: "@rspack/binding-darwin-arm64@npm:1.4.11" +"@rollup/rollup-win32-x64-msvc@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-win32-x64-msvc@npm:4.53.3" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@rspack/binding-darwin-arm64@npm:1.6.7": + version: 1.6.7 + resolution: "@rspack/binding-darwin-arm64@npm:1.6.7" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@rspack/binding-darwin-x64@npm:1.4.11": - version: 1.4.11 - resolution: "@rspack/binding-darwin-x64@npm:1.4.11" +"@rspack/binding-darwin-x64@npm:1.6.7": + version: 1.6.7 + resolution: "@rspack/binding-darwin-x64@npm:1.6.7" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@rspack/binding-linux-arm64-gnu@npm:1.4.11": - version: 1.4.11 - resolution: "@rspack/binding-linux-arm64-gnu@npm:1.4.11" +"@rspack/binding-linux-arm64-gnu@npm:1.6.7": + version: 1.6.7 + resolution: "@rspack/binding-linux-arm64-gnu@npm:1.6.7" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@rspack/binding-linux-arm64-musl@npm:1.4.11": - version: 1.4.11 - resolution: "@rspack/binding-linux-arm64-musl@npm:1.4.11" +"@rspack/binding-linux-arm64-musl@npm:1.6.7": + version: 1.6.7 + resolution: "@rspack/binding-linux-arm64-musl@npm:1.6.7" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@rspack/binding-linux-x64-gnu@npm:1.4.11": - version: 1.4.11 - resolution: "@rspack/binding-linux-x64-gnu@npm:1.4.11" +"@rspack/binding-linux-x64-gnu@npm:1.6.7": + version: 1.6.7 + resolution: "@rspack/binding-linux-x64-gnu@npm:1.6.7" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@rspack/binding-linux-x64-musl@npm:1.4.11": - version: 1.4.11 - resolution: "@rspack/binding-linux-x64-musl@npm:1.4.11" +"@rspack/binding-linux-x64-musl@npm:1.6.7": + version: 1.6.7 + resolution: "@rspack/binding-linux-x64-musl@npm:1.6.7" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@rspack/binding-wasm32-wasi@npm:1.4.11": - version: 1.4.11 - resolution: "@rspack/binding-wasm32-wasi@npm:1.4.11" +"@rspack/binding-wasm32-wasi@npm:1.6.7": + version: 1.6.7 + resolution: "@rspack/binding-wasm32-wasi@npm:1.6.7" dependencies: - "@napi-rs/wasm-runtime": "npm:^1.0.1" + "@napi-rs/wasm-runtime": "npm:1.0.7" conditions: cpu=wasm32 languageName: node linkType: hard -"@rspack/binding-win32-arm64-msvc@npm:1.4.11": - version: 1.4.11 - resolution: "@rspack/binding-win32-arm64-msvc@npm:1.4.11" +"@rspack/binding-win32-arm64-msvc@npm:1.6.7": + version: 1.6.7 + resolution: "@rspack/binding-win32-arm64-msvc@npm:1.6.7" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@rspack/binding-win32-ia32-msvc@npm:1.4.11": - version: 1.4.11 - resolution: "@rspack/binding-win32-ia32-msvc@npm:1.4.11" +"@rspack/binding-win32-ia32-msvc@npm:1.6.7": + version: 1.6.7 + resolution: "@rspack/binding-win32-ia32-msvc@npm:1.6.7" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@rspack/binding-win32-x64-msvc@npm:1.4.11": - version: 1.4.11 - resolution: "@rspack/binding-win32-x64-msvc@npm:1.4.11" +"@rspack/binding-win32-x64-msvc@npm:1.6.7": + version: 1.6.7 + resolution: "@rspack/binding-win32-x64-msvc@npm:1.6.7" conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"@rspack/binding@npm:1.4.11": - version: 1.4.11 - resolution: "@rspack/binding@npm:1.4.11" +"@rspack/binding@npm:1.6.7": + version: 1.6.7 + resolution: "@rspack/binding@npm:1.6.7" dependencies: - "@rspack/binding-darwin-arm64": "npm:1.4.11" - "@rspack/binding-darwin-x64": "npm:1.4.11" - "@rspack/binding-linux-arm64-gnu": "npm:1.4.11" - "@rspack/binding-linux-arm64-musl": "npm:1.4.11" - "@rspack/binding-linux-x64-gnu": "npm:1.4.11" - "@rspack/binding-linux-x64-musl": "npm:1.4.11" - "@rspack/binding-wasm32-wasi": "npm:1.4.11" - "@rspack/binding-win32-arm64-msvc": "npm:1.4.11" - "@rspack/binding-win32-ia32-msvc": "npm:1.4.11" - "@rspack/binding-win32-x64-msvc": "npm:1.4.11" + "@rspack/binding-darwin-arm64": "npm:1.6.7" + "@rspack/binding-darwin-x64": "npm:1.6.7" + "@rspack/binding-linux-arm64-gnu": "npm:1.6.7" + "@rspack/binding-linux-arm64-musl": "npm:1.6.7" + "@rspack/binding-linux-x64-gnu": "npm:1.6.7" + "@rspack/binding-linux-x64-musl": "npm:1.6.7" + "@rspack/binding-wasm32-wasi": "npm:1.6.7" + "@rspack/binding-win32-arm64-msvc": "npm:1.6.7" + "@rspack/binding-win32-ia32-msvc": "npm:1.6.7" + "@rspack/binding-win32-x64-msvc": "npm:1.6.7" dependenciesMeta: "@rspack/binding-darwin-arm64": optional: true @@ -16846,23 +17091,23 @@ __metadata: optional: true "@rspack/binding-win32-x64-msvc": optional: true - checksum: 10/8bb94774204f41888ff442afec06f019d008abba79964b74d566acf64f7216a148a1842f90c44b3bf680e69b697d8e5cd0f1cca6fd0b8a94df5f97c2a3f05510 + checksum: 10/80837f5cbdcac9eb6fb2213436baa3a5a841508340456c473e36bed2882197f456462db675b2d43cc1ed84d61109bae4bef0d474131a670113601ad80727769f languageName: node linkType: hard "@rspack/core@npm:^1.4.11": - version: 1.4.11 - resolution: "@rspack/core@npm:1.4.11" + version: 1.6.7 + resolution: "@rspack/core@npm:1.6.7" dependencies: - "@module-federation/runtime-tools": "npm:0.17.1" - "@rspack/binding": "npm:1.4.11" - "@rspack/lite-tapable": "npm:1.0.1" + "@module-federation/runtime-tools": "npm:0.21.6" + "@rspack/binding": "npm:1.6.7" + "@rspack/lite-tapable": "npm:1.1.0" peerDependencies: "@swc/helpers": ">=0.5.1" peerDependenciesMeta: "@swc/helpers": optional: true - checksum: 10/77d463bd90feb2d24f7bc56df198f0b7ad310a9eb676070eac8d78014d151e783943c5b44c64700a51a36708c626a341eeaa9b3287e358616d09dfe25ab04e77 + checksum: 10/c374d954c86a24dfba59b6e3c6388ce365723c83ea7012a6e95175b6245f7080b13e8560c25d744558e850c04a10d95fbe7ee92b4eabbd40a1ef578caf60615b languageName: node linkType: hard @@ -16881,16 +17126,16 @@ __metadata: languageName: node linkType: hard -"@rspack/lite-tapable@npm:1.0.1, @rspack/lite-tapable@npm:^1.0.1": - version: 1.0.1 - resolution: "@rspack/lite-tapable@npm:1.0.1" - checksum: 10/240b7832965bca5a52d1f03a8539dab5810958ce24b5a670405b2505d81350f10d668f4055648f5918bc18ac033e637bcb7f92189345f0f2f671b546019c2f9e +"@rspack/lite-tapable@npm:1.1.0, @rspack/lite-tapable@npm:^1.1.0": + version: 1.1.0 + resolution: "@rspack/lite-tapable@npm:1.1.0" + checksum: 10/41ff73fe5e1b8dccaad746c9c1bd36dd67649e1ad35776f311b5ba94333a397704e11158579e25a6a7e677c51abe35e66987b1b000faef48d4e4ad2470fea150 languageName: node linkType: hard "@rspack/plugin-react-refresh@npm:^1.4.3": - version: 1.4.3 - resolution: "@rspack/plugin-react-refresh@npm:1.4.3" + version: 1.5.3 + resolution: "@rspack/plugin-react-refresh@npm:1.5.3" dependencies: error-stack-parser: "npm:^2.1.4" html-entities: "npm:^2.6.0" @@ -16900,7 +17145,7 @@ __metadata: peerDependenciesMeta: webpack-hot-middleware: optional: true - checksum: 10/ddbe4268f0c5eb1e6c4384db16cad42628596ff7ca97707b5075be894f60bb87de2483fe2735129dc624380e46b7999735af7c418123a6bb2d01280ca5fea2c1 + checksum: 10/3886a13dca3d42e9245480283ab839c16015a48eceda0d7352114de26968e319e8f110c5ec4dbe4c20d4a8457b368401840c736ce49f774edd450cf3ba193f62 languageName: node linkType: hard @@ -17110,41 +17355,41 @@ __metadata: languageName: node linkType: hard -"@shikijs/engine-oniguruma@npm:^3.9.1": - version: 3.9.2 - resolution: "@shikijs/engine-oniguruma@npm:3.9.2" +"@shikijs/engine-oniguruma@npm:^3.17.1": + version: 3.18.0 + resolution: "@shikijs/engine-oniguruma@npm:3.18.0" dependencies: - "@shikijs/types": "npm:3.9.2" + "@shikijs/types": "npm:3.18.0" "@shikijs/vscode-textmate": "npm:^10.0.2" - checksum: 10/1ffb3501df871aea7fcafd9ed1cbe49e8897d479f90448fba892fd00aee7b2bd2a0afedabb0cb48e6038be91c7582d6aab98b95873f2fd38176be66c3160271b + checksum: 10/66fddeedd5e96b926ed06081dc678738b599c47da80e2f8809bd812398e9ba6e0fb00b7943a92e21c22c7aea2a813042bd936d28ee25901c58182e023122a176 languageName: node linkType: hard -"@shikijs/langs@npm:^3.9.1": - version: 3.9.2 - resolution: "@shikijs/langs@npm:3.9.2" +"@shikijs/langs@npm:^3.17.1": + version: 3.18.0 + resolution: "@shikijs/langs@npm:3.18.0" dependencies: - "@shikijs/types": "npm:3.9.2" - checksum: 10/eef3380d6296179280bebd742b586a7388cc120388e4dcff61dc93e71ee5dc50bc9219e7b579744f79f1132de0f141706fc8e5f3772c13a4ef62a3db2eb31744 + "@shikijs/types": "npm:3.18.0" + checksum: 10/6d872ea7d700081f4c021bea0692948443cb47f5664d5977ad902da953bdfaf71a2a5fba0e6d159ad279a37ce62fdb473698922495813c5dd2de2ecd8b3683c4 languageName: node linkType: hard -"@shikijs/themes@npm:^3.9.1": - version: 3.9.2 - resolution: "@shikijs/themes@npm:3.9.2" +"@shikijs/themes@npm:^3.17.1": + version: 3.18.0 + resolution: "@shikijs/themes@npm:3.18.0" dependencies: - "@shikijs/types": "npm:3.9.2" - checksum: 10/29836bdbc75560772472597eb173f0fbb07a7dbd161f854b89adcd6ed3a9aab46a829cb3919d4b519a2604dde1e0021a538917995e0d3f1efb608ce812f1338f + "@shikijs/types": "npm:3.18.0" + checksum: 10/6b5221a23042fd4ce2af60dc36f85b04615f962990cc8a1c6e8b0ca12c6af2fb7152b5c2e89213236436a46751cc746c98fbb7ca72ef9f1a950cf3c4ec10277a languageName: node linkType: hard -"@shikijs/types@npm:3.9.2, @shikijs/types@npm:^3.9.1": - version: 3.9.2 - resolution: "@shikijs/types@npm:3.9.2" +"@shikijs/types@npm:3.18.0, @shikijs/types@npm:^3.17.1": + version: 3.18.0 + resolution: "@shikijs/types@npm:3.18.0" dependencies: "@shikijs/vscode-textmate": "npm:^10.0.2" "@types/hast": "npm:^3.0.4" - checksum: 10/d21020066f12c618be759cdeb01984d8236bfa3aec96343e2886040748aaf3c7fe07a2cbeebe125afed3d57136dcae35eb28f2ba6985f0b6327cbc90ba387472 + checksum: 10/32a11448e716a31a6ef24483f6063fcb43243e6801fed235af25a7afc5ca23f9115616338e3cec3b64f6ec8bf6aa674571344636931331948da012269792a47d languageName: node linkType: hard @@ -17238,6 +17483,13 @@ __metadata: languageName: node linkType: hard +"@sinclair/typebox@npm:^0.34.0": + version: 0.34.41 + resolution: "@sinclair/typebox@npm:0.34.41" + checksum: 10/5c04a7f42156a7813a159947a0c3fe7e9f11aa722141ac3ff32242faf031b443ef71763d8791ce8d01bd5856770de51fd6fcda94b3a51558ba1f6d5112fa33f4 + languageName: node + linkType: hard + "@sindresorhus/is@npm:^0.14.0": version: 0.14.0 resolution: "@sindresorhus/is@npm:0.14.0" @@ -17286,21 +17538,12 @@ __metadata: languageName: node linkType: hard -"@sinonjs/fake-timers@npm:^10.0.2": - version: 10.3.0 - resolution: "@sinonjs/fake-timers@npm:10.3.0" - dependencies: - "@sinonjs/commons": "npm:^3.0.0" - checksum: 10/78155c7bd866a85df85e22028e046b8d46cf3e840f72260954f5e3ed5bd97d66c595524305a6841ffb3f681a08f6e5cef572a2cce5442a8a232dc29fb409b83e - languageName: node - linkType: hard - -"@sinonjs/fake-timers@npm:^13.0.1": - version: 13.0.2 - resolution: "@sinonjs/fake-timers@npm:13.0.2" +"@sinonjs/fake-timers@npm:^13.0.0, @sinonjs/fake-timers@npm:^13.0.1": + version: 13.0.5 + resolution: "@sinonjs/fake-timers@npm:13.0.5" dependencies: "@sinonjs/commons": "npm:^3.0.1" - checksum: 10/77cca5c548e2529931908c48ac375f162ee901bc52110197b4c470b2535c6c571f9ecd4fa12157f4d2ae174c5391f03940fb563a681a691fb44204a0ef3ded35 + checksum: 10/11ee417968fc4dce1896ab332ac13f353866075a9d2a88ed1f6258f17cc4f7d93e66031b51fcddb8c203aa4d53fd980b0ae18aba06269f4682164878a992ec3f languageName: node linkType: hard @@ -17391,10 +17634,10 @@ __metadata: languageName: node linkType: hard -"@slack/types@npm:^2.11.0, @slack/types@npm:^2.13.0, @slack/types@npm:^2.14.0, @slack/types@npm:^2.9.0": - version: 2.14.0 - resolution: "@slack/types@npm:2.14.0" - checksum: 10/fa24a113b88e087f899078504c2ba50ab9795f7c2dd1a2d95b28217a3af20e554494f9cc3b8c8ce173120990d98e19400c95369f9067cecfcc46c08b59d2a46f +"@slack/types@npm:^2.11.0, @slack/types@npm:^2.13.0, @slack/types@npm:^2.14.0, @slack/types@npm:^2.18.0": + version: 2.19.0 + resolution: "@slack/types@npm:2.19.0" + checksum: 10/d5fbc227147b32a964072cb46e2c328b896507a374194532ddf594e18e4ccc2afe9f31f2b92d14ace43ef856b22979523e565616be2c87a2dc6c575d4f919fd0 languageName: node linkType: hard @@ -17418,22 +17661,22 @@ __metadata: linkType: hard "@slack/web-api@npm:^7.5.0": - version: 7.9.3 - resolution: "@slack/web-api@npm:7.9.3" + version: 7.13.0 + resolution: "@slack/web-api@npm:7.13.0" dependencies: "@slack/logger": "npm:^4.0.0" - "@slack/types": "npm:^2.9.0" + "@slack/types": "npm:^2.18.0" "@types/node": "npm:>=18.0.0" "@types/retry": "npm:0.12.0" - axios: "npm:^1.8.3" + axios: "npm:^1.11.0" eventemitter3: "npm:^5.0.1" - form-data: "npm:^4.0.0" + form-data: "npm:^4.0.4" is-electron: "npm:2.2.2" is-stream: "npm:^2" p-queue: "npm:^6" p-retry: "npm:^4" retry: "npm:^0.13.1" - checksum: 10/dc8aa95c8127a1155f0c0756bc819185da0b471feb5953dc118301e577e67f45ad4ef64d9459ff430b44f769344a6347d1636ad59267483e9ac0104611263a05 + checksum: 10/9e254c372f1b4c3255acd317805f9dfabd38e90d0d8e96f2f79a35957d40d88eed5ba09ec59ae0838dbec32f99bd65ff2773c3528e44cd7aea273dd5e1fd3b82 languageName: node linkType: hard @@ -18539,19 +18782,6 @@ __metadata: languageName: node linkType: hard -"@snyk/github-codeowners@npm:1.1.0": - version: 1.1.0 - resolution: "@snyk/github-codeowners@npm:1.1.0" - dependencies: - commander: "npm:^4.1.1" - ignore: "npm:^5.1.8" - p-map: "npm:^4.0.0" - bin: - github-codeowners: dist/cli.js - checksum: 10/34120ef622616fef1ed8af12869d8c1803842aafa3fbacca263805ee7c85f58d11bdc301ef698c9b41268b275b9fd090f5d9f6d89c556abe9d52196e72d1c510 - languageName: node - linkType: hard - "@snyk/graphlib@npm:2.1.9-patch.3": version: 2.1.9-patch.3 resolution: "@snyk/graphlib@npm:2.1.9-patch.3" @@ -18575,6 +18805,16 @@ __metadata: languageName: node linkType: hard +"@so-ric/colorspace@npm:^1.1.6": + version: 1.1.6 + resolution: "@so-ric/colorspace@npm:1.1.6" + dependencies: + color: "npm:^5.0.2" + text-hex: "npm:1.0.x" + checksum: 10/fc3285e5cb9a458d255aa678d9453174ca40689a4c692f1617907996ab8eb78839542439604ced484c4f674a5297f7ba8b0e63fcfe901174f43c3d9c3c881b52 + languageName: node + linkType: hard + "@spotify/eslint-config-base@npm:^15.0.0": version: 15.0.0 resolution: "@spotify/eslint-config-base@npm:15.0.0" @@ -18892,82 +19132,121 @@ __metadata: languageName: node linkType: hard -"@storybook/addon-a11y@npm:^9.1.7": - version: 9.1.7 - resolution: "@storybook/addon-a11y@npm:9.1.7" +"@storybook/addon-a11y@npm:^10.1.9": + version: 10.1.9 + resolution: "@storybook/addon-a11y@npm:10.1.9" dependencies: "@storybook/global": "npm:^5.0.0" axe-core: "npm:^4.2.0" peerDependencies: - storybook: ^9.1.7 - checksum: 10/d62a623d3e185acef3ff6b1471db8f72d46685e3e612628f442193b35b12dc0e110ff197d0125a3e6749497917e703feaa047068aab6c37572e2dc0aa04fcc0f + storybook: ^10.1.9 + checksum: 10/d004f9975d20368ce58bb6c25bc421920ed6898ae2342a821776c41b6ed7597e41f7bfe932fc6be73f7611ba053cdcd63b18cf7c9ec0e5375a0c01fe45635b0f languageName: node linkType: hard -"@storybook/addon-docs@npm:^9.1.7": - version: 9.1.7 - resolution: "@storybook/addon-docs@npm:9.1.7" +"@storybook/addon-docs@npm:^10.1.9": + version: 10.1.9 + resolution: "@storybook/addon-docs@npm:10.1.9" dependencies: "@mdx-js/react": "npm:^3.0.0" - "@storybook/csf-plugin": "npm:9.1.7" - "@storybook/icons": "npm:^1.4.0" - "@storybook/react-dom-shim": "npm:9.1.7" + "@storybook/csf-plugin": "npm:10.1.9" + "@storybook/icons": "npm:^2.0.0" + "@storybook/react-dom-shim": "npm:10.1.9" react: "npm:^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" react-dom: "npm:^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" ts-dedent: "npm:^2.0.0" peerDependencies: - storybook: ^9.1.7 - checksum: 10/89a26ba462c2f7498159fecb6f66a47fbc68675f80906b10420594553c10de0ad871429f3124efb0cefd06bc8ceca3f12c17334d6e796bf7f094b4c29fd61aae + storybook: ^10.1.9 + checksum: 10/4f24aa255b2cc3c5ad1560730e40aba5f2019a8069456e1f03043cf67de14cbb9ac26650eb805fddb6395182db62d850df127fc310a1fff49c39cf166a63aa02 languageName: node linkType: hard -"@storybook/addon-links@npm:^9.1.7": - version: 9.1.7 - resolution: "@storybook/addon-links@npm:9.1.7" +"@storybook/addon-links@npm:^10.1.9": + version: 10.1.9 + resolution: "@storybook/addon-links@npm:10.1.9" dependencies: "@storybook/global": "npm:^5.0.0" peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^9.1.7 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + storybook: ^10.1.9 peerDependenciesMeta: react: optional: true - checksum: 10/487f3055ce1a87984794d195fdf8eb4c19c5c8263dc94d16fde310eb97a9785b311b81d5bc8ce07e31a8b0a7cff29eb58f718152b87b5746ec0f529c021f698b + checksum: 10/c0f9c97b64dd50e0ea0642eb75e2f7af81548958aeef35e1d44992c7d85ee8796cc034088aebba5e81b760932e064e39b7bdc64f572bbd68d237f6870c95f52e languageName: node linkType: hard -"@storybook/addon-themes@npm:^9.1.7": - version: 9.1.7 - resolution: "@storybook/addon-themes@npm:9.1.7" +"@storybook/addon-themes@npm:^10.1.9": + version: 10.1.9 + resolution: "@storybook/addon-themes@npm:10.1.9" dependencies: ts-dedent: "npm:^2.0.0" peerDependencies: - storybook: ^9.1.7 - checksum: 10/3a57c3b2265e775c2fc0cee3c8f4b3189915c9dc8001f74351d427094739501112842fb02e94893c3290aec0bdea64fbc00374b8f7095da39765844ae51c5df3 + storybook: ^10.1.9 + checksum: 10/66d231efb94919aa89bbb92291925d96519c993d6d75326850caad432a1425c4aa93b4249bf46fffc5b41724ef007d01477045a74e55e937410d8fa7be7037f6 languageName: node linkType: hard -"@storybook/builder-vite@npm:9.1.7": - version: 9.1.7 - resolution: "@storybook/builder-vite@npm:9.1.7" +"@storybook/addon-vitest@npm:^10.1.9": + version: 10.1.9 + resolution: "@storybook/addon-vitest@npm:10.1.9" dependencies: - "@storybook/csf-plugin": "npm:9.1.7" + "@storybook/global": "npm:^5.0.0" + "@storybook/icons": "npm:^2.0.0" + peerDependencies: + "@vitest/browser": ^3.0.0 || ^4.0.0 + "@vitest/browser-playwright": ^4.0.0 + "@vitest/runner": ^3.0.0 || ^4.0.0 + storybook: ^10.1.9 + vitest: ^3.0.0 || ^4.0.0 + peerDependenciesMeta: + "@vitest/browser": + optional: true + "@vitest/browser-playwright": + optional: true + "@vitest/runner": + optional: true + vitest: + optional: true + checksum: 10/8d1be8902a243d6c42a84d0acd1550014e5fa6cb509cdfbec6603e6b3d34def5f28d483f8d4289ef7be87d48f41a47f34f4f7028eef7add49cec5d98cf477a0d + languageName: node + linkType: hard + +"@storybook/builder-vite@npm:10.1.9": + version: 10.1.9 + resolution: "@storybook/builder-vite@npm:10.1.9" + dependencies: + "@storybook/csf-plugin": "npm:10.1.9" + "@vitest/mocker": "npm:3.2.4" ts-dedent: "npm:^2.0.0" peerDependencies: - storybook: ^9.1.7 + storybook: ^10.1.9 vite: ^5.0.0 || ^6.0.0 || ^7.0.0 - checksum: 10/f285896e8103ded0c81d1b89d500179e83088b6d1e82b9deca9b5e03b209b68c89d5735ffc0a3a5ac30a3f4c847b361de0289523f0a39c0585fbc82d516c298e + checksum: 10/4dc086193b45219b24e528404ed51c4dbc240a9ac20feeef88a1b051ae286264006741b402f4936745f5733c8b568e090b029aaea73bf5e3a078047aa957f8ba languageName: node linkType: hard -"@storybook/csf-plugin@npm:9.1.7": - version: 9.1.7 - resolution: "@storybook/csf-plugin@npm:9.1.7" +"@storybook/csf-plugin@npm:10.1.9": + version: 10.1.9 + resolution: "@storybook/csf-plugin@npm:10.1.9" dependencies: - unplugin: "npm:^1.3.1" + unplugin: "npm:^2.3.5" peerDependencies: - storybook: ^9.1.7 - checksum: 10/d90d3b410c74e893d0b51179fd1357fba0df7410da4e04b55c373705eca7e48bad4e2062be9a201b0c764b3821a7208b06bc5469e00079ee8b00b86d6fbb6f4e + esbuild: "*" + rollup: "*" + storybook: ^10.1.9 + vite: "*" + webpack: "*" + peerDependenciesMeta: + esbuild: + optional: true + rollup: + optional: true + vite: + optional: true + webpack: + optional: true + checksum: 10/604339107f7bd57f64b5b0d9ddc16a447fc0987d348cb9add5bb2fc75b568760afb3689cd51c73df48cc13bf2d82386f89da57e53f500687434d403cd7395e49 languageName: node linkType: hard @@ -18978,392 +19257,393 @@ __metadata: languageName: node linkType: hard -"@storybook/icons@npm:^1.4.0": - version: 1.4.0 - resolution: "@storybook/icons@npm:1.4.0" +"@storybook/icons@npm:^2.0.0": + version: 2.0.1 + resolution: "@storybook/icons@npm:2.0.1" peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - checksum: 10/513d36188bb84f1f64dd982b6bd577de4c3d7bc2aa9d318a2acf8c654d16994bac0b669787a4ced6720e471251bcb0ec68b8d8dc2cc7245d11102bd617243700 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + checksum: 10/04ffa285f4defc611def51f82492688bc49f6f4e8ce4e7ba5c99a1c1410b7e8820b5da65c33610a497df2409de7b48fae399052c5cacab6a4a4a9b48a36ebfd5 languageName: node linkType: hard -"@storybook/react-dom-shim@npm:9.1.7": - version: 9.1.7 - resolution: "@storybook/react-dom-shim@npm:9.1.7" +"@storybook/react-dom-shim@npm:10.1.9": + version: 10.1.9 + resolution: "@storybook/react-dom-shim@npm:10.1.9" peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^9.1.7 - checksum: 10/3d909506dea4f1927698ca3f9d9d49680d4d3f7fb8f14125f5f9a2f1a0a4fca4759f82ef29fbeb5afc50aabb8f66179a4ea6409ccb91c294aba8701028c61d08 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + storybook: ^10.1.9 + checksum: 10/2b6e598eb8ddac80fd6cd4d888b3a8da1c352e9ffc666a1bcce6f4ac404c77cc75571a57b433e1a12f34cfd255db31fb399a7f38e70bde5d197de2d072eeac85 languageName: node linkType: hard -"@storybook/react-vite@npm:^9.1.7": - version: 9.1.7 - resolution: "@storybook/react-vite@npm:9.1.7" +"@storybook/react-vite@npm:^10.1.9": + version: 10.1.9 + resolution: "@storybook/react-vite@npm:10.1.9" dependencies: - "@joshwooding/vite-plugin-react-docgen-typescript": "npm:0.6.1" + "@joshwooding/vite-plugin-react-docgen-typescript": "npm:^0.6.3" "@rollup/pluginutils": "npm:^5.0.2" - "@storybook/builder-vite": "npm:9.1.7" - "@storybook/react": "npm:9.1.7" - find-up: "npm:^7.0.0" + "@storybook/builder-vite": "npm:10.1.9" + "@storybook/react": "npm:10.1.9" + empathic: "npm:^2.0.0" magic-string: "npm:^0.30.0" react-docgen: "npm:^8.0.0" resolve: "npm:^1.22.8" tsconfig-paths: "npm:^4.2.0" peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^9.1.7 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + storybook: ^10.1.9 vite: ^5.0.0 || ^6.0.0 || ^7.0.0 - checksum: 10/6e676ef8c34179d2cad2afb5c952130bd770d362828f5a10481d44a13e0938c34843d2a3914921acd539adf1c0d5c2108881344a6d68bc3a5d4baf55d4b0a317 + checksum: 10/e55978b8eaee2f5d9a7b30c2547d3f29497468c0bac5f20308633554f381d066d2f0549a4997d9ec29693f018d6889d9b9c4bfb4b2e822c4730999fa1605c573 languageName: node linkType: hard -"@storybook/react@npm:9.1.7": - version: 9.1.7 - resolution: "@storybook/react@npm:9.1.7" +"@storybook/react@npm:10.1.9": + version: 10.1.9 + resolution: "@storybook/react@npm:10.1.9" dependencies: "@storybook/global": "npm:^5.0.0" - "@storybook/react-dom-shim": "npm:9.1.7" + "@storybook/react-dom-shim": "npm:10.1.9" + react-docgen: "npm:^8.0.2" peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^9.1.7 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + storybook: ^10.1.9 typescript: ">= 4.9.x" peerDependenciesMeta: typescript: optional: true - checksum: 10/691b4204e0fa405e071b77996c9ee18c17250733c6239b6f7361d3803f8da90a4fc7288364dea841aaa0ad1a78f931589ec443fdaf2bfe6ad340856648251c4e + checksum: 10/964f5a3b77638597289c72be0991323fcbe0f5d7451b5c7bceac7e998dd819897936fb486e38d0b70e42507ca6895850d9a484acc8d171a6ecbd9ce41a0b19ad languageName: node linkType: hard -"@swagger-api/apidom-ast@npm:^1.0.0-beta.48": - version: 1.0.0-beta.48 - resolution: "@swagger-api/apidom-ast@npm:1.0.0-beta.48" +"@swagger-api/apidom-ast@npm:^1.0.0-rc.4": + version: 1.0.0-rc.4 + resolution: "@swagger-api/apidom-ast@npm:1.0.0-rc.4" dependencies: "@babel/runtime-corejs3": "npm:^7.26.10" - "@swagger-api/apidom-error": "npm:^1.0.0-beta.48" + "@swagger-api/apidom-error": "npm:^1.0.0-rc.4" "@types/ramda": "npm:~0.30.0" ramda: "npm:~0.30.0" ramda-adjunct: "npm:^5.0.0" unraw: "npm:^3.0.0" - checksum: 10/b3f2b91df2b9116db318ce44551d3846453b7d9f17eb809c19890ecbbc17166ad6a1fa54698b79e85600960e2f1dd2ea56487d9a50537ee362a1a9dd63f91840 + checksum: 10/77be60bd4085525de506eb31a4f67de7850296534b98cb981db5a9e3ac8ebe07b92cb6ff8edacc5f199373f8dab9bc845b6695ae4a40dc15d0e05a05c8b3041f languageName: node linkType: hard -"@swagger-api/apidom-core@npm:>=1.0.0-beta.41 <1.0.0-rc.0, @swagger-api/apidom-core@npm:^1.0.0-beta.48": - version: 1.0.0-beta.48 - resolution: "@swagger-api/apidom-core@npm:1.0.0-beta.48" +"@swagger-api/apidom-core@npm:^1.0.0-rc.1, @swagger-api/apidom-core@npm:^1.0.0-rc.4": + version: 1.0.0-rc.4 + resolution: "@swagger-api/apidom-core@npm:1.0.0-rc.4" dependencies: "@babel/runtime-corejs3": "npm:^7.26.10" - "@swagger-api/apidom-ast": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-error": "npm:^1.0.0-beta.48" + "@swagger-api/apidom-ast": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-error": "npm:^1.0.0-rc.4" "@types/ramda": "npm:~0.30.0" minim: "npm:~0.23.8" ramda: "npm:~0.30.0" ramda-adjunct: "npm:^5.0.0" short-unique-id: "npm:^5.3.2" ts-mixer: "npm:^6.0.3" - checksum: 10/abf7328a4d821f6083daa80fe1e719511825ff855dc4be59a4147a100c1ae34254cba4050ecc29e5147877f7e9d797681e96931da0ce432c310aaae82cd5a371 + checksum: 10/73763b2888aa1e7642dd08192fa91a6c5049575856bb6916333bf194f1798706b424e38efd39d9729ce95ec1fe545407c6ec3a9212e360d57af02f003f077643 languageName: node linkType: hard -"@swagger-api/apidom-error@npm:>=1.0.0-beta.41 <1.0.0-rc.0, @swagger-api/apidom-error@npm:^1.0.0-beta.48": - version: 1.0.0-beta.48 - resolution: "@swagger-api/apidom-error@npm:1.0.0-beta.48" +"@swagger-api/apidom-error@npm:^1.0.0-rc.1, @swagger-api/apidom-error@npm:^1.0.0-rc.4": + version: 1.0.0-rc.4 + resolution: "@swagger-api/apidom-error@npm:1.0.0-rc.4" dependencies: "@babel/runtime-corejs3": "npm:^7.20.7" - checksum: 10/ce6461f5b06a6297074949d1aabd605c272c3061241e4d47f3720707ac8bc41c272deed033ae131fb5620bd6d709e0744275353ed490f7eca81f75db94abfc7e + checksum: 10/dfbc2e9d570eb15e925a4eb0dd4e59f8d5a01cfda4a78dd83320c71f3406082b73a6ea2b61229730a3830a707fdb94b17b3b0cb0ffaf45699917434b36971409 languageName: node linkType: hard -"@swagger-api/apidom-json-pointer@npm:>=1.0.0-beta.41 <1.0.0-rc.0, @swagger-api/apidom-json-pointer@npm:^1.0.0-beta.40 <1.0.0-rc.0, @swagger-api/apidom-json-pointer@npm:^1.0.0-beta.48": - version: 1.0.0-beta.48 - resolution: "@swagger-api/apidom-json-pointer@npm:1.0.0-beta.48" +"@swagger-api/apidom-json-pointer@npm:^1.0.0-rc.0, @swagger-api/apidom-json-pointer@npm:^1.0.0-rc.1, @swagger-api/apidom-json-pointer@npm:^1.0.0-rc.4": + version: 1.0.0-rc.4 + resolution: "@swagger-api/apidom-json-pointer@npm:1.0.0-rc.4" dependencies: "@babel/runtime-corejs3": "npm:^7.26.10" - "@swagger-api/apidom-core": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-error": "npm:^1.0.0-beta.48" + "@swagger-api/apidom-core": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-error": "npm:^1.0.0-rc.4" "@swaggerexpert/json-pointer": "npm:^2.10.1" - checksum: 10/2075f4d64813128ee80da21f16fd96bc51cf232505d920fc77af86acd2ea1db342936753b824153b232e9522d4a7f389fd870afdf3518b0af91f497119b6e1c5 + checksum: 10/cd8ea73069934422a7c48a3ca6a61201e3acfc35cd8cb8df016c4bcfb655b6ba21abee5011edbe4cc1fa83076e1d1c3031d8e9384b3e0b2e6e0b103fa3ea96cc languageName: node linkType: hard -"@swagger-api/apidom-ns-api-design-systems@npm:^1.0.0-beta.48": - version: 1.0.0-beta.48 - resolution: "@swagger-api/apidom-ns-api-design-systems@npm:1.0.0-beta.48" +"@swagger-api/apidom-ns-api-design-systems@npm:^1.0.0-rc.4": + version: 1.0.0-rc.4 + resolution: "@swagger-api/apidom-ns-api-design-systems@npm:1.0.0-rc.4" dependencies: "@babel/runtime-corejs3": "npm:^7.26.10" - "@swagger-api/apidom-core": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-error": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-ns-openapi-3-1": "npm:^1.0.0-beta.48" + "@swagger-api/apidom-core": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-error": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-ns-openapi-3-1": "npm:^1.0.0-rc.4" "@types/ramda": "npm:~0.30.0" ramda: "npm:~0.30.0" ramda-adjunct: "npm:^5.0.0" ts-mixer: "npm:^6.0.3" - checksum: 10/48e6a4f323572715f8990f83f6a1617af9d7ca0c6cd0e08f9b05c6f178664da233498c7c2461f636a97a525aaa60748c1da2a8d949ed43a7a14c1639d382f737 + checksum: 10/e30c5da34485eeb62be9b37ccc58bc11d2f4559799369a391157c42b2ff5bbb46e9a931b9e0dcd856912ad4078bc2631f6b272464e77709fdfd8c1725c780d3f languageName: node linkType: hard -"@swagger-api/apidom-ns-arazzo-1@npm:^1.0.0-beta.40 <1.0.0-rc.0, @swagger-api/apidom-ns-arazzo-1@npm:^1.0.0-beta.48": - version: 1.0.0-beta.48 - resolution: "@swagger-api/apidom-ns-arazzo-1@npm:1.0.0-beta.48" +"@swagger-api/apidom-ns-arazzo-1@npm:^1.0.0-rc.0, @swagger-api/apidom-ns-arazzo-1@npm:^1.0.0-rc.4": + version: 1.0.0-rc.4 + resolution: "@swagger-api/apidom-ns-arazzo-1@npm:1.0.0-rc.4" dependencies: "@babel/runtime-corejs3": "npm:^7.26.10" - "@swagger-api/apidom-core": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-ns-json-schema-2020-12": "npm:^1.0.0-beta.48" + "@swagger-api/apidom-core": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-ns-json-schema-2020-12": "npm:^1.0.0-rc.4" "@types/ramda": "npm:~0.30.0" ramda: "npm:~0.30.0" ramda-adjunct: "npm:^5.0.0" ts-mixer: "npm:^6.0.3" - checksum: 10/3b9f60ec9ca9dccc5e3d46a48a6d7b30915294bdb7dc6ee481aae57de707485885f887ad9b9daec469712c087e6d74ed748ac8d748ed6d19cb1fb6219141bb12 + checksum: 10/4c56afb584d79e7be530b5aba31cf4556d5fbefeafcd8d25c03fa74d895bafb99e8c9d266c3b09f06758c7bbcff6a1367105240e238cd56312e83e1f8393430c languageName: node linkType: hard -"@swagger-api/apidom-ns-asyncapi-2@npm:^1.0.0-beta.40 <1.0.0-rc.0, @swagger-api/apidom-ns-asyncapi-2@npm:^1.0.0-beta.48": - version: 1.0.0-beta.48 - resolution: "@swagger-api/apidom-ns-asyncapi-2@npm:1.0.0-beta.48" +"@swagger-api/apidom-ns-asyncapi-2@npm:^1.0.0-rc.0, @swagger-api/apidom-ns-asyncapi-2@npm:^1.0.0-rc.4": + version: 1.0.0-rc.4 + resolution: "@swagger-api/apidom-ns-asyncapi-2@npm:1.0.0-rc.4" dependencies: "@babel/runtime-corejs3": "npm:^7.26.10" - "@swagger-api/apidom-core": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-ns-json-schema-draft-7": "npm:^1.0.0-beta.48" + "@swagger-api/apidom-core": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-ns-json-schema-draft-7": "npm:^1.0.0-rc.4" "@types/ramda": "npm:~0.30.0" ramda: "npm:~0.30.0" ramda-adjunct: "npm:^5.0.0" ts-mixer: "npm:^6.0.3" - checksum: 10/99bcd30eb7c14334b2ebe3adfdb7ad8cf93d9565fc72217863a82b1ba48d4b5839b639964cf830bf9ba64c41c7a7d7eedeb53d8d28e5379bde1fafa8b424ab02 + checksum: 10/94ea647db429877c914dc6449165570ea13233d81f9b3b28f6d5d035b7cccdd53f7bf50279ad97b42a91f20d109d50a040e32fa571b1a1f5793e339e4426c6db languageName: node linkType: hard -"@swagger-api/apidom-ns-json-schema-2019-09@npm:^1.0.0-beta.48": - version: 1.0.0-beta.48 - resolution: "@swagger-api/apidom-ns-json-schema-2019-09@npm:1.0.0-beta.48" +"@swagger-api/apidom-ns-json-schema-2019-09@npm:^1.0.0-rc.4": + version: 1.0.0-rc.4 + resolution: "@swagger-api/apidom-ns-json-schema-2019-09@npm:1.0.0-rc.4" dependencies: "@babel/runtime-corejs3": "npm:^7.26.10" - "@swagger-api/apidom-core": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-error": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-ns-json-schema-draft-7": "npm:^1.0.0-beta.48" + "@swagger-api/apidom-core": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-error": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-ns-json-schema-draft-7": "npm:^1.0.0-rc.4" "@types/ramda": "npm:~0.30.0" ramda: "npm:~0.30.0" ramda-adjunct: "npm:^5.0.0" ts-mixer: "npm:^6.0.4" - checksum: 10/bed0ed8b2ef35def9da2b8cebb31dba0d83fab88a38ab1a1af4760d370f5b3d0a1dfda7f1f1991204eab97531ddc90c70c153cb3ba9a7a5b93be93f02d873097 + checksum: 10/8760f7252a31eaed22417f3f181e1f29f25c9100044a78b4f1c3690ddc6402845ba5c90ee98297dc56f7b3d3758c4fb086c53c204b7d1c8f87faebdf57654ea5 languageName: node linkType: hard -"@swagger-api/apidom-ns-json-schema-2020-12@npm:^1.0.0-beta.48": - version: 1.0.0-beta.48 - resolution: "@swagger-api/apidom-ns-json-schema-2020-12@npm:1.0.0-beta.48" +"@swagger-api/apidom-ns-json-schema-2020-12@npm:^1.0.0-rc.4": + version: 1.0.0-rc.4 + resolution: "@swagger-api/apidom-ns-json-schema-2020-12@npm:1.0.0-rc.4" dependencies: "@babel/runtime-corejs3": "npm:^7.26.10" - "@swagger-api/apidom-core": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-error": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-ns-json-schema-2019-09": "npm:^1.0.0-beta.48" + "@swagger-api/apidom-core": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-error": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-ns-json-schema-2019-09": "npm:^1.0.0-rc.4" "@types/ramda": "npm:~0.30.0" ramda: "npm:~0.30.0" ramda-adjunct: "npm:^5.0.0" ts-mixer: "npm:^6.0.4" - checksum: 10/6bfad975a9db33224bc980edafab8e39218d6eb0acc384881ba14b35061d2c51b45f3e778529f5cf5875330501c892f433319dc4613a2d08ae22cf33f832d91e + checksum: 10/05d31abb732435cfbdc6cc46332f4a2d90462e11c103fefa22f669827c99916363bc569adce0fcbbe52c51061c490006f8ca20bd1420ecfea680ad35589f8390 languageName: node linkType: hard -"@swagger-api/apidom-ns-json-schema-draft-4@npm:^1.0.0-beta.48": - version: 1.0.0-beta.48 - resolution: "@swagger-api/apidom-ns-json-schema-draft-4@npm:1.0.0-beta.48" +"@swagger-api/apidom-ns-json-schema-draft-4@npm:^1.0.0-rc.4": + version: 1.0.0-rc.4 + resolution: "@swagger-api/apidom-ns-json-schema-draft-4@npm:1.0.0-rc.4" dependencies: "@babel/runtime-corejs3": "npm:^7.26.10" - "@swagger-api/apidom-ast": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-core": "npm:^1.0.0-beta.48" + "@swagger-api/apidom-ast": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-core": "npm:^1.0.0-rc.4" "@types/ramda": "npm:~0.30.0" ramda: "npm:~0.30.0" ramda-adjunct: "npm:^5.0.0" ts-mixer: "npm:^6.0.4" - checksum: 10/860c09c46b6ef274afeaf4fb5aa0445dd9d394fb81f3d251d34c484ce31ca568e8d8e63acdfd207180dc28ac1a6fe082fe7139dbe1aadac2e5b81f42f80aefcd + checksum: 10/37223af3cf5e6feff7021e40129eacda2f89f7a176466bfdef12f2785b8963a4583ff8466215af7b2f7508515c29baa86a549ee1449a7b40afee7c84c27f5ec8 languageName: node linkType: hard -"@swagger-api/apidom-ns-json-schema-draft-6@npm:^1.0.0-beta.48": - version: 1.0.0-beta.48 - resolution: "@swagger-api/apidom-ns-json-schema-draft-6@npm:1.0.0-beta.48" +"@swagger-api/apidom-ns-json-schema-draft-6@npm:^1.0.0-rc.4": + version: 1.0.0-rc.4 + resolution: "@swagger-api/apidom-ns-json-schema-draft-6@npm:1.0.0-rc.4" dependencies: "@babel/runtime-corejs3": "npm:^7.26.10" - "@swagger-api/apidom-core": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-error": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-ns-json-schema-draft-4": "npm:^1.0.0-beta.48" + "@swagger-api/apidom-core": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-error": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-ns-json-schema-draft-4": "npm:^1.0.0-rc.4" "@types/ramda": "npm:~0.30.0" ramda: "npm:~0.30.0" ramda-adjunct: "npm:^5.0.0" ts-mixer: "npm:^6.0.4" - checksum: 10/418d8c1cf20cc12841ee1d7e17bc57cbfa296d7833d4f656c650fcb5ade4bd646088177c9cc1c682b2ebd80fb3713de02b8dc562d155e3874c482e9d0d4edcc2 + checksum: 10/9294144d88e1bac74f26c99c3b7b1a0dacdf5e7823360d6ae18918c67a20ae42b297c00b4d641a803bd90ad6c1e42390b4d1ef1de5916becead4fee1e4c0507c languageName: node linkType: hard -"@swagger-api/apidom-ns-json-schema-draft-7@npm:^1.0.0-beta.48": - version: 1.0.0-beta.48 - resolution: "@swagger-api/apidom-ns-json-schema-draft-7@npm:1.0.0-beta.48" +"@swagger-api/apidom-ns-json-schema-draft-7@npm:^1.0.0-rc.4": + version: 1.0.0-rc.4 + resolution: "@swagger-api/apidom-ns-json-schema-draft-7@npm:1.0.0-rc.4" dependencies: "@babel/runtime-corejs3": "npm:^7.26.10" - "@swagger-api/apidom-core": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-error": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-ns-json-schema-draft-6": "npm:^1.0.0-beta.48" + "@swagger-api/apidom-core": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-error": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-ns-json-schema-draft-6": "npm:^1.0.0-rc.4" "@types/ramda": "npm:~0.30.0" ramda: "npm:~0.30.0" ramda-adjunct: "npm:^5.0.0" ts-mixer: "npm:^6.0.4" - checksum: 10/6e683458465f221c490440f94a1d1328a39db87a27c257a5d700b2effc937b8568f98f5042d74f56fdf6692da4b4027074c33c59348199fc821c45de9598e473 + checksum: 10/53111c3c6f3ba7ae21863b70afdd0eeea4db9b571602c9ec79e4525aaaa83dde32907c8a05ce658e5244b4400ff554dc7aca9c73a9a1b91cfffecf0f09bf4f48 languageName: node linkType: hard -"@swagger-api/apidom-ns-openapi-2@npm:^1.0.0-beta.40 <1.0.0-rc.0, @swagger-api/apidom-ns-openapi-2@npm:^1.0.0-beta.48": - version: 1.0.0-beta.48 - resolution: "@swagger-api/apidom-ns-openapi-2@npm:1.0.0-beta.48" +"@swagger-api/apidom-ns-openapi-2@npm:^1.0.0-rc.0, @swagger-api/apidom-ns-openapi-2@npm:^1.0.0-rc.4": + version: 1.0.0-rc.4 + resolution: "@swagger-api/apidom-ns-openapi-2@npm:1.0.0-rc.4" dependencies: "@babel/runtime-corejs3": "npm:^7.26.10" - "@swagger-api/apidom-core": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-error": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-ns-json-schema-draft-4": "npm:^1.0.0-beta.48" + "@swagger-api/apidom-core": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-error": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-ns-json-schema-draft-4": "npm:^1.0.0-rc.4" "@types/ramda": "npm:~0.30.0" ramda: "npm:~0.30.0" ramda-adjunct: "npm:^5.0.0" ts-mixer: "npm:^6.0.3" - checksum: 10/768fb7ec2c8506857837975529f311fe28359dd56a836c3b3cb1685bed623c489b5327e5fe58a41e70235ba525ba6401cc32fc9bd50bc5ec1cc0baf6fe144900 + checksum: 10/42dbedf81c96c2e3e851b234777772e8662cf4957f3d1cc81dac0356a33840652e61011133fd404b0465f3a238451878cdb53182f9d295d53ff6a3e97ed94265 languageName: node linkType: hard -"@swagger-api/apidom-ns-openapi-3-0@npm:^1.0.0-beta.40 <1.0.0-rc.0, @swagger-api/apidom-ns-openapi-3-0@npm:^1.0.0-beta.48": - version: 1.0.0-beta.48 - resolution: "@swagger-api/apidom-ns-openapi-3-0@npm:1.0.0-beta.48" +"@swagger-api/apidom-ns-openapi-3-0@npm:^1.0.0-rc.0, @swagger-api/apidom-ns-openapi-3-0@npm:^1.0.0-rc.4": + version: 1.0.0-rc.4 + resolution: "@swagger-api/apidom-ns-openapi-3-0@npm:1.0.0-rc.4" dependencies: "@babel/runtime-corejs3": "npm:^7.26.10" - "@swagger-api/apidom-core": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-error": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-ns-json-schema-draft-4": "npm:^1.0.0-beta.48" + "@swagger-api/apidom-core": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-error": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-ns-json-schema-draft-4": "npm:^1.0.0-rc.4" "@types/ramda": "npm:~0.30.0" ramda: "npm:~0.30.0" ramda-adjunct: "npm:^5.0.0" ts-mixer: "npm:^6.0.3" - checksum: 10/a005d660c2e476a3d1bb74da9a2efa7fb0a68b1f52ddbde01514f4db9ef14051833f55b001c812da44fce3445c145ce5fd62a137477a71a6bcad220115c1e440 + checksum: 10/91211128aa583a1d155789e4e7e5a5fc7a7adc1fc69f836e5b742168d7f60e2c3a961ab449b5cbf47c803e536cf3490ff4ce44608d9834c2d06eeb9eb0b3feef languageName: node linkType: hard -"@swagger-api/apidom-ns-openapi-3-1@npm:>=1.0.0-beta.41 <1.0.0-rc.0, @swagger-api/apidom-ns-openapi-3-1@npm:^1.0.0-beta.40 <1.0.0-rc.0, @swagger-api/apidom-ns-openapi-3-1@npm:^1.0.0-beta.48": - version: 1.0.0-beta.48 - resolution: "@swagger-api/apidom-ns-openapi-3-1@npm:1.0.0-beta.48" +"@swagger-api/apidom-ns-openapi-3-1@npm:^1.0.0-rc.0, @swagger-api/apidom-ns-openapi-3-1@npm:^1.0.0-rc.1, @swagger-api/apidom-ns-openapi-3-1@npm:^1.0.0-rc.4": + version: 1.0.0-rc.4 + resolution: "@swagger-api/apidom-ns-openapi-3-1@npm:1.0.0-rc.4" dependencies: "@babel/runtime-corejs3": "npm:^7.26.10" - "@swagger-api/apidom-ast": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-core": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-json-pointer": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-ns-json-schema-2020-12": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-ns-openapi-3-0": "npm:^1.0.0-beta.48" + "@swagger-api/apidom-ast": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-core": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-json-pointer": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-ns-json-schema-2020-12": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-ns-openapi-3-0": "npm:^1.0.0-rc.4" "@types/ramda": "npm:~0.30.0" ramda: "npm:~0.30.0" ramda-adjunct: "npm:^5.0.0" ts-mixer: "npm:^6.0.3" - checksum: 10/3423b3d642487d562376a572dac31fec760d3a64fe8bb4065ee0634a340c418656b2ea9cfc484059db5105e7389c74ac32620413243990141a7bbdc2e7cb1062 + checksum: 10/11739023a16d5aa41766aa24d094799e41b80644b4129ea3df9d606343abc6215f0350062ccb709d5361b7f2e1f516d0f2fea7c53cd1a938b1d4c2f859ac1a4b languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-api-design-systems-json@npm:^1.0.0-beta.40 <1.0.0-rc.0": - version: 1.0.0-beta.48 - resolution: "@swagger-api/apidom-parser-adapter-api-design-systems-json@npm:1.0.0-beta.48" +"@swagger-api/apidom-parser-adapter-api-design-systems-json@npm:^1.0.0-rc.0": + version: 1.0.0-rc.4 + resolution: "@swagger-api/apidom-parser-adapter-api-design-systems-json@npm:1.0.0-rc.4" dependencies: "@babel/runtime-corejs3": "npm:^7.26.10" - "@swagger-api/apidom-core": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-ns-api-design-systems": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-parser-adapter-json": "npm:^1.0.0-beta.48" + "@swagger-api/apidom-core": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-ns-api-design-systems": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-parser-adapter-json": "npm:^1.0.0-rc.4" "@types/ramda": "npm:~0.30.0" ramda: "npm:~0.30.0" ramda-adjunct: "npm:^5.0.0" - checksum: 10/ac86988052a7ad9f03c389cef02b22da36d6cbaae6c670c7642615de7f6efe921b3991f14a55793f803e5b5cb9eb0bcda30857a70a0a0d1c31d8f2d8023e78c6 + checksum: 10/edb734b20658354c865cc6b12315450be0d7ac340fce80185cab8f476ae9ec8983d13042788132f24ff9b32c4edf292d28c1e88a1652b927ec6e6c4679f7cce1 languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-api-design-systems-yaml@npm:^1.0.0-beta.40 <1.0.0-rc.0": - version: 1.0.0-beta.48 - resolution: "@swagger-api/apidom-parser-adapter-api-design-systems-yaml@npm:1.0.0-beta.48" +"@swagger-api/apidom-parser-adapter-api-design-systems-yaml@npm:^1.0.0-rc.0": + version: 1.0.0-rc.4 + resolution: "@swagger-api/apidom-parser-adapter-api-design-systems-yaml@npm:1.0.0-rc.4" dependencies: "@babel/runtime-corejs3": "npm:^7.26.10" - "@swagger-api/apidom-core": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-ns-api-design-systems": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-parser-adapter-yaml-1-2": "npm:^1.0.0-beta.48" + "@swagger-api/apidom-core": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-ns-api-design-systems": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-parser-adapter-yaml-1-2": "npm:^1.0.0-rc.4" "@types/ramda": "npm:~0.30.0" ramda: "npm:~0.30.0" ramda-adjunct: "npm:^5.0.0" - checksum: 10/c0c9f35707afe05c559c8edacc0f548d3916f8f0cb0b4800b441258cbd871ba5c8ed083758b82bbe2589f022964bcd199f8d839648a78e979c94234e7ff22a08 + checksum: 10/8477220d192b17eb165096cb8fe699d48b554f2eb0ef737218f7136100a2a3cb7dfbcbf954dab4244796d48d0e82154b0788cfd9fe36226dcc85b2a6e11f65f0 languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-arazzo-json-1@npm:^1.0.0-beta.40 <1.0.0-rc.0": - version: 1.0.0-beta.48 - resolution: "@swagger-api/apidom-parser-adapter-arazzo-json-1@npm:1.0.0-beta.48" +"@swagger-api/apidom-parser-adapter-arazzo-json-1@npm:^1.0.0-rc.0": + version: 1.0.0-rc.4 + resolution: "@swagger-api/apidom-parser-adapter-arazzo-json-1@npm:1.0.0-rc.4" dependencies: "@babel/runtime-corejs3": "npm:^7.26.10" - "@swagger-api/apidom-core": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-ns-arazzo-1": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-parser-adapter-json": "npm:^1.0.0-beta.48" + "@swagger-api/apidom-core": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-ns-arazzo-1": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-parser-adapter-json": "npm:^1.0.0-rc.4" "@types/ramda": "npm:~0.30.0" ramda: "npm:~0.30.0" ramda-adjunct: "npm:^5.0.0" - checksum: 10/ec8bd9268b09d3446bb922d881ceab4f52164f995409a305dfa140b9c9790c2f75bf9d59bbc1d6859e1943bc1376ee72a6b7865eaf4b2043795c8576d489ce1b + checksum: 10/545d8883a0c5eedfd99c4a85347355865c701eed114cd75df54965174f07f2f4a884efd61e836d2168bc859dddfbbd168857dd0f3721b0d397f4c424bd0312ec languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-arazzo-yaml-1@npm:^1.0.0-beta.40 <1.0.0-rc.0": - version: 1.0.0-beta.48 - resolution: "@swagger-api/apidom-parser-adapter-arazzo-yaml-1@npm:1.0.0-beta.48" +"@swagger-api/apidom-parser-adapter-arazzo-yaml-1@npm:^1.0.0-rc.0": + version: 1.0.0-rc.4 + resolution: "@swagger-api/apidom-parser-adapter-arazzo-yaml-1@npm:1.0.0-rc.4" dependencies: "@babel/runtime-corejs3": "npm:^7.26.10" - "@swagger-api/apidom-core": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-ns-arazzo-1": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-parser-adapter-yaml-1-2": "npm:^1.0.0-beta.48" + "@swagger-api/apidom-core": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-ns-arazzo-1": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-parser-adapter-yaml-1-2": "npm:^1.0.0-rc.4" "@types/ramda": "npm:~0.30.0" ramda: "npm:~0.30.0" ramda-adjunct: "npm:^5.0.0" - checksum: 10/285a55e288475bd20a960fcc90d61bb0b29c8fc586a77ac3ba254c7eacc11db95a964648ae61e8deec20d90bfe32ea5eb11ec8857c6c4b44061c98045be75d5c + checksum: 10/acec60d1874d22990b021b64458f153c080a15239c84f1ed4a710ad7480d2a7c5a8c04cb895ae874e83bf467865abc6e93d30da2f58aee0921fcab375b4565f6 languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-asyncapi-json-2@npm:^1.0.0-beta.40 <1.0.0-rc.0": - version: 1.0.0-beta.48 - resolution: "@swagger-api/apidom-parser-adapter-asyncapi-json-2@npm:1.0.0-beta.48" +"@swagger-api/apidom-parser-adapter-asyncapi-json-2@npm:^1.0.0-rc.0": + version: 1.0.0-rc.4 + resolution: "@swagger-api/apidom-parser-adapter-asyncapi-json-2@npm:1.0.0-rc.4" dependencies: "@babel/runtime-corejs3": "npm:^7.26.10" - "@swagger-api/apidom-core": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-ns-asyncapi-2": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-parser-adapter-json": "npm:^1.0.0-beta.48" + "@swagger-api/apidom-core": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-ns-asyncapi-2": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-parser-adapter-json": "npm:^1.0.0-rc.4" "@types/ramda": "npm:~0.30.0" ramda: "npm:~0.30.0" ramda-adjunct: "npm:^5.0.0" - checksum: 10/1011a2be2fd576013ae5b725592c49f99dc42c50127d2707dc48893a33eb94a3820f62be6650f5bcbdb987034b5ef150905415eb44c7384a3376da97982bc467 + checksum: 10/16303fe4e38f993e25ad96d11f28a5b1ff42dd75ca2401b85b17f7937bbdcf7fb645c96644d3a70bf1c79d615609df4526f073c26a7719b5a4c4de50bd21f51e languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-asyncapi-yaml-2@npm:^1.0.0-beta.40 <1.0.0-rc.0": - version: 1.0.0-beta.48 - resolution: "@swagger-api/apidom-parser-adapter-asyncapi-yaml-2@npm:1.0.0-beta.48" +"@swagger-api/apidom-parser-adapter-asyncapi-yaml-2@npm:^1.0.0-rc.0": + version: 1.0.0-rc.4 + resolution: "@swagger-api/apidom-parser-adapter-asyncapi-yaml-2@npm:1.0.0-rc.4" dependencies: "@babel/runtime-corejs3": "npm:^7.26.10" - "@swagger-api/apidom-core": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-ns-asyncapi-2": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-parser-adapter-yaml-1-2": "npm:^1.0.0-beta.48" + "@swagger-api/apidom-core": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-ns-asyncapi-2": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-parser-adapter-yaml-1-2": "npm:^1.0.0-rc.4" "@types/ramda": "npm:~0.30.0" ramda: "npm:~0.30.0" ramda-adjunct: "npm:^5.0.0" - checksum: 10/c6f28dc27fe796ef3c8440afaa3ce78163e1290fd3c73437541eb629b028d4552537fdeaf29cfd9415774ee2909321289f5c9eb4682e6c5cbf6981ddabaf78b5 + checksum: 10/0894af80561bf688bc8fa06bf21e19e6b1ad6dbbe7c2c1d8f3e449f63d8d2d6e437647def9ef92ca6044df4d46a75b9581297cae655e1489b50418ac3e8de90b languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-json@npm:^1.0.0-beta.40 <1.0.0-rc.0, @swagger-api/apidom-parser-adapter-json@npm:^1.0.0-beta.48": - version: 1.0.0-beta.48 - resolution: "@swagger-api/apidom-parser-adapter-json@npm:1.0.0-beta.48" +"@swagger-api/apidom-parser-adapter-json@npm:^1.0.0-rc.0, @swagger-api/apidom-parser-adapter-json@npm:^1.0.0-rc.4": + version: 1.0.0-rc.4 + resolution: "@swagger-api/apidom-parser-adapter-json@npm:1.0.0-rc.4" dependencies: "@babel/runtime-corejs3": "npm:^7.26.10" - "@swagger-api/apidom-ast": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-core": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-error": "npm:^1.0.0-beta.48" + "@swagger-api/apidom-ast": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-core": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-error": "npm:^1.0.0-rc.4" "@types/ramda": "npm:~0.30.0" node-gyp: "npm:latest" ramda: "npm:~0.30.0" @@ -19371,148 +19651,147 @@ __metadata: tree-sitter: "npm:=0.21.1" tree-sitter-json: "npm:=0.24.8" web-tree-sitter: "npm:=0.24.5" - checksum: 10/ddb74c62c2a28d359584d385027db17c9630186e6f007e28220379ac27b2875c236b5a748101ff0d46edc46a222287db3ba3e0f43345ce2cf978cda691879b04 + checksum: 10/7447cdc9e19a585e3e7275ae6a560c6ab137c39b5d5548bec4a1499b178d669cd78ed27d4b5f24187e1f09d840b5735ae01b24e6cfe7b0ed9920a587a9b16109 languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-openapi-json-2@npm:^1.0.0-beta.40 <1.0.0-rc.0": - version: 1.0.0-beta.48 - resolution: "@swagger-api/apidom-parser-adapter-openapi-json-2@npm:1.0.0-beta.48" +"@swagger-api/apidom-parser-adapter-openapi-json-2@npm:^1.0.0-rc.0": + version: 1.0.0-rc.4 + resolution: "@swagger-api/apidom-parser-adapter-openapi-json-2@npm:1.0.0-rc.4" dependencies: "@babel/runtime-corejs3": "npm:^7.26.10" - "@swagger-api/apidom-core": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-ns-openapi-2": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-parser-adapter-json": "npm:^1.0.0-beta.48" + "@swagger-api/apidom-core": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-ns-openapi-2": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-parser-adapter-json": "npm:^1.0.0-rc.4" "@types/ramda": "npm:~0.30.0" ramda: "npm:~0.30.0" ramda-adjunct: "npm:^5.0.0" - checksum: 10/c5d4ebfa13c58487626a9b2764995f690db5bbe25de80212d9f216451b20716facb67f3fccae03ed986810d5ecb832756716ba86fcd506b1a3e974aa0e3117dc + checksum: 10/85f11179c6ebd7dbd7a99cf969e6c5b67ea0b95d64d8a41b83d87ea8db2ec95e23fd0481bbb365bbfedb5f8d7cdf6c193a8120562d9f104e1395272c52feca74 languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-openapi-json-3-0@npm:^1.0.0-beta.40 <1.0.0-rc.0": - version: 1.0.0-beta.48 - resolution: "@swagger-api/apidom-parser-adapter-openapi-json-3-0@npm:1.0.0-beta.48" +"@swagger-api/apidom-parser-adapter-openapi-json-3-0@npm:^1.0.0-rc.0": + version: 1.0.0-rc.4 + resolution: "@swagger-api/apidom-parser-adapter-openapi-json-3-0@npm:1.0.0-rc.4" dependencies: "@babel/runtime-corejs3": "npm:^7.26.10" - "@swagger-api/apidom-core": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-ns-openapi-3-0": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-parser-adapter-json": "npm:^1.0.0-beta.48" + "@swagger-api/apidom-core": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-ns-openapi-3-0": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-parser-adapter-json": "npm:^1.0.0-rc.4" "@types/ramda": "npm:~0.30.0" ramda: "npm:~0.30.0" ramda-adjunct: "npm:^5.0.0" - checksum: 10/b2e2d71cbb862ec477ebdda8f0e71353c58cef40b1d709ab8cdcea364757f7ffd2643c13a8ff60d0993ffe6a9229deaba6654fea6f3a890730a0b598183de1db + checksum: 10/fa701aa34dfb6f8088a8b896ed4ee2dfdfbe0b0bab80914e8aa85594de1babce65cd37256d70bc6b46eaae726d9dcbe0f564fd6a8711c44997729b724c85adbf languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-openapi-json-3-1@npm:^1.0.0-beta.40 <1.0.0-rc.0": - version: 1.0.0-beta.48 - resolution: "@swagger-api/apidom-parser-adapter-openapi-json-3-1@npm:1.0.0-beta.48" +"@swagger-api/apidom-parser-adapter-openapi-json-3-1@npm:^1.0.0-rc.0": + version: 1.0.0-rc.4 + resolution: "@swagger-api/apidom-parser-adapter-openapi-json-3-1@npm:1.0.0-rc.4" dependencies: "@babel/runtime-corejs3": "npm:^7.26.10" - "@swagger-api/apidom-core": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-ns-openapi-3-1": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-parser-adapter-json": "npm:^1.0.0-beta.48" + "@swagger-api/apidom-core": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-ns-openapi-3-1": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-parser-adapter-json": "npm:^1.0.0-rc.4" "@types/ramda": "npm:~0.30.0" ramda: "npm:~0.30.0" ramda-adjunct: "npm:^5.0.0" - checksum: 10/a9db188dee99f38e0a91644362e87c526559ddfb35019ed69738a5bebdad645beab925f47d1f0ae2430ca10bd83f329a4007bb2b3b6d23c6fe32d23865fdd672 + checksum: 10/382a36f76315862ceeb15b4e16e01f3e8aaf9b846025653c6a8a81230e8ac05a93ae1f9f1ce1fea76ca7ee2a8c5f0577f33ae8913cfb02bac23fc74850c47d05 languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-openapi-yaml-2@npm:^1.0.0-beta.40 <1.0.0-rc.0": - version: 1.0.0-beta.48 - resolution: "@swagger-api/apidom-parser-adapter-openapi-yaml-2@npm:1.0.0-beta.48" +"@swagger-api/apidom-parser-adapter-openapi-yaml-2@npm:^1.0.0-rc.0": + version: 1.0.0-rc.4 + resolution: "@swagger-api/apidom-parser-adapter-openapi-yaml-2@npm:1.0.0-rc.4" dependencies: "@babel/runtime-corejs3": "npm:^7.26.10" - "@swagger-api/apidom-core": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-ns-openapi-2": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-parser-adapter-yaml-1-2": "npm:^1.0.0-beta.48" + "@swagger-api/apidom-core": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-ns-openapi-2": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-parser-adapter-yaml-1-2": "npm:^1.0.0-rc.4" "@types/ramda": "npm:~0.30.0" ramda: "npm:~0.30.0" ramda-adjunct: "npm:^5.0.0" - checksum: 10/ed29926c1b08108cae294bc100fd279b555731ebc23edba2461e4817f82273003cf650f1eac0d1f2382ad590d76255e23ebf08438c3017ddcec7149e7140761d + checksum: 10/8236aea1dabe5d968a0111a196e7799ad20e3957583bf6f01bb63008ff8a0aa33db457133327be0db4d872a6a844e9cfc4c1962d3b23090a3588a0498ccec3ee languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-openapi-yaml-3-0@npm:^1.0.0-beta.40 <1.0.0-rc.0": - version: 1.0.0-beta.48 - resolution: "@swagger-api/apidom-parser-adapter-openapi-yaml-3-0@npm:1.0.0-beta.48" +"@swagger-api/apidom-parser-adapter-openapi-yaml-3-0@npm:^1.0.0-rc.0": + version: 1.0.0-rc.4 + resolution: "@swagger-api/apidom-parser-adapter-openapi-yaml-3-0@npm:1.0.0-rc.4" dependencies: "@babel/runtime-corejs3": "npm:^7.26.10" - "@swagger-api/apidom-core": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-ns-openapi-3-0": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-parser-adapter-yaml-1-2": "npm:^1.0.0-beta.48" + "@swagger-api/apidom-core": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-ns-openapi-3-0": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-parser-adapter-yaml-1-2": "npm:^1.0.0-rc.4" "@types/ramda": "npm:~0.30.0" ramda: "npm:~0.30.0" ramda-adjunct: "npm:^5.0.0" - checksum: 10/10d28a60ec9b4197d0c75bf05832c07fc1e8f61f72875ebe1baf328671c53499b51a9c065e1f0310c7c22aa6cb8f51ab2e8ba2692eee2b52f609982e8fe316c5 + checksum: 10/5286670c5c7b1fad5e97f0da88e40870ba98e2511334eb32c99d9b8d8059e6cc77b2ca6f3e539a9db2cd75809d2695c4000288f14a00d00a38107360ee85825c languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-openapi-yaml-3-1@npm:^1.0.0-beta.40 <1.0.0-rc.0": - version: 1.0.0-beta.48 - resolution: "@swagger-api/apidom-parser-adapter-openapi-yaml-3-1@npm:1.0.0-beta.48" +"@swagger-api/apidom-parser-adapter-openapi-yaml-3-1@npm:^1.0.0-rc.0": + version: 1.0.0-rc.4 + resolution: "@swagger-api/apidom-parser-adapter-openapi-yaml-3-1@npm:1.0.0-rc.4" dependencies: "@babel/runtime-corejs3": "npm:^7.26.10" - "@swagger-api/apidom-core": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-ns-openapi-3-1": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-parser-adapter-yaml-1-2": "npm:^1.0.0-beta.48" + "@swagger-api/apidom-core": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-ns-openapi-3-1": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-parser-adapter-yaml-1-2": "npm:^1.0.0-rc.4" "@types/ramda": "npm:~0.30.0" ramda: "npm:~0.30.0" ramda-adjunct: "npm:^5.0.0" - checksum: 10/2f31d09f7aba46b94ad2891097c3e2b880f6f76fab298dbcd794dd42c49fc0d9194f5a73abeb4f3140c4b53deff769f3eddbf16e70a9d764c36cdb24b4998071 + checksum: 10/bdce51f49c2784217237e667ddc4c111095ed7dd11cef94b3383ddf6a4a0e886492546a301aa803fdcfc7fb9923f5cdcfaba305cc98fcfeedd02d85e749a80f8 languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-yaml-1-2@npm:^1.0.0-beta.40 <1.0.0-rc.0, @swagger-api/apidom-parser-adapter-yaml-1-2@npm:^1.0.0-beta.48": - version: 1.0.0-beta.48 - resolution: "@swagger-api/apidom-parser-adapter-yaml-1-2@npm:1.0.0-beta.48" +"@swagger-api/apidom-parser-adapter-yaml-1-2@npm:^1.0.0-rc.0, @swagger-api/apidom-parser-adapter-yaml-1-2@npm:^1.0.0-rc.4": + version: 1.0.0-rc.4 + resolution: "@swagger-api/apidom-parser-adapter-yaml-1-2@npm:1.0.0-rc.4" dependencies: "@babel/runtime-corejs3": "npm:^7.26.10" - "@swagger-api/apidom-ast": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-core": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-error": "npm:^1.0.0-beta.48" + "@swagger-api/apidom-ast": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-core": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-error": "npm:^1.0.0-rc.4" "@tree-sitter-grammars/tree-sitter-yaml": "npm:=0.7.1" "@types/ramda": "npm:~0.30.0" - node-gyp: "npm:latest" ramda: "npm:~0.30.0" ramda-adjunct: "npm:^5.0.0" tree-sitter: "npm:=0.22.4" web-tree-sitter: "npm:=0.24.5" - checksum: 10/c032b088ffef50e119fb9cb60e7a6edfc17ec09e40c6d5ee62f5561c4da806f29ef5ba850f701763c755491f323754c23bb5a07da0cbbd3ed7d673caf5364559 + checksum: 10/c47bf36c8c2cbb8e2a0004167199d1a79df2c9c3cb97e50d7e55c2aa869546ad4376e067593b045a71d92df708b96bdadc0e7878dc60e547b9345e54384fb096 languageName: node linkType: hard -"@swagger-api/apidom-reference@npm:>=1.0.0-beta.41 <1.0.0-rc.0": - version: 1.0.0-beta.48 - resolution: "@swagger-api/apidom-reference@npm:1.0.0-beta.48" +"@swagger-api/apidom-reference@npm:^1.0.0-rc.1": + version: 1.0.0-rc.4 + resolution: "@swagger-api/apidom-reference@npm:1.0.0-rc.4" dependencies: "@babel/runtime-corejs3": "npm:^7.26.10" - "@swagger-api/apidom-core": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-error": "npm:^1.0.0-beta.48" - "@swagger-api/apidom-json-pointer": "npm:^1.0.0-beta.40 <1.0.0-rc.0" - "@swagger-api/apidom-ns-arazzo-1": "npm:^1.0.0-beta.40 <1.0.0-rc.0" - "@swagger-api/apidom-ns-asyncapi-2": "npm:^1.0.0-beta.40 <1.0.0-rc.0" - "@swagger-api/apidom-ns-openapi-2": "npm:^1.0.0-beta.40 <1.0.0-rc.0" - "@swagger-api/apidom-ns-openapi-3-0": "npm:^1.0.0-beta.40 <1.0.0-rc.0" - "@swagger-api/apidom-ns-openapi-3-1": "npm:^1.0.0-beta.40 <1.0.0-rc.0" - "@swagger-api/apidom-parser-adapter-api-design-systems-json": "npm:^1.0.0-beta.40 <1.0.0-rc.0" - "@swagger-api/apidom-parser-adapter-api-design-systems-yaml": "npm:^1.0.0-beta.40 <1.0.0-rc.0" - "@swagger-api/apidom-parser-adapter-arazzo-json-1": "npm:^1.0.0-beta.40 <1.0.0-rc.0" - "@swagger-api/apidom-parser-adapter-arazzo-yaml-1": "npm:^1.0.0-beta.40 <1.0.0-rc.0" - "@swagger-api/apidom-parser-adapter-asyncapi-json-2": "npm:^1.0.0-beta.40 <1.0.0-rc.0" - "@swagger-api/apidom-parser-adapter-asyncapi-yaml-2": "npm:^1.0.0-beta.40 <1.0.0-rc.0" - "@swagger-api/apidom-parser-adapter-json": "npm:^1.0.0-beta.40 <1.0.0-rc.0" - "@swagger-api/apidom-parser-adapter-openapi-json-2": "npm:^1.0.0-beta.40 <1.0.0-rc.0" - "@swagger-api/apidom-parser-adapter-openapi-json-3-0": "npm:^1.0.0-beta.40 <1.0.0-rc.0" - "@swagger-api/apidom-parser-adapter-openapi-json-3-1": "npm:^1.0.0-beta.40 <1.0.0-rc.0" - "@swagger-api/apidom-parser-adapter-openapi-yaml-2": "npm:^1.0.0-beta.40 <1.0.0-rc.0" - "@swagger-api/apidom-parser-adapter-openapi-yaml-3-0": "npm:^1.0.0-beta.40 <1.0.0-rc.0" - "@swagger-api/apidom-parser-adapter-openapi-yaml-3-1": "npm:^1.0.0-beta.40 <1.0.0-rc.0" - "@swagger-api/apidom-parser-adapter-yaml-1-2": "npm:^1.0.0-beta.40 <1.0.0-rc.0" + "@swagger-api/apidom-core": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-error": "npm:^1.0.0-rc.4" + "@swagger-api/apidom-json-pointer": "npm:^1.0.0-rc.0" + "@swagger-api/apidom-ns-arazzo-1": "npm:^1.0.0-rc.0" + "@swagger-api/apidom-ns-asyncapi-2": "npm:^1.0.0-rc.0" + "@swagger-api/apidom-ns-openapi-2": "npm:^1.0.0-rc.0" + "@swagger-api/apidom-ns-openapi-3-0": "npm:^1.0.0-rc.0" + "@swagger-api/apidom-ns-openapi-3-1": "npm:^1.0.0-rc.0" + "@swagger-api/apidom-parser-adapter-api-design-systems-json": "npm:^1.0.0-rc.0" + "@swagger-api/apidom-parser-adapter-api-design-systems-yaml": "npm:^1.0.0-rc.0" + "@swagger-api/apidom-parser-adapter-arazzo-json-1": "npm:^1.0.0-rc.0" + "@swagger-api/apidom-parser-adapter-arazzo-yaml-1": "npm:^1.0.0-rc.0" + "@swagger-api/apidom-parser-adapter-asyncapi-json-2": "npm:^1.0.0-rc.0" + "@swagger-api/apidom-parser-adapter-asyncapi-yaml-2": "npm:^1.0.0-rc.0" + "@swagger-api/apidom-parser-adapter-json": "npm:^1.0.0-rc.0" + "@swagger-api/apidom-parser-adapter-openapi-json-2": "npm:^1.0.0-rc.0" + "@swagger-api/apidom-parser-adapter-openapi-json-3-0": "npm:^1.0.0-rc.0" + "@swagger-api/apidom-parser-adapter-openapi-json-3-1": "npm:^1.0.0-rc.0" + "@swagger-api/apidom-parser-adapter-openapi-yaml-2": "npm:^1.0.0-rc.0" + "@swagger-api/apidom-parser-adapter-openapi-yaml-3-0": "npm:^1.0.0-rc.0" + "@swagger-api/apidom-parser-adapter-openapi-yaml-3-1": "npm:^1.0.0-rc.0" + "@swagger-api/apidom-parser-adapter-yaml-1-2": "npm:^1.0.0-rc.0" "@types/ramda": "npm:~0.30.0" - axios: "npm:^1.9.0" + axios: "npm:^1.12.2" minimatch: "npm:^7.4.3" process: "npm:^0.11.10" ramda: "npm:~0.30.0" @@ -19558,7 +19837,7 @@ __metadata: optional: true "@swagger-api/apidom-parser-adapter-yaml-1-2": optional: true - checksum: 10/fd86401690a3992123783c1b6044cdbb4a36b75d437e2519f6ec092d1b03273be45e884fc426e27a9413484047d40f819751f4f7174d9625de8a52a28d2d9e35 + checksum: 10/0efab87df6254abb4259912e6f845420b9fbd33c6a0491fdba5c166f0fcee880bdcea898e03b92b20bb5bf6251047df986797f6471000633a7dd448968e1de50 languageName: node linkType: hard @@ -19580,92 +19859,92 @@ __metadata: languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.11.24": - version: 1.11.24 - resolution: "@swc/core-darwin-arm64@npm:1.11.24" +"@swc/core-darwin-arm64@npm:1.15.6": + version: 1.15.6 + resolution: "@swc/core-darwin-arm64@npm:1.15.6" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.11.24": - version: 1.11.24 - resolution: "@swc/core-darwin-x64@npm:1.11.24" +"@swc/core-darwin-x64@npm:1.15.6": + version: 1.15.6 + resolution: "@swc/core-darwin-x64@npm:1.15.6" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.11.24": - version: 1.11.24 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.11.24" +"@swc/core-linux-arm-gnueabihf@npm:1.15.6": + version: 1.15.6 + resolution: "@swc/core-linux-arm-gnueabihf@npm:1.15.6" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@swc/core-linux-arm64-gnu@npm:1.11.24": - version: 1.11.24 - resolution: "@swc/core-linux-arm64-gnu@npm:1.11.24" +"@swc/core-linux-arm64-gnu@npm:1.15.6": + version: 1.15.6 + resolution: "@swc/core-linux-arm64-gnu@npm:1.15.6" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.11.24": - version: 1.11.24 - resolution: "@swc/core-linux-arm64-musl@npm:1.11.24" +"@swc/core-linux-arm64-musl@npm:1.15.6": + version: 1.15.6 + resolution: "@swc/core-linux-arm64-musl@npm:1.15.6" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.11.24": - version: 1.11.24 - resolution: "@swc/core-linux-x64-gnu@npm:1.11.24" +"@swc/core-linux-x64-gnu@npm:1.15.6": + version: 1.15.6 + resolution: "@swc/core-linux-x64-gnu@npm:1.15.6" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.11.24": - version: 1.11.24 - resolution: "@swc/core-linux-x64-musl@npm:1.11.24" +"@swc/core-linux-x64-musl@npm:1.15.6": + version: 1.15.6 + resolution: "@swc/core-linux-x64-musl@npm:1.15.6" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.11.24": - version: 1.11.24 - resolution: "@swc/core-win32-arm64-msvc@npm:1.11.24" +"@swc/core-win32-arm64-msvc@npm:1.15.6": + version: 1.15.6 + resolution: "@swc/core-win32-arm64-msvc@npm:1.15.6" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.11.24": - version: 1.11.24 - resolution: "@swc/core-win32-ia32-msvc@npm:1.11.24" +"@swc/core-win32-ia32-msvc@npm:1.15.6": + version: 1.15.6 + resolution: "@swc/core-win32-ia32-msvc@npm:1.15.6" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.11.24": - version: 1.11.24 - resolution: "@swc/core-win32-x64-msvc@npm:1.11.24" +"@swc/core-win32-x64-msvc@npm:1.15.6": + version: 1.15.6 + resolution: "@swc/core-win32-x64-msvc@npm:1.15.6" conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"@swc/core@npm:^1.3.46": - version: 1.11.24 - resolution: "@swc/core@npm:1.11.24" +"@swc/core@npm:^1.15.6": + version: 1.15.6 + resolution: "@swc/core@npm:1.15.6" dependencies: - "@swc/core-darwin-arm64": "npm:1.11.24" - "@swc/core-darwin-x64": "npm:1.11.24" - "@swc/core-linux-arm-gnueabihf": "npm:1.11.24" - "@swc/core-linux-arm64-gnu": "npm:1.11.24" - "@swc/core-linux-arm64-musl": "npm:1.11.24" - "@swc/core-linux-x64-gnu": "npm:1.11.24" - "@swc/core-linux-x64-musl": "npm:1.11.24" - "@swc/core-win32-arm64-msvc": "npm:1.11.24" - "@swc/core-win32-ia32-msvc": "npm:1.11.24" - "@swc/core-win32-x64-msvc": "npm:1.11.24" + "@swc/core-darwin-arm64": "npm:1.15.6" + "@swc/core-darwin-x64": "npm:1.15.6" + "@swc/core-linux-arm-gnueabihf": "npm:1.15.6" + "@swc/core-linux-arm64-gnu": "npm:1.15.6" + "@swc/core-linux-arm64-musl": "npm:1.15.6" + "@swc/core-linux-x64-gnu": "npm:1.15.6" + "@swc/core-linux-x64-musl": "npm:1.15.6" + "@swc/core-win32-arm64-msvc": "npm:1.15.6" + "@swc/core-win32-ia32-msvc": "npm:1.15.6" + "@swc/core-win32-x64-msvc": "npm:1.15.6" "@swc/counter": "npm:^0.1.3" - "@swc/types": "npm:^0.1.21" + "@swc/types": "npm:^0.1.25" peerDependencies: "@swc/helpers": ">=0.5.17" dependenciesMeta: @@ -19692,7 +19971,7 @@ __metadata: peerDependenciesMeta: "@swc/helpers": optional: true - checksum: 10/0b3e883f8a5652a7ab221a777386ccc8a65fc5b53d533bad15b703b22984eb3b449efd907b1872263f1a9990a9a50612f3c6deb619894a43f03cd974ec9bd1b7 + checksum: 10/d17d1b5e6e81f8c262b668f237b863dd612eaa19fc35e74067b2a27ba3998c0c511ec7f49cd91c02f61fa77dd1b5d7e65d293736f65ec45d6c13989904b1c7eb languageName: node linkType: hard @@ -19703,7 +19982,7 @@ __metadata: languageName: node linkType: hard -"@swc/helpers@npm:^0.5.0, @swc/helpers@npm:^0.5.8": +"@swc/helpers@npm:^0.5.0, @swc/helpers@npm:^0.5.17, @swc/helpers@npm:^0.5.8": version: 0.5.17 resolution: "@swc/helpers@npm:0.5.17" dependencies: @@ -19712,25 +19991,25 @@ __metadata: languageName: node linkType: hard -"@swc/jest@npm:^0.2.22": - version: 0.2.38 - resolution: "@swc/jest@npm:0.2.38" +"@swc/jest@npm:^0.2.39": + version: 0.2.39 + resolution: "@swc/jest@npm:0.2.39" dependencies: - "@jest/create-cache-key-function": "npm:^29.7.0" + "@jest/create-cache-key-function": "npm:^30.0.0" "@swc/counter": "npm:^0.1.3" jsonc-parser: "npm:^3.2.0" peerDependencies: "@swc/core": "*" - checksum: 10/3aaf557425e806890ebefea35334b7795e9f8ddf6f82d634d865ef917333cca4208190af1a9610c134c0e3b7a6a1aea4ec77a659e3ca5965be7aace65ce80c97 + checksum: 10/a2b7ed6fbb908867e673d1bbff9efde7eee225a57ad75735216ce2005e40c5cfb92285bd807d2058f1c0317e3d48ed71f5577fe85b28bebc80c1bc2c3a03306e languageName: node linkType: hard -"@swc/types@npm:^0.1.21": - version: 0.1.21 - resolution: "@swc/types@npm:0.1.21" +"@swc/types@npm:^0.1.25": + version: 0.1.25 + resolution: "@swc/types@npm:0.1.25" dependencies: "@swc/counter": "npm:^0.1.3" - checksum: 10/6554bf5c78519f49099a2ba448d170191a14b1c7a35df848f10ee4d6c03ecd681e5213884905187de1d1d221589ec8b5cb77f477d099dc1627c3ec9d7f2fcdb0 + checksum: 10/f6741450224892d12df43e5ca7f3cc0287df644dcd672626eb0cc2a3a8e3e875f4b29eb11336f37c7240cf6e010ba59eb3a79f4fb8bee5cbd168dfc1326ff369 languageName: node linkType: hard @@ -19835,8 +20114,8 @@ __metadata: linkType: hard "@testing-library/jest-dom@npm:^6.0.0, @testing-library/jest-dom@npm:^6.6.3": - version: 6.8.0 - resolution: "@testing-library/jest-dom@npm:6.8.0" + version: 6.9.1 + resolution: "@testing-library/jest-dom@npm:6.9.1" dependencies: "@adobe/css-tools": "npm:^4.4.0" aria-query: "npm:^5.0.0" @@ -19844,7 +20123,7 @@ __metadata: dom-accessibility-api: "npm:^0.6.3" picocolors: "npm:^1.1.1" redent: "npm:^3.0.0" - checksum: 10/d9bebf1f32e46fdde7e12a2b1ee1f8d113b2fb56e86720f185c32ccae2b76e74c76ecaa69c3aeee98a5fded3417b47032891e7ec9be83d4e6bf888ed8356032f + checksum: 10/409b4f519e4c68f4d31e3b0317338cc19098b9029513fca61aa2af8270086ae3956a1eaedd19bbce2d2c9e2cf9ff27a616c06556be7a26e101c0d529a0062233 languageName: node linkType: hard @@ -19913,14 +20192,14 @@ __metadata: languageName: node linkType: hard -"@tokenizer/inflate@npm:^0.2.7": - version: 0.2.7 - resolution: "@tokenizer/inflate@npm:0.2.7" +"@tokenizer/inflate@npm:^0.3.1": + version: 0.3.1 + resolution: "@tokenizer/inflate@npm:0.3.1" dependencies: - debug: "npm:^4.4.0" + debug: "npm:^4.4.1" fflate: "npm:^0.8.2" token-types: "npm:^6.0.0" - checksum: 10/6cee1857e47ca0fc053d6cd87773b7c21857ab84cb847c7d9437a76d923e265c88f8e99a4ac9643c2f989f4b9791259ca17128f0480191449e2b412821a1b9a7 + checksum: 10/a505d1b43b1a6c0ce0aacc681558daad4fc2f595a938dcd23c99cf3d6845189c7e5bd8f1785253675bd73ff45df8b47beeeab96197d30ff578d81029ff923103 languageName: node linkType: hard @@ -20078,12 +20357,12 @@ __metadata: languageName: node linkType: hard -"@tybys/wasm-util@npm:^0.10.0": - version: 0.10.0 - resolution: "@tybys/wasm-util@npm:0.10.0" +"@tybys/wasm-util@npm:^0.10.0, @tybys/wasm-util@npm:^0.10.1": + version: 0.10.1 + resolution: "@tybys/wasm-util@npm:0.10.1" dependencies: tslib: "npm:^2.4.0" - checksum: 10/779d047a77e8a619b6e26b6fe556f413316d846e9a35438668a15510a4d6e7294388c998f65911f6f1a13838745575d7793cb1d27182752f6f95991725b15d45 + checksum: 10/7fe0d239397aebb002ac4855d30c197c06a05ea8df8511350a3a5b1abeefe26167c60eda8a5508337571161e4c4b53d7c1342296123f9607af8705369de9fa7f languageName: node linkType: hard @@ -20144,7 +20423,7 @@ __metadata: languageName: node linkType: hard -"@types/babel__core@npm:^7.1.14, @types/babel__core@npm:^7.20.5": +"@types/babel__core@npm:^7.20.5": version: 7.20.5 resolution: "@types/babel__core@npm:7.20.5" dependencies: @@ -20176,7 +20455,7 @@ __metadata: languageName: node linkType: hard -"@types/babel__traverse@npm:*, @types/babel__traverse@npm:^7.0.6, @types/babel__traverse@npm:^7.20.7": +"@types/babel__traverse@npm:*, @types/babel__traverse@npm:^7.20.7": version: 7.28.0 resolution: "@types/babel__traverse@npm:7.28.0" dependencies: @@ -20310,11 +20589,12 @@ __metadata: linkType: hard "@types/compression@npm:^1.7.5": - version: 1.7.5 - resolution: "@types/compression@npm:1.7.5" + version: 1.8.1 + resolution: "@types/compression@npm:1.8.1" dependencies: "@types/express": "npm:*" - checksum: 10/9d65485bfb8e20035dedbbbebea06ea0c0554ac7bedb11ec3f2c6582cb082d121a10a03b4803b56315ae31705043eddf97eaf49c3dad6f9e39f7875b27c8feb4 + "@types/node": "npm:*" + checksum: 10/cd746c830a5c981568d36989c3c43a55caf1872b54e3f9891b82fba04501de11882091df3ece11fbede2de01179c99d08639a08831e06c3966873f928407c01a languageName: node linkType: hard @@ -20354,11 +20634,11 @@ __metadata: linkType: hard "@types/cookie-parser@npm:^1.4.2": - version: 1.4.9 - resolution: "@types/cookie-parser@npm:1.4.9" + version: 1.4.10 + resolution: "@types/cookie-parser@npm:1.4.10" peerDependencies: "@types/express": "*" - checksum: 10/6192a4899b5412a4c3be0f47158321aef73a4cd7e7a4f7b2a37e2e1045f11a21209681cb1bc5335f250ee2a6ce64d8a3fefb851181a98e6415d3716ef9ed1f62 + checksum: 10/1f37b5a4115dbfd4b7bbea2d874fbf9495eca8c3e8c87fa7e38c50f9fff66222377c911cfdc7a1ea08855e822919c5534ebbcc4bf25b596bc6f7270e403483d9 languageName: node linkType: hard @@ -20574,7 +20854,19 @@ __metadata: languageName: node linkType: hard -"@types/express-serve-static-core@npm:*, @types/express-serve-static-core@npm:^4.17.21, @types/express-serve-static-core@npm:^4.17.33, @types/express-serve-static-core@npm:^4.17.5": +"@types/express-serve-static-core@npm:*": + version: 5.1.0 + resolution: "@types/express-serve-static-core@npm:5.1.0" + dependencies: + "@types/node": "npm:*" + "@types/qs": "npm:*" + "@types/range-parser": "npm:*" + "@types/send": "npm:*" + checksum: 10/c0b5b7ebc15b222f51e5705da2b8a5180335bf70927cc83c065784331aa9291984db1bfa4a14f5ba31b538dcb543561d9280046051fa4c9b7256eb971293e735 + languageName: node + linkType: hard + +"@types/express-serve-static-core@npm:^4.17.21, @types/express-serve-static-core@npm:^4.17.33, @types/express-serve-static-core@npm:^4.17.5": version: 4.19.7 resolution: "@types/express-serve-static-core@npm:4.19.7" dependencies: @@ -20655,15 +20947,6 @@ __metadata: languageName: node linkType: hard -"@types/graceful-fs@npm:^4.1.3": - version: 4.1.5 - resolution: "@types/graceful-fs@npm:4.1.5" - dependencies: - "@types/node": "npm:*" - checksum: 10/d076bb61f45d0fc42dee496ef8b1c2f8742e15d5e47e90e20d0243386e426c04d4efd408a48875ab432f7960b4ce3414db20ed0fbbfc7bcc89d84e574f6e045a - languageName: node - linkType: hard - "@types/hast@npm:^2.0.0": version: 2.3.4 resolution: "@types/hast@npm:2.3.4" @@ -20673,7 +20956,7 @@ __metadata: languageName: node linkType: hard -"@types/hast@npm:^3.0.4": +"@types/hast@npm:^3.0.0, @types/hast@npm:^3.0.4": version: 3.0.4 resolution: "@types/hast@npm:3.0.4" dependencies: @@ -20732,11 +21015,11 @@ __metadata: linkType: hard "@types/http-proxy@npm:^1.17.15, @types/http-proxy@npm:^1.17.4, @types/http-proxy@npm:^1.17.8": - version: 1.17.16 - resolution: "@types/http-proxy@npm:1.17.16" + version: 1.17.17 + resolution: "@types/http-proxy@npm:1.17.17" dependencies: "@types/node": "npm:*" - checksum: 10/a054ac8f5301acfcfdcec3a775f52dc371180bbe60037906534312f10cceb3799b4a16e46c56c22f9925d078e11dcda1723c38f1ddd124be8169a4cccca69c8c + checksum: 10/893e46e12be576baa471cf2fc13a4f0e413eaf30a5850de8fdbea3040e138ad4171234c59b986cf7137ff20a1582b254bf0c44cfd715d5ed772e1ab94dd75cd1 languageName: node linkType: hard @@ -20773,7 +21056,7 @@ __metadata: languageName: node linkType: hard -"@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.1": +"@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.1, @types/istanbul-lib-coverage@npm:^2.0.6": version: 2.0.6 resolution: "@types/istanbul-lib-coverage@npm:2.0.6" checksum: 10/3feac423fd3e5449485afac999dcfcb3d44a37c830af898b689fadc65d26526460bedb889db278e0d4d815a670331796494d073a10ee6e3a6526301fe7415778 @@ -20789,7 +21072,7 @@ __metadata: languageName: node linkType: hard -"@types/istanbul-reports@npm:^3.0.0": +"@types/istanbul-reports@npm:^3.0.0, @types/istanbul-reports@npm:^3.0.4": version: 3.0.4 resolution: "@types/istanbul-reports@npm:3.0.4" dependencies: @@ -20798,22 +21081,22 @@ __metadata: languageName: node linkType: hard -"@types/jest@npm:*, @types/jest@npm:^29.5.11": - version: 29.5.14 - resolution: "@types/jest@npm:29.5.14" +"@types/jest@npm:*, @types/jest@npm:^30.0.0": + version: 30.0.0 + resolution: "@types/jest@npm:30.0.0" dependencies: - expect: "npm:^29.0.0" - pretty-format: "npm:^29.0.0" - checksum: 10/59ec7a9c4688aae8ee529316c43853468b6034f453d08a2e1064b281af9c81234cec986be796288f1bbb29efe943bc950e70c8fa8faae1e460d50e3cf9760f9b + expect: "npm:^30.0.0" + pretty-format: "npm:^30.0.0" + checksum: 10/cdeaa924c68b5233d9ff92861a89e7042df2b0f197633729bcf3a31e65bd4e9426e751c5665b5ac2de0b222b33f100a5502da22aefce3d2c62931c715e88f209 languageName: node linkType: hard "@types/jquery@npm:^3.3.34": - version: 3.5.32 - resolution: "@types/jquery@npm:3.5.32" + version: 3.5.33 + resolution: "@types/jquery@npm:3.5.33" dependencies: "@types/sizzle": "npm:*" - checksum: 10/2c67cac338828870ead5c5e608f5fa5ab8101598ed4572cf49b58c342adffe8918d2e2fc94d7954e6b98a889cef8c3f4e6f44b8fecb75e80854b0f9cf9dd18a1 + checksum: 10/9a9e2cddc584f9afa1970b0febac0b65bed6d8084baf9655346f5787ee1b25975a0f259b0c81edc7757fbb92d584ed2d1b39804ab78ab0238407c7e4b0376011 languageName: node linkType: hard @@ -20848,14 +21131,14 @@ __metadata: languageName: node linkType: hard -"@types/jsdom@npm:^20.0.0": - version: 20.0.0 - resolution: "@types/jsdom@npm:20.0.0" +"@types/jsdom@npm:^21.1.7": + version: 21.1.7 + resolution: "@types/jsdom@npm:21.1.7" dependencies: "@types/node": "npm:*" "@types/tough-cookie": "npm:*" parse5: "npm:^7.0.0" - checksum: 10/4cd814a948aa9b739652cde183acc6a9a10bcf04ed82c3a53f691bbc52d156b49269fa3046c70842680a29d240607fcd7be5f35a73ddbf571d95a664e8e49cec + checksum: 10/a5ee54aec813ac928ef783f69828213af4d81325f584e1fe7573a9ae139924c40768d1d5249237e62d51b9a34ed06bde059c86c6b0248d627457ec5e5d532dfa languageName: node linkType: hard @@ -20935,9 +21218,9 @@ __metadata: linkType: hard "@types/lodash@npm:^4.14.151": - version: 4.17.20 - resolution: "@types/lodash@npm:4.17.20" - checksum: 10/8cd8ad3bd78d2e06a93ae8d6c9907981d5673655fec7cb274a4d9a59549aab5bb5b3017361280773b8990ddfccf363e14d1b37c97af8a9fe363de677f9a61524 + version: 4.17.21 + resolution: "@types/lodash@npm:4.17.21" + checksum: 10/34920830a3bc82ba619cda05e606fef00c148a69b4f19f770645d2587ccdb8e42ef3ddfc174b7884c0c709fc0a1aeb48f7326da969bad12a1464a03efbbe414c languageName: node linkType: hard @@ -20955,7 +21238,14 @@ __metadata: languageName: node linkType: hard -"@types/luxon@npm:^3.0.0, @types/luxon@npm:~3.4.0": +"@types/luxon@npm:^3.0.0": + version: 3.7.1 + resolution: "@types/luxon@npm:3.7.1" + checksum: 10/c7bc164c278393ea0be938f986c74b4cddfab9013b1aff4495b016f771ded1d5b7b7b4825b2c7f0b8799edce19c5f531c28ff434ab3dedf994ac2d99a20fd4c4 + languageName: node + linkType: hard + +"@types/luxon@npm:~3.4.0": version: 3.4.2 resolution: "@types/luxon@npm:3.4.2" checksum: 10/fd89566e3026559f2bc4ddcc1e70a2c16161905ed50be9473ec0cfbbbe919165041408c4f6e06c4bcf095445535052e2c099087c76b1b38e368127e618fc968d @@ -21052,12 +21342,12 @@ __metadata: languageName: node linkType: hard -"@types/multer@npm:^1.4.12": - version: 1.4.12 - resolution: "@types/multer@npm:1.4.12" +"@types/multer@npm:^1.4.13": + version: 1.4.13 + resolution: "@types/multer@npm:1.4.13" dependencies: "@types/express": "npm:*" - checksum: 10/3d2b32da58ddd67f972d4ef1021492f78d65f33f936b6fb25dd461bb6cc7b03bfd1de1a11562c4310680dac8054e4398038db51767a0ffbf1fe62457b3706e95 + checksum: 10/f650a9f431007f05a5c51d6359140bea5f77d1299668d45a0791ddbf7789f1c220a3e038039c5e0de6608e273d5ee8001e9649c606d7e0e847e8774ccc5d1d68 languageName: node linkType: hard @@ -21091,11 +21381,11 @@ __metadata: linkType: hard "@types/node-forge@npm:^1.3.0": - version: 1.3.13 - resolution: "@types/node-forge@npm:1.3.13" + version: 1.3.14 + resolution: "@types/node-forge@npm:1.3.14" dependencies: "@types/node": "npm:*" - checksum: 10/4d62a6b0cedeb45145de6b05df0082b0ba32675aeb1bf8dbe003804eb61be412a613e82f56b65ba1051594abda4f4c9c0aa9aac009cf106af6faf6217eee8681 + checksum: 10/500ce72435285fca145837da079b49a09a5bdf8391b0effc3eb2455783dd81ab129e574a36e1a0374a4823d889d5328177ebfd6fe45b432c0c43d48d790fe39c languageName: node linkType: hard @@ -21225,13 +21515,13 @@ __metadata: linkType: hard "@types/passport-google-oauth20@npm:^2.0.3": - version: 2.0.16 - resolution: "@types/passport-google-oauth20@npm:2.0.16" + version: 2.0.17 + resolution: "@types/passport-google-oauth20@npm:2.0.17" dependencies: "@types/express": "npm:*" "@types/passport": "npm:*" "@types/passport-oauth2": "npm:*" - checksum: 10/fd4a2ec9e1360f540904c48e1c28c58fdddbb58cca3e8fd317db180050489a626f12c1fe092ef2faed7e8f2e45e10cece1725628453d2806b0d3e5a703cd77e6 + checksum: 10/534b10d00347f74014205485a96bbf80ba357de8293847cf3e1df67e7b10197fc4128f4c64be6ddf41ede61451e40627810323c26117c863cf244179dc59ee9f languageName: node linkType: hard @@ -21245,13 +21535,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.17 - resolution: "@types/passport-oauth2@npm:1.4.17" + version: 1.8.0 + resolution: "@types/passport-oauth2@npm:1.8.0" dependencies: "@types/express": "npm:*" "@types/oauth": "npm:*" "@types/passport": "npm:*" - checksum: 10/4c5d2d6f717bb0b3d049669e47ca27cb166cbbef2073dccd302b10e62936c9e392074acabe6cb593f7eeb37a6a3cf81b9d3a4f35a46018a6645ac37d0f1706cb + checksum: 10/f874fb3c8646a720c4ae2b7da905b9db03e19617981e42c64b1dbe3313e7df9ab66682de41538db3279e1805b146ba6fc35902462c1858d605c30bb20cac7609 languageName: node linkType: hard @@ -21312,6 +21602,13 @@ __metadata: languageName: node linkType: hard +"@types/prismjs@npm:^1.0.0": + version: 1.26.5 + resolution: "@types/prismjs@npm:1.26.5" + checksum: 10/617099479db9550119d0f84272dc79d64b2cf3e0d7a17167fe740d55fdf0f155697d935409464392d164e62080c2c88d649cf4bc4fdd30a87127337536657277 + languageName: node + linkType: hard + "@types/promise.allsettled@npm:^1.0.3": version: 1.0.6 resolution: "@types/promise.allsettled@npm:1.0.6" @@ -21368,11 +21665,11 @@ __metadata: linkType: hard "@types/react-grid-layout@npm:^1.3.2": - version: 1.3.5 - resolution: "@types/react-grid-layout@npm:1.3.5" + version: 1.3.6 + resolution: "@types/react-grid-layout@npm:1.3.6" dependencies: "@types/react": "npm:*" - checksum: 10/21599054dfa977ed8445b1ab3198a842531cb36bd620564c3f8a469688cbea051149eb644a99b2f8f6d02f8d9909a6145668f385781b5647601e9663de216946 + checksum: 10/80b9cd6ab14f5cd32a62451544cbbeff32d6c8c3fefd6e04f974429a0b1b0d2aded1f4767ae4ce9cd4caa395e514531f5e5d6a3c3e93dba4906a907f8d77ee21 languageName: node linkType: hard @@ -21529,11 +21826,11 @@ __metadata: linkType: hard "@types/rollup-plugin-peer-deps-external@npm:^2.2.0": - version: 2.2.5 - resolution: "@types/rollup-plugin-peer-deps-external@npm:2.2.5" - dependencies: - rollup: "npm:^0.63.4" - checksum: 10/3f0d130fc15c80eac737391e180e77597da1200ff1f6d28a44f785a0de7f29144df805ab5b020ba38b243af6959e9da0757efa4141c4e737cd04eebe50f59c07 + version: 2.2.6 + resolution: "@types/rollup-plugin-peer-deps-external@npm:2.2.6" + peerDependencies: + rollup: "*" + checksum: 10/9fcee30d60d9d8de0f4bbf7694c254a18798b0ff415563a60fb2ed8c6c46423c64e1a977e0344b8393c26221dbd6e74d9e872c2694b518fcf149ba85d94e7eac languageName: node linkType: hard @@ -21607,11 +21904,11 @@ __metadata: linkType: hard "@types/set-cookie-parser@npm:^2.4.0": - version: 2.4.3 - resolution: "@types/set-cookie-parser@npm:2.4.3" + version: 2.4.10 + resolution: "@types/set-cookie-parser@npm:2.4.10" dependencies: "@types/node": "npm:*" - checksum: 10/8c0ded364c5a53598dc58f6c668d6fdbefa3bb78fcb1181202b92f4d8495ca33b4317f54ac0fe42824278e789d730ee5cbd2f7f864466e708589ff4eab2bf457 + checksum: 10/105cc90c7d7deeb344858f720b58bd137356586545ac00d1a448e050bfcc0f385553ff26bc9c674bd8c2e953a458149eadb1945ee3d1eee81e6c0656236ebc0a languageName: node linkType: hard @@ -21673,10 +21970,10 @@ __metadata: languageName: node linkType: hard -"@types/stack-utils@npm:^2.0.0": - version: 2.0.0 - resolution: "@types/stack-utils@npm:2.0.0" - checksum: 10/b3fbae25b073116977ecb5c67d22f14567b51a7792403b0bf46e5de8f29bde3bd4ec1626afb22065495ca7f1c699c8bd66720050c94b8f8f9bcefbee79d161fd +"@types/stack-utils@npm:^2.0.3": + version: 2.0.3 + resolution: "@types/stack-utils@npm:2.0.3" + checksum: 10/72576cc1522090fe497337c2b99d9838e320659ac57fa5560fcbdcbafcf5d0216c6b3a0a8a4ee4fdb3b1f5e3420aa4f6223ab57b82fef3578bec3206425c6cf5 languageName: node linkType: hard @@ -21908,12 +22205,12 @@ __metadata: languageName: node linkType: hard -"@types/yargs@npm:^17.0.8": - version: 17.0.12 - resolution: "@types/yargs@npm:17.0.12" +"@types/yargs@npm:^17.0.33, @types/yargs@npm:^17.0.8": + version: 17.0.35 + resolution: "@types/yargs@npm:17.0.35" dependencies: "@types/yargs-parser": "npm:*" - checksum: 10/ffbbfad0c75cc058e0518f202e3651b9fb60c7c1325240cc72ac0a022da746a759ba3c6e0099152076fed5012fb694eb4685e4520c04dc8399c22bb81221bff5 + checksum: 10/47bcd4476a4194ea11617ea71cba8a1eddf5505fc39c44336c1a08d452a0de4486aedbc13f47a017c8efbcb5a8aa358d976880663732ebcbc6dbcbbecadb0581 languageName: node linkType: hard @@ -21948,39 +22245,39 @@ __metadata: linkType: hard "@typescript-eslint/eslint-plugin@npm:^8.17.0": - version: 8.29.1 - resolution: "@typescript-eslint/eslint-plugin@npm:8.29.1" + version: 8.48.1 + resolution: "@typescript-eslint/eslint-plugin@npm:8.48.1" dependencies: "@eslint-community/regexpp": "npm:^4.10.0" - "@typescript-eslint/scope-manager": "npm:8.29.1" - "@typescript-eslint/type-utils": "npm:8.29.1" - "@typescript-eslint/utils": "npm:8.29.1" - "@typescript-eslint/visitor-keys": "npm:8.29.1" + "@typescript-eslint/scope-manager": "npm:8.48.1" + "@typescript-eslint/type-utils": "npm:8.48.1" + "@typescript-eslint/utils": "npm:8.48.1" + "@typescript-eslint/visitor-keys": "npm:8.48.1" graphemer: "npm:^1.4.0" - ignore: "npm:^5.3.1" + ignore: "npm:^7.0.0" natural-compare: "npm:^1.4.0" - ts-api-utils: "npm:^2.0.1" + ts-api-utils: "npm:^2.1.0" peerDependencies: - "@typescript-eslint/parser": ^8.0.0 || ^8.0.0-alpha.0 + "@typescript-eslint/parser": ^8.48.1 eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.9.0" - checksum: 10/0568894f0ea50e67622605eb347d4e26a41571ad06234478ac695a097e9b3ff6252d6d60034853d7a6b8ec644b5c1d354be21075d691173dd7f2fbecb1102674 + typescript: ">=4.8.4 <6.0.0" + checksum: 10/3ccf420805fb8adb2f3059fa26eb9c6211c0624966d8c8654a1bd586bf87f30be0c62524dfd785185ef573bedd91c42ec3c98c23aed5d60cb9ac583dd9334bc8 languageName: node linkType: hard "@typescript-eslint/parser@npm:^8.16.0": - version: 8.29.1 - resolution: "@typescript-eslint/parser@npm:8.29.1" + version: 8.48.1 + resolution: "@typescript-eslint/parser@npm:8.48.1" dependencies: - "@typescript-eslint/scope-manager": "npm:8.29.1" - "@typescript-eslint/types": "npm:8.29.1" - "@typescript-eslint/typescript-estree": "npm:8.29.1" - "@typescript-eslint/visitor-keys": "npm:8.29.1" + "@typescript-eslint/scope-manager": "npm:8.48.1" + "@typescript-eslint/types": "npm:8.48.1" + "@typescript-eslint/typescript-estree": "npm:8.48.1" + "@typescript-eslint/visitor-keys": "npm:8.48.1" debug: "npm:^4.3.4" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.9.0" - checksum: 10/effb4cc24e375e4229e711b3ea8611a205bf81964cb487f518dd4a7d6cecde7324201ce4e2c3cd420e0ce7649899294307da2cd77f145af4efef3a0292189f20 + typescript: ">=4.8.4 <6.0.0" + checksum: 10/d8409c9ede4b1cd2ad0e10e94bb00c54f79352f7d54c97bf24419cb983c19b9f6097e6c31b217ce7ec5cfc9a48117e732d9f88ce0cb8c0ccf7fc3faecdf854a3 languageName: node linkType: hard @@ -22017,16 +22314,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:8.29.1": - version: 8.29.1 - resolution: "@typescript-eslint/scope-manager@npm:8.29.1" - dependencies: - "@typescript-eslint/types": "npm:8.29.1" - "@typescript-eslint/visitor-keys": "npm:8.29.1" - checksum: 10/33a02f490b53436729f5ca2e6e0c5b8db72adb455274e5de43bdaada21033e7941aed1d92653321991e186af77f7794dc0ac35d2fce891cdf65a6d3fb192249e - languageName: node - linkType: hard - "@typescript-eslint/scope-manager@npm:8.48.1": version: 8.48.1 resolution: "@typescript-eslint/scope-manager@npm:8.48.1" @@ -22046,18 +22333,19 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:8.29.1": - version: 8.29.1 - resolution: "@typescript-eslint/type-utils@npm:8.29.1" +"@typescript-eslint/type-utils@npm:8.48.1": + version: 8.48.1 + resolution: "@typescript-eslint/type-utils@npm:8.48.1" dependencies: - "@typescript-eslint/typescript-estree": "npm:8.29.1" - "@typescript-eslint/utils": "npm:8.29.1" + "@typescript-eslint/types": "npm:8.48.1" + "@typescript-eslint/typescript-estree": "npm:8.48.1" + "@typescript-eslint/utils": "npm:8.48.1" debug: "npm:^4.3.4" - ts-api-utils: "npm:^2.0.1" + ts-api-utils: "npm:^2.1.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.9.0" - checksum: 10/3774d6fb32c058b3fa607480e5603fdd2919e07d8babbc00aa703f31c6fd6f7fbc25c25ff246e7e6ac6b77ad0e0b66838a7136aebc31503a58fbe509f68ab2f4 + typescript: ">=4.8.4 <6.0.0" + checksum: 10/6cf9370ac5437e2d64c71964646aed9e6c1ea3c7bb473258b50ae422106461d290f4215b9435b892a2dd563e3c31feb3169532375513b56b7e48f4a425283091 languageName: node linkType: hard @@ -22075,13 +22363,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/types@npm:8.29.1": - version: 8.29.1 - resolution: "@typescript-eslint/types@npm:8.29.1" - checksum: 10/99ff59e7af3728858af9b7fdc0165955bcf5cd2eefeaafabfbdd7951fbc8ad869cbb7bed7bcbed6c3c50a8661333b33364dc1de0a0c8f3c64d5882339a5d30dd - languageName: node - linkType: hard - "@typescript-eslint/types@npm:8.48.1, @typescript-eslint/types@npm:^8.48.1": version: 8.48.1 resolution: "@typescript-eslint/types@npm:8.48.1" @@ -22126,24 +22407,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:8.29.1": - version: 8.29.1 - resolution: "@typescript-eslint/typescript-estree@npm:8.29.1" - dependencies: - "@typescript-eslint/types": "npm:8.29.1" - "@typescript-eslint/visitor-keys": "npm:8.29.1" - debug: "npm:^4.3.4" - fast-glob: "npm:^3.3.2" - is-glob: "npm:^4.0.3" - minimatch: "npm:^9.0.4" - semver: "npm:^7.6.0" - ts-api-utils: "npm:^2.0.1" - peerDependencies: - typescript: ">=4.8.4 <5.9.0" - checksum: 10/dded2ebe4c3287443000e3b825e673d0eddb7c48eb2d373c5b7059ea7dbbeba488d7f1de2e42ed7a9299ccff926a65821f2b5594022b49564026ba01c0cc07ab - languageName: node - linkType: hard - "@typescript-eslint/typescript-estree@npm:8.48.1, @typescript-eslint/typescript-estree@npm:^8.23.0": version: 8.48.1 resolution: "@typescript-eslint/typescript-estree@npm:8.48.1" @@ -22163,18 +22426,18 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/utils@npm:8.29.1": - version: 8.29.1 - resolution: "@typescript-eslint/utils@npm:8.29.1" +"@typescript-eslint/utils@npm:8.48.1, @typescript-eslint/utils@npm:^6.0.0 || ^7.0.0 || ^8.0.0, @typescript-eslint/utils@npm:^8.8.1": + version: 8.48.1 + resolution: "@typescript-eslint/utils@npm:8.48.1" dependencies: - "@eslint-community/eslint-utils": "npm:^4.4.0" - "@typescript-eslint/scope-manager": "npm:8.29.1" - "@typescript-eslint/types": "npm:8.29.1" - "@typescript-eslint/typescript-estree": "npm:8.29.1" + "@eslint-community/eslint-utils": "npm:^4.7.0" + "@typescript-eslint/scope-manager": "npm:8.48.1" + "@typescript-eslint/types": "npm:8.48.1" + "@typescript-eslint/typescript-estree": "npm:8.48.1" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.9.0" - checksum: 10/1d2c85c97a39e063fe490c0cdb6513716e4735bda0bc937475b44d9224074a5070f888dfed1e75f4a91c8f4d825b44fce90b685e07bda391dfeb2553b9b39a5a + typescript: ">=4.8.4 <6.0.0" + checksum: 10/34afe5cf78020b682473e6529d6268eb8015bdb020a3c5303c4abb230d4d7c39e6fc8b9df58d1f0f35a1ceeb5d6182e71e42fe7a28dde8ffc31f8560f2dacc7c languageName: node linkType: hard @@ -22196,21 +22459,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/utils@npm:^6.0.0 || ^7.0.0 || ^8.0.0, @typescript-eslint/utils@npm:^8.8.1": - version: 8.48.1 - resolution: "@typescript-eslint/utils@npm:8.48.1" - dependencies: - "@eslint-community/eslint-utils": "npm:^4.7.0" - "@typescript-eslint/scope-manager": "npm:8.48.1" - "@typescript-eslint/types": "npm:8.48.1" - "@typescript-eslint/typescript-estree": "npm:8.48.1" - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <6.0.0" - checksum: 10/34afe5cf78020b682473e6529d6268eb8015bdb020a3c5303c4abb230d4d7c39e6fc8b9df58d1f0f35a1ceeb5d6182e71e42fe7a28dde8ffc31f8560f2dacc7c - languageName: node - linkType: hard - "@typescript-eslint/utils@npm:^7.0.0": version: 7.18.0 resolution: "@typescript-eslint/utils@npm:7.18.0" @@ -22245,16 +22493,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:8.29.1": - version: 8.29.1 - resolution: "@typescript-eslint/visitor-keys@npm:8.29.1" - dependencies: - "@typescript-eslint/types": "npm:8.29.1" - eslint-visitor-keys: "npm:^4.2.0" - checksum: 10/788290c369c13403692d857e0a464b5c2223e1fef28c717b7dbc61140d33697ce43c7d1a7cb7ac585f2012fc702ce2ec489363d34bf566303d3c48fa494803c5 - languageName: node - linkType: hard - "@typescript-eslint/visitor-keys@npm:8.48.1": version: 8.48.1 resolution: "@typescript-eslint/visitor-keys@npm:8.48.1" @@ -22265,9 +22503,9 @@ __metadata: languageName: node linkType: hard -"@uiw/codemirror-extensions-basic-setup@npm:4.24.2": - version: 4.24.2 - resolution: "@uiw/codemirror-extensions-basic-setup@npm:4.24.2" +"@uiw/codemirror-extensions-basic-setup@npm:4.25.3": + version: 4.25.3 + resolution: "@uiw/codemirror-extensions-basic-setup@npm:4.25.3" dependencies: "@codemirror/autocomplete": "npm:^6.0.0" "@codemirror/commands": "npm:^6.0.0" @@ -22284,19 +22522,19 @@ __metadata: "@codemirror/search": ">=6.0.0" "@codemirror/state": ">=6.0.0" "@codemirror/view": ">=6.0.0" - checksum: 10/077f64b4bbb6178038d30a3cb2961c0ff89c0836b73210d0ac3fca828c3ba8fbce61e42635ec2e2997cdffff5472b75ad58541c4e62f98d52b83d475da0c56eb + checksum: 10/6ece4ee0fd6433a81bb6b2e18623db3df097d31d13c53184fbf4355cf3aaac5201d73dfa984f58390f0f6f7cfb631bd2ee20f3613b99b7259e2e1352e954c179 languageName: node linkType: hard "@uiw/react-codemirror@npm:^4.9.3": - version: 4.24.2 - resolution: "@uiw/react-codemirror@npm:4.24.2" + version: 4.25.3 + resolution: "@uiw/react-codemirror@npm:4.25.3" dependencies: "@babel/runtime": "npm:^7.18.6" "@codemirror/commands": "npm:^6.1.0" "@codemirror/state": "npm:^6.1.1" "@codemirror/theme-one-dark": "npm:^6.0.0" - "@uiw/codemirror-extensions-basic-setup": "npm:4.24.2" + "@uiw/codemirror-extensions-basic-setup": "npm:4.25.3" codemirror: "npm:^6.0.0" peerDependencies: "@babel/runtime": ">=7.11.0" @@ -22306,14 +22544,149 @@ __metadata: codemirror: ">=6.0.0" react: ">=17.0.0" react-dom: ">=17.0.0" - checksum: 10/f0816fcf40c451c8bc15319d62f5b8d62a04c12c2bc053569212b31edba7c7164e45fd161ebb683a03fd5a50697b91a6ac4cab2d2d1a45da5f2626d959c399a0 + checksum: 10/a3ece671a48cce623da6c9d890f07bdbb1597b2fb2a6f8f6ef65f2b14b5d5b4fa90791476539b4fba3ac13d226fe00d283a5165d3632f34f5db3b49139a8887d languageName: node linkType: hard -"@ungap/structured-clone@npm:^1.2.0": - version: 1.2.0 - resolution: "@ungap/structured-clone@npm:1.2.0" - checksum: 10/c6fe89a505e513a7592e1438280db1c075764793a2397877ff1351721fe8792a966a5359769e30242b3cd023f2efb9e63ca2ca88019d73b564488cc20e3eab12 +"@ungap/structured-clone@npm:^1.2.0, @ungap/structured-clone@npm:^1.3.0": + version: 1.3.0 + resolution: "@ungap/structured-clone@npm:1.3.0" + checksum: 10/80d6910946f2b1552a2406650051c91bbd1f24a6bf854354203d84fe2714b3e8ce4618f49cc3410494173a1c1e8e9777372fe68dce74bd45faf0a7a1a6ccf448 + languageName: node + linkType: hard + +"@unrs/resolver-binding-android-arm-eabi@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-android-arm-eabi@npm:1.11.1" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@unrs/resolver-binding-android-arm64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-android-arm64@npm:1.11.1" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-darwin-arm64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-darwin-arm64@npm:1.11.1" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-darwin-x64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-darwin-x64@npm:1.11.1" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-freebsd-x64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-freebsd-x64@npm:1.11.1" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.11.1" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm-musleabihf@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm-musleabihf@npm:1.11.1" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm64-gnu@npm:1.11.1" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm64-musl@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm64-musl@npm:1.11.1" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-ppc64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-ppc64-gnu@npm:1.11.1" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-riscv64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-riscv64-gnu@npm:1.11.1" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-riscv64-musl@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-riscv64-musl@npm:1.11.1" + conditions: os=linux & cpu=riscv64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-s390x-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-s390x-gnu@npm:1.11.1" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-x64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-x64-gnu@npm:1.11.1" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-x64-musl@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-x64-musl@npm:1.11.1" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-wasm32-wasi@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-wasm32-wasi@npm:1.11.1" + dependencies: + "@napi-rs/wasm-runtime": "npm:^0.2.11" + conditions: cpu=wasm32 + languageName: node + linkType: hard + +"@unrs/resolver-binding-win32-arm64-msvc@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-win32-arm64-msvc@npm:1.11.1" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-win32-ia32-msvc@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-win32-ia32-msvc@npm:1.11.1" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@unrs/resolver-binding-win32-x64-msvc@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-win32-x64-msvc@npm:1.11.1" + conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -22327,24 +22700,24 @@ __metadata: languageName: node linkType: hard -"@useoptic/json-pointer-helpers@npm:1.0.8": - version: 1.0.8 - resolution: "@useoptic/json-pointer-helpers@npm:1.0.8" +"@useoptic/json-pointer-helpers@npm:1.0.9": + version: 1.0.9 + resolution: "@useoptic/json-pointer-helpers@npm:1.0.9" dependencies: jsonpointer: "npm:^5.0.1" minimatch: "npm:9.0.3" - checksum: 10/075142e33ab89de448283ef2199438e84942ad285600df33d6a8f3553e4d3ab60d139c080c0dcd667f60ee607cadedeceb904739b6d7b03d99c2558413f1b223 + checksum: 10/066c08f512998d3b971f801bbd8677f1da36a0bb7b4d45eb552e98e0813673b23644ec27bc99fac5d47959d6a88ee06b4a52f9bc916cc29ddb8f48d05f54c462 languageName: node linkType: hard -"@useoptic/openapi-io@npm:1.0.8": - version: 1.0.8 - resolution: "@useoptic/openapi-io@npm:1.0.8" +"@useoptic/openapi-io@npm:1.0.9": + version: 1.0.9 + resolution: "@useoptic/openapi-io@npm:1.0.9" dependencies: "@apidevtools/json-schema-ref-parser": "npm:9.0.9" "@jsdevtools/ono": "npm:^7.1.3" - "@useoptic/json-pointer-helpers": "npm:1.0.8" - "@useoptic/openapi-utilities": "npm:1.0.8" + "@useoptic/json-pointer-helpers": "npm:1.0.9" + "@useoptic/openapi-utilities": "npm:1.0.9" ajv: "npm:8.17.1" ajv-errors: "npm:~3.0.0" ajv-formats: "npm:~2.1.0" @@ -22362,15 +22735,15 @@ __metadata: upath: "npm:^2.0.1" yaml: "npm:^2.3.2" yaml-ast-parser: "npm:^0.0.43" - checksum: 10/1d228bf7191ed8496b1ddcb5478ff051f5d7d2014e8dfa4d0e60e3d2def1284dc607e35f6ccba3b36a2d6263ce5fdea0b573bf9a7164f122036f2d54831db159 + checksum: 10/d428fa70bd432d1cfe4d8f6073dd6d17b35e104a59c682bfe586b8bad3161b217b479767d19570629faa01804a90435a83f425c6080956d533abec4ff7bad486 languageName: node linkType: hard -"@useoptic/openapi-utilities@npm:1.0.8": - version: 1.0.8 - resolution: "@useoptic/openapi-utilities@npm:1.0.8" +"@useoptic/openapi-utilities@npm:1.0.9": + version: 1.0.9 + resolution: "@useoptic/openapi-utilities@npm:1.0.9" dependencies: - "@useoptic/json-pointer-helpers": "npm:1.0.8" + "@useoptic/json-pointer-helpers": "npm:1.0.9" ajv: "npm:8.17.1" ajv-errors: "npm:^3.0.0" ajv-formats: "npm:^3.0.1" @@ -22387,7 +22760,7 @@ __metadata: ts-invariant: "npm:^0.9.3" url-join: "npm:^4.0.1" yaml-ast-parser: "npm:^0.0.43" - checksum: 10/0c0b7ec345ca9b13553c096dbf39dc90e719fc4c21855134783b7c98896bd16b2bd7e19c5419a345e4e44705e928e8dafea574d20a075028ae50a5871042a5ea + checksum: 10/9808d95c6bfa6d41f206400695de26666f3bd1fd5601b052705199fab92fee1912ca2b841dce9a3d6b7dec87fb6fc39ccf0de636bef9d7d8f04736a8c1520b7f languageName: node linkType: hard @@ -22417,8 +22790,8 @@ __metadata: linkType: hard "@useoptic/optic@npm:^1.0.0": - version: 1.0.8 - resolution: "@useoptic/optic@npm:1.0.8" + version: 1.0.9 + resolution: "@useoptic/optic@npm:1.0.9" dependencies: "@babel/runtime": "npm:^7.20.6" "@httptoolkit/httpolyglot": "npm:^2.0.1" @@ -22428,10 +22801,10 @@ __metadata: "@sentry/node": "npm:^7.74.0" "@sinclair/typebox": "npm:0.31.28" "@stoplight/spectral-core": "npm:^1.8.1" - "@useoptic/openapi-io": "npm:1.0.8" - "@useoptic/openapi-utilities": "npm:1.0.8" - "@useoptic/rulesets-base": "npm:1.0.8" - "@useoptic/standard-rulesets": "npm:1.0.8" + "@useoptic/openapi-io": "npm:1.0.9" + "@useoptic/openapi-utilities": "npm:1.0.9" + "@useoptic/rulesets-base": "npm:1.0.9" + "@useoptic/standard-rulesets": "npm:1.0.9" ajv: "npm:8.17.1" ajv-formats: "npm:~2.1.0" async-exit-hook: "npm:^2.0.1" @@ -22488,34 +22861,34 @@ __metadata: yaml: "npm:^2.3.4" bin: optic: build/index.js - checksum: 10/7d9275697e068ffe72656bf38044d5724cc18b707e9507c65babe28f1b84017cc7be33abef4fa696fa9290e843342778d0131004aee76417fc902aa25d68038a + checksum: 10/84d05ec412c450a99626044220554ec94aa47ed42c897bd2d9cf6dbbd4c7e92b40a4c7b5429b7841eef95b2649d614339c1a73b52c45733cc6d4aaf6573d4120 languageName: node linkType: hard -"@useoptic/rulesets-base@npm:1.0.8": - version: 1.0.8 - resolution: "@useoptic/rulesets-base@npm:1.0.8" +"@useoptic/rulesets-base@npm:1.0.9": + version: 1.0.9 + resolution: "@useoptic/rulesets-base@npm:1.0.9" dependencies: "@stoplight/spectral-core": "npm:^1.8.1" "@stoplight/spectral-rulesets": "npm:^1.14.1" - "@useoptic/json-pointer-helpers": "npm:1.0.8" - "@useoptic/openapi-utilities": "npm:1.0.8" + "@useoptic/json-pointer-helpers": "npm:1.0.9" + "@useoptic/openapi-utilities": "npm:1.0.9" ajv: "npm:^8.6.0" lodash.pick: "npm:^4.4.0" node-fetch: "npm:^2.6.7" semver: "npm:^7.5.4" bin: rulesets-base: build/index.js - checksum: 10/d92a2f72dca642f61ea0a4f0318b0f9e689c647b30c90896c49cfd294ab635b096906c697e57cb28486cc647154025ede0328c72dfc785dd7e873429e316a5db + checksum: 10/335a507ca34e2d6279a23d8eb5ced6577ed83a18af221e21e490202d55e6835dc1572fc4399c8d90e6317fb3eaa9335e85139466b93efef4aaa5022268ea4a6e languageName: node linkType: hard -"@useoptic/standard-rulesets@npm:1.0.8": - version: 1.0.8 - resolution: "@useoptic/standard-rulesets@npm:1.0.8" +"@useoptic/standard-rulesets@npm:1.0.9": + version: 1.0.9 + resolution: "@useoptic/standard-rulesets@npm:1.0.9" dependencies: - "@useoptic/openapi-utilities": "npm:1.0.8" - "@useoptic/rulesets-base": "npm:1.0.8" + "@useoptic/openapi-utilities": "npm:1.0.9" + "@useoptic/rulesets-base": "npm:1.0.9" ajv: "npm:^8.6.0" ajv-draft-04: "npm:^1.0.0" ajv-formats: "npm:~2.1.0" @@ -22526,7 +22899,7 @@ __metadata: whatwg-mimetype: "npm:^3.0.0" bin: standard-rulesets: build/index.js - checksum: 10/63f60ac25fb8cccd0ea89097336cf5bc7ad59022ad6ef49fd382e7555f5ea9d88ca144991315eb07646aa309f5f38f3d056c4b7c869ab6b5f66fa9e93d96f4ef + checksum: 10/c4605dd4ffaf8623150cf1c0de846e44b4e3d506e3011d37fe28f7f3deaa911b908c9f135c245eb2d5641cd34bebc29b16d64d5ef2d3443c5fa1d489f3f2e803 languageName: node linkType: hard @@ -22846,9 +23219,9 @@ __metadata: linkType: hard "@xmldom/xmldom@npm:^0.8.3": - version: 0.8.10 - resolution: "@xmldom/xmldom@npm:0.8.10" - checksum: 10/62400bc5e0e75b90650e33a5ceeb8d94829dd11f9b260962b71a784cd014ddccec3e603fe788af9c1e839fa4648d8c521ebd80d8b752878d3a40edabc9ce7ccf + version: 0.8.11 + resolution: "@xmldom/xmldom@npm:0.8.11" + checksum: 10/f6d6ffdf71cf19d9b3c10e978fad40d2f85453bf5b2aa05be8aa0c5ad13f84690c3153316729213cc652d06ec12c605ddb0aa03886f1d73d51b974b4105d31e3 languageName: node linkType: hard @@ -23636,13 +24009,6 @@ __metadata: languageName: node linkType: hard -"abab@npm:^2.0.6": - version: 2.0.6 - resolution: "abab@npm:2.0.6" - checksum: 10/ebe95d7278999e605823fc515a3b05d689bc72e7f825536e73c95ebf621636874c6de1b749b3c4bf866b96ccd4b3a2802efa313d0e45ad51a413c8c73247db20 - languageName: node - linkType: hard - "abbrev@npm:1": version: 1.1.1 resolution: "abbrev@npm:1.1.1" @@ -23686,16 +24052,6 @@ __metadata: languageName: node linkType: hard -"acorn-globals@npm:^6.0.0": - version: 6.0.0 - resolution: "acorn-globals@npm:6.0.0" - dependencies: - acorn: "npm:^7.1.1" - acorn-walk: "npm:^7.1.1" - checksum: 10/72d95e5b5e585f9acd019b993ab8bbba68bb3cbc9d9b5c1ebb3c2f1fe5981f11deababfb4949f48e6262f9c57878837f5958c0cca396f81023814680ca878042 - languageName: node - linkType: hard - "acorn-import-attributes@npm:^1.9.5": version: 1.9.5 resolution: "acorn-import-attributes@npm:1.9.5" @@ -23723,13 +24079,6 @@ __metadata: languageName: node linkType: hard -"acorn-walk@npm:^7.1.1": - version: 7.1.1 - resolution: "acorn-walk@npm:7.1.1" - checksum: 10/f3cbf2f7eba3bd27b6e2c0a68d10304de365581fa30b129d0420697135791f44a6d1b0da341d40a2e8af319574f4bd5cb970279dd35fdd1fc5beacaba29c6a4e - languageName: node - linkType: hard - "acorn-walk@npm:^8.1.1": version: 8.2.0 resolution: "acorn-walk@npm:8.2.0" @@ -23737,16 +24086,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^7.1.1": - version: 7.4.1 - resolution: "acorn@npm:7.4.1" - bin: - acorn: bin/acorn - checksum: 10/8be2a40714756d713dfb62544128adce3b7102c6eb94bc312af196c2cc4af76e5b93079bd66b05e9ca31b35a9b0ce12171d16bc55f366cafdb794fdab9d753ec - languageName: node - linkType: hard - -"acorn@npm:^8.14.0, acorn@npm:^8.15.0, acorn@npm:^8.4.1, acorn@npm:^8.7.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": +"acorn@npm:^8.14.0, acorn@npm:^8.15.0, acorn@npm:^8.4.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": version: 8.15.0 resolution: "acorn@npm:8.15.0" bin: @@ -23910,7 +24250,7 @@ __metadata: languageName: node linkType: hard -"ajv@npm:^6.12.2, ajv@npm:^6.12.4, ajv@npm:^6.12.5, ajv@npm:^6.12.6": +"ajv@npm:^6.12.2, ajv@npm:^6.12.4, ajv@npm:^6.12.5": version: 6.12.6 resolution: "ajv@npm:6.12.6" dependencies: @@ -24027,9 +24367,9 @@ __metadata: linkType: hard "ansi-regex@npm:*, ansi-regex@npm:^6.0.1": - version: 6.1.0 - resolution: "ansi-regex@npm:6.1.0" - checksum: 10/495834a53b0856c02acd40446f7130cb0f8284f4a39afdab20d5dc42b2e198b1196119fe887beed8f9055c4ff2055e3b2f6d4641d0be018cdfb64fedf6fc1aac + version: 6.2.2 + resolution: "ansi-regex@npm:6.2.2" + checksum: 10/9b17ce2c6daecc75bcd5966b9ad672c23b184dc3ed9bf3c98a0702f0d2f736c15c10d461913568f2cf527a5e64291c7473358885dd493305c84a1cfed66ba94f languageName: node linkType: hard @@ -24065,7 +24405,7 @@ __metadata: languageName: node linkType: hard -"ansi-styles@npm:^5.0.0": +"ansi-styles@npm:^5.0.0, ansi-styles@npm:^5.2.0": version: 5.2.0 resolution: "ansi-styles@npm:5.2.0" checksum: 10/d7f4e97ce0623aea6bc0d90dcd28881ee04cba06c570b97fd3391bd7a268eedfd9d5e2dd4fdcbdd82b8105df5faf6f24aaedc08eaf3da898e702db5948f63469 @@ -24086,13 +24426,13 @@ __metadata: languageName: node linkType: hard -"anymatch@npm:^3.0.3, anymatch@npm:~3.1.2": - version: 3.1.2 - resolution: "anymatch@npm:3.1.2" +"anymatch@npm:^3.1.3, anymatch@npm:~3.1.2": + version: 3.1.3 + resolution: "anymatch@npm:3.1.3" dependencies: normalize-path: "npm:^3.0.0" picomatch: "npm:^2.0.4" - checksum: 10/985163db2292fac9e5a1e072bf99f1b5baccf196e4de25a0b0b81865ebddeb3b3eb4480734ef0a2ac8c002845396b91aa89121f5b84f93981a4658164a9ec6e9 + checksum: 10/3e044fd6d1d26545f235a9fe4d7a534e2029d8e59fa7fd9f2a6eb21230f6b5380ea1eaf55136e60cbf8e613544b3b766e7a6fa2102e2a3a117505466e3025dc2 languageName: node linkType: hard @@ -24299,7 +24639,7 @@ __metadata: languageName: node linkType: hard -"array-includes@npm:^3.1.6, array-includes@npm:^3.1.8": +"array-includes@npm:^3.1.6, array-includes@npm:^3.1.8, array-includes@npm:^3.1.9": version: 3.1.9 resolution: "array-includes@npm:3.1.9" dependencies: @@ -24343,21 +24683,22 @@ __metadata: languageName: node linkType: hard -"array.prototype.findlastindex@npm:^1.2.5": - version: 1.2.5 - resolution: "array.prototype.findlastindex@npm:1.2.5" +"array.prototype.findlastindex@npm:^1.2.6": + version: 1.2.6 + resolution: "array.prototype.findlastindex@npm:1.2.6" dependencies: - call-bind: "npm:^1.0.7" + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.4" define-properties: "npm:^1.2.1" - es-abstract: "npm:^1.23.2" + es-abstract: "npm:^1.23.9" es-errors: "npm:^1.3.0" - es-object-atoms: "npm:^1.0.0" - es-shim-unscopables: "npm:^1.0.2" - checksum: 10/7c5c821f357cd53ab6cc305de8086430dd8d7a2485db87b13f843e868055e9582b1fd338f02338f67fc3a1603ceaf9610dd2a470b0b506f9d18934780f95b246 + es-object-atoms: "npm:^1.1.1" + es-shim-unscopables: "npm:^1.1.0" + checksum: 10/5ddb6420e820bef6ddfdcc08ce780d0fd5e627e97457919c27e32359916de5a11ce12f7c55073555e503856618eaaa70845d6ca11dcba724766f38eb1c22f7a2 languageName: node linkType: hard -"array.prototype.flat@npm:^1.3.1, array.prototype.flat@npm:^1.3.2": +"array.prototype.flat@npm:^1.3.1, array.prototype.flat@npm:^1.3.3": version: 1.3.3 resolution: "array.prototype.flat@npm:1.3.3" dependencies: @@ -24551,6 +24892,20 @@ __metadata: languageName: node linkType: hard +"async-function@npm:^1.0.0": + version: 1.0.0 + resolution: "async-function@npm:1.0.0" + checksum: 10/1a09379937d846f0ce7614e75071c12826945d4e417db634156bf0e4673c495989302f52186dfa9767a1d9181794554717badd193ca2bbab046ef1da741d8efd + languageName: node + linkType: hard + +"async-generator-function@npm:^1.0.0": + version: 1.0.0 + resolution: "async-generator-function@npm:1.0.0" + checksum: 10/3d49e7acbeee9e84537f4cb0e0f91893df8eba976759875ae8ee9e3d3c82f6ecdebdb347c2fad9926b92596d93cdfc78ecc988bcdf407e40433e8e8e6fe5d78e + languageName: node + linkType: hard + "async-lock@npm:^1.4.1": version: 1.4.1 resolution: "async-lock@npm:1.4.1" @@ -24732,18 +25087,7 @@ __metadata: languageName: node linkType: hard -"axios@npm:1.9.0": - version: 1.9.0 - resolution: "axios@npm:1.9.0" - dependencies: - follow-redirects: "npm:^1.15.6" - form-data: "npm:^4.0.0" - proxy-from-env: "npm:^1.1.0" - checksum: 10/a2f90bba56820883879f32a237e2b9ff25c250365dcafd41cec41b3406a3df334a148f90010182dfdadb4b41dc59f6f0b3e8898ff41b666d1157b5f3f4523497 - languageName: node - linkType: hard - -"axios@npm:^1.0.0, axios@npm:^1.13.0, axios@npm:^1.6.0, axios@npm:^1.7.4, axios@npm:^1.8.3, axios@npm:^1.9.0": +"axios@npm:1.13.2, axios@npm:^1.0.0, axios@npm:^1.11.0, axios@npm:^1.12.2, axios@npm:^1.13.0, axios@npm:^1.7.4": version: 1.13.2 resolution: "axios@npm:1.13.2" dependencies: @@ -24778,45 +25122,42 @@ __metadata: languageName: node linkType: hard -"babel-jest@npm:^29.7.0": - version: 29.7.0 - resolution: "babel-jest@npm:29.7.0" +"babel-jest@npm:30.2.0": + version: 30.2.0 + resolution: "babel-jest@npm:30.2.0" dependencies: - "@jest/transform": "npm:^29.7.0" - "@types/babel__core": "npm:^7.1.14" - babel-plugin-istanbul: "npm:^6.1.1" - babel-preset-jest: "npm:^29.6.3" - chalk: "npm:^4.0.0" - graceful-fs: "npm:^4.2.9" + "@jest/transform": "npm:30.2.0" + "@types/babel__core": "npm:^7.20.5" + babel-plugin-istanbul: "npm:^7.0.1" + babel-preset-jest: "npm:30.2.0" + chalk: "npm:^4.1.2" + graceful-fs: "npm:^4.2.11" slash: "npm:^3.0.0" peerDependencies: - "@babel/core": ^7.8.0 - checksum: 10/8a0953bd813b3a8926008f7351611055548869e9a53dd36d6e7e96679001f71e65fd7dbfe253265c3ba6a4e630dc7c845cf3e78b17d758ef1880313ce8fba258 + "@babel/core": ^7.11.0 || ^8.0.0-0 + checksum: 10/4c7351a366cf8ac2b8a2e4e438867693eb9d83ed24c29c648da4576f700767aaf72a5d14337fc3f92c50b069f5025b26c7b89e3b7b867914b7cf8997fc15f095 languageName: node linkType: hard -"babel-plugin-istanbul@npm:^6.1.1": - version: 6.1.1 - resolution: "babel-plugin-istanbul@npm:6.1.1" +"babel-plugin-istanbul@npm:^7.0.1": + version: 7.0.1 + resolution: "babel-plugin-istanbul@npm:7.0.1" dependencies: "@babel/helper-plugin-utils": "npm:^7.0.0" "@istanbuljs/load-nyc-config": "npm:^1.0.0" - "@istanbuljs/schema": "npm:^0.1.2" - istanbul-lib-instrument: "npm:^5.0.4" + "@istanbuljs/schema": "npm:^0.1.3" + istanbul-lib-instrument: "npm:^6.0.2" test-exclude: "npm:^6.0.0" - checksum: 10/ffd436bb2a77bbe1942a33245d770506ab2262d9c1b3c1f1da7f0592f78ee7445a95bc2efafe619dd9c1b6ee52c10033d6c7d29ddefe6f5383568e60f31dfe8d + checksum: 10/fe9f865f975aaa7a033de9ccb2b63fdcca7817266c5e98d3e02ac7ffd774c695093d215302796cb3770a71ef4574e7a9b298504c3c0c104cf4b48c8eda67b2a6 languageName: node linkType: hard -"babel-plugin-jest-hoist@npm:^29.6.3": - version: 29.6.3 - resolution: "babel-plugin-jest-hoist@npm:29.6.3" +"babel-plugin-jest-hoist@npm:30.2.0": + version: 30.2.0 + resolution: "babel-plugin-jest-hoist@npm:30.2.0" dependencies: - "@babel/template": "npm:^7.3.3" - "@babel/types": "npm:^7.3.3" - "@types/babel__core": "npm:^7.1.14" - "@types/babel__traverse": "npm:^7.0.6" - checksum: 10/9bfa86ec4170bd805ab8ca5001ae50d8afcb30554d236ba4a7ffc156c1a92452e220e4acbd98daefc12bf0216fccd092d0a2efed49e7e384ec59e0597a926d65 + "@types/babel__core": "npm:^7.20.5" + checksum: 10/360e87a9aa35f4cf208a10ba79e1821ea906f9e3399db2a9762cbc5076fd59f808e571d88b5b1106738d22e23f9ddefbb8137b2780b2abd401c8573b85c8a2f5 languageName: node linkType: hard @@ -24864,37 +25205,40 @@ __metadata: languageName: node linkType: hard -"babel-preset-current-node-syntax@npm:^1.0.0": - version: 1.0.0 - resolution: "babel-preset-current-node-syntax@npm:1.0.0" +"babel-preset-current-node-syntax@npm:^1.2.0": + version: 1.2.0 + resolution: "babel-preset-current-node-syntax@npm:1.2.0" dependencies: "@babel/plugin-syntax-async-generators": "npm:^7.8.4" "@babel/plugin-syntax-bigint": "npm:^7.8.3" - "@babel/plugin-syntax-class-properties": "npm:^7.8.3" - "@babel/plugin-syntax-import-meta": "npm:^7.8.3" + "@babel/plugin-syntax-class-properties": "npm:^7.12.13" + "@babel/plugin-syntax-class-static-block": "npm:^7.14.5" + "@babel/plugin-syntax-import-attributes": "npm:^7.24.7" + "@babel/plugin-syntax-import-meta": "npm:^7.10.4" "@babel/plugin-syntax-json-strings": "npm:^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators": "npm:^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators": "npm:^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator": "npm:^7.8.3" - "@babel/plugin-syntax-numeric-separator": "npm:^7.8.3" + "@babel/plugin-syntax-numeric-separator": "npm:^7.10.4" "@babel/plugin-syntax-object-rest-spread": "npm:^7.8.3" "@babel/plugin-syntax-optional-catch-binding": "npm:^7.8.3" "@babel/plugin-syntax-optional-chaining": "npm:^7.8.3" - "@babel/plugin-syntax-top-level-await": "npm:^7.8.3" + "@babel/plugin-syntax-private-property-in-object": "npm:^7.14.5" + "@babel/plugin-syntax-top-level-await": "npm:^7.14.5" peerDependencies: - "@babel/core": ^7.0.0 - checksum: 10/2d45944dc78da3a7ec3bce2a48664bd33e21f5b718a724cc2860921d2e2152678a3de50df9a8d5add8c3c3a10b444925f03ead28090c9dde89ea695044a010db + "@babel/core": ^7.0.0 || ^8.0.0-0 + checksum: 10/3608fa671cfa46364ea6ec704b8fcdd7514b7b70e6ec09b1199e13ae73ed346c51d5ce2cb6d4d5b295f6a3f2cad1fdeec2308aa9e037002dd7c929194cc838ea languageName: node linkType: hard -"babel-preset-jest@npm:^29.6.3": - version: 29.6.3 - resolution: "babel-preset-jest@npm:29.6.3" +"babel-preset-jest@npm:30.2.0": + version: 30.2.0 + resolution: "babel-preset-jest@npm:30.2.0" dependencies: - babel-plugin-jest-hoist: "npm:^29.6.3" - babel-preset-current-node-syntax: "npm:^1.0.0" + babel-plugin-jest-hoist: "npm:30.2.0" + babel-preset-current-node-syntax: "npm:^1.2.0" peerDependencies: - "@babel/core": ^7.0.0 - checksum: 10/aa4ff2a8a728d9d698ed521e3461a109a1e66202b13d3494e41eea30729a5e7cc03b3a2d56c594423a135429c37bf63a9fa8b0b9ce275298be3095a88c69f6fb + "@babel/core": ^7.11.0 || ^8.0.0-beta.1 + checksum: 10/f75e155a8cf63ea1c5ca942bf757b934427630a1eeafdf861e9117879b3367931fc521da3c41fd52f8d59d705d1093ffb46c9474b3fd4d765d194bea5659d7d9 languageName: node linkType: hard @@ -25037,11 +25381,11 @@ __metadata: linkType: hard "baseline-browser-mapping@npm:^2.8.25": - version: 2.8.32 - resolution: "baseline-browser-mapping@npm:2.8.32" + version: 2.9.8 + resolution: "baseline-browser-mapping@npm:2.9.8" bin: baseline-browser-mapping: dist/cli.js - checksum: 10/d3223faeb8a5d5aa0c2aecc7ecff85e0f2452ba79f8a1ab170a828a1b0efd5eabf38a5264f8ea223cfdee526cf9df689cefbef2f4f22825fc462c37b3483c607 + checksum: 10/1c9cf2fb0cc008ba86d5f1bd1f1a771d6f508dbd6124d173549c650734d6d305eba49622e8bc0160beea9ecafcd2f5f104ffdc92f4a815a4926b74a2d7a6d986 languageName: node linkType: hard @@ -25075,15 +25419,6 @@ __metadata: languageName: node linkType: hard -"better-opn@npm:^3.0.2": - version: 3.0.2 - resolution: "better-opn@npm:3.0.2" - dependencies: - open: "npm:^8.0.4" - checksum: 10/24668e5a837d0d2c0edf17ad5ebcfeb00a8a5578a5eb09f7a409e1a60617cdfea40b8ebfc95e5f12d9568157930d033e6805788fcf0780413ac982c95d3745d1 - languageName: node - linkType: hard - "better-path-resolve@npm:1.0.0": version: 1.0.0 resolution: "better-path-resolve@npm:1.0.0" @@ -25094,13 +25429,13 @@ __metadata: linkType: hard "better-sqlite3@npm:^12.0.0": - version: 12.2.0 - resolution: "better-sqlite3@npm:12.2.0" + version: 12.5.0 + resolution: "better-sqlite3@npm:12.5.0" dependencies: bindings: "npm:^1.5.0" node-gyp: "npm:latest" prebuild-install: "npm:^7.1.1" - checksum: 10/2662e321237624d5813a7b97528dfc11fc5110b068d57f4096de82d7136e7e4a4b722a2a4266ddfb5095070712fd3d2542f6212ccb68e2d3eb2042498269e1cf + checksum: 10/8d81cde54231430d5b7fca8d7224ccdd13708ea769765e7a284af1744376568553016ed500f55e7ff992c57f12e29044da17a950adda2a4d361a5295c237d2ea languageName: node linkType: hard @@ -25117,6 +25452,15 @@ __metadata: languageName: node linkType: hard +"bidi-js@npm:^1.0.3": + version: 1.0.3 + resolution: "bidi-js@npm:1.0.3" + dependencies: + require-from-string: "npm:^2.0.2" + checksum: 10/c4341c7a98797efe3d186cd99d6f97e9030a4f959794ca200ef2ec0a678483a916335bba6c2c0608a21d04a221288a31c9fd0faa0cd9b3903b93594b42466a6a + languageName: node + linkType: hard + "big.js@npm:^5.2.2": version: 5.2.2 resolution: "big.js@npm:5.2.2" @@ -25381,13 +25725,6 @@ __metadata: languageName: node linkType: hard -"browser-process-hrtime@npm:^1.0.0": - version: 1.0.0 - resolution: "browser-process-hrtime@npm:1.0.0" - checksum: 10/e30f868cdb770b1201afb714ad1575dd86366b6e861900884665fb627109b3cc757c40067d3bfee1ff2a29c835257ea30725a8018a9afd02ac1c24b408b1e45f - languageName: node - linkType: hard - "browser-resolve@npm:^2.0.0": version: 2.0.0 resolution: "browser-resolve@npm:2.0.0" @@ -25525,7 +25862,7 @@ __metadata: languageName: node linkType: hard -"buffer-equal-constant-time@npm:1.0.1": +"buffer-equal-constant-time@npm:^1.0.1": version: 1.0.1 resolution: "buffer-equal-constant-time@npm:1.0.1" checksum: 10/80bb945f5d782a56f374b292770901065bad21420e34936ecbe949e57724b4a13874f735850dd1cc61f078773c4fb5493a41391e7bda40d1fa388d6bd80daaab @@ -25845,7 +26182,7 @@ __metadata: languageName: node linkType: hard -"callsites@npm:^3.0.0": +"callsites@npm:^3.0.0, callsites@npm:^3.1.0": version: 3.1.0 resolution: "callsites@npm:3.1.0" checksum: 10/072d17b6abb459c2ba96598918b55868af677154bec7e73d222ef95a8fdb9bbf7dae96a8421085cdad8cd190d86653b5b6dc55a4484f2e5b2e27d5e0c3fc15b3 @@ -25876,7 +26213,7 @@ __metadata: languageName: node linkType: hard -"camelcase@npm:^6.2.0": +"camelcase@npm:^6.2.0, camelcase@npm:^6.3.0": version: 6.3.0 resolution: "camelcase@npm:6.3.0" checksum: 10/8c96818a9076434998511251dcb2761a94817ea17dbdc37f47ac080bd088fc62c7369429a19e2178b993497132c8cbcf5cc1f44ba963e76782ba469c0474938d @@ -25903,9 +26240,9 @@ __metadata: linkType: hard "caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001754": - version: 1.0.30001759 - resolution: "caniuse-lite@npm:1.0.30001759" - checksum: 10/da0ec28dd993dffa99402914903426b9466d2798d41c1dc9341fcb7dd10f58fdd148122e2c65001246c030ba1c939645b7b4597f6321e3246dc792323bb11541 + version: 1.0.30001760 + resolution: "caniuse-lite@npm:1.0.30001760" + checksum: 10/ac5c13d00b946c3ace331d25379ed9d85743b1028aba79ae80402cb128b4b491122585144898fefb836d4d9879c13c717a081ae241a00420cbbc7e1b934ec685 languageName: node linkType: hard @@ -25961,9 +26298,9 @@ __metadata: linkType: hard "chalk@npm:^5.4.1": - version: 5.4.1 - resolution: "chalk@npm:5.4.1" - checksum: 10/29df3ffcdf25656fed6e95962e2ef86d14dfe03cd50e7074b06bad9ffbbf6089adbb40f75c00744d843685c8d008adaf3aed31476780312553caf07fa86e5bc7 + version: 5.6.2 + resolution: "chalk@npm:5.6.2" + checksum: 10/1b2f48f6fba1370670d5610f9cd54c391d6ede28f4b7062dd38244ea5768777af72e5be6b74fb6c6d54cb84c4a2dff3f3afa9b7cb5948f7f022cfd3d087989e0 languageName: node linkType: hard @@ -25988,6 +26325,13 @@ __metadata: languageName: node linkType: hard +"character-entities-legacy@npm:^3.0.0": + version: 3.0.0 + resolution: "character-entities-legacy@npm:3.0.0" + checksum: 10/7582af055cb488b626d364b7d7a4e46b06abd526fb63c0e4eb35bcb9c9799cc4f76b39f34fdccef2d1174ac95e53e9ab355aae83227c1a2505877893fce77731 + languageName: node + linkType: hard + "character-entities@npm:^1.0.0": version: 1.2.4 resolution: "character-entities@npm:1.2.4" @@ -26016,13 +26360,6 @@ __metadata: languageName: node linkType: hard -"chardet@npm:^0.7.0": - version: 0.7.0 - resolution: "chardet@npm:0.7.0" - checksum: 10/b0ec668fba5eeec575ed2559a0917ba41a6481f49063c8445400e476754e0957ee09e44dc032310f526182b8f1bf25e9d4ed371f74050af7be1383e06bc44952 - languageName: node - linkType: hard - "chardet@npm:^2.1.1": version: 2.1.1 resolution: "chardet@npm:2.1.1" @@ -26070,6 +26407,15 @@ __metadata: languageName: node linkType: hard +"chokidar@npm:^4.0.1": + version: 4.0.3 + resolution: "chokidar@npm:4.0.3" + dependencies: + readdirp: "npm:^4.0.1" + checksum: 10/bf2a575ea5596000e88f5db95461a9d59ad2047e939d5a4aac59dd472d126be8f1c1ff3c7654b477cf532d18f42a97279ef80ee847972fd2a25410bf00b80b59 + languageName: node + linkType: hard + "chownr@npm:^1.1.1": version: 1.1.4 resolution: "chownr@npm:1.1.4" @@ -26114,10 +26460,10 @@ __metadata: languageName: node linkType: hard -"ci-info@npm:^4.0.0": - version: 4.0.0 - resolution: "ci-info@npm:4.0.0" - checksum: 10/c983bb7ff1b06648f4a47432201abbd58291147d8ab5043dbb5c03e1a0e3fb2347f40d29b66a3044f28ffeb5dade01ac35aa6bd4e7464a44d9a49a3d7532415a +"ci-info@npm:^4.0.0, ci-info@npm:^4.2.0": + version: 4.3.1 + resolution: "ci-info@npm:4.3.1" + checksum: 10/9dc952bef67e665ccde2e7a552d42d5d095529d21829ece060a00925ede2dfa136160c70ef2471ea6ed6c9b133218b47c007f56955c0f1734a2e57f240aa7445 languageName: node linkType: hard @@ -26140,13 +26486,20 @@ __metadata: languageName: node linkType: hard -"cjs-module-lexer@npm:^1.0.0, cjs-module-lexer@npm:^1.2.2": +"cjs-module-lexer@npm:^1.2.2": version: 1.4.3 resolution: "cjs-module-lexer@npm:1.4.3" checksum: 10/d2b92f919a2dedbfd61d016964fce8da0035f827182ed6839c97cac56e8a8077cfa6a59388adfe2bc588a19cef9bbe830d683a76a6e93c51f65852062cfe2591 languageName: node linkType: hard +"cjs-module-lexer@npm:^2.1.0": + version: 2.1.1 + resolution: "cjs-module-lexer@npm:2.1.1" + checksum: 10/db4331152f4414f3a451865554290eb7d146699aa2aefe1504891951d791ab450f1a75b0477630a4f2942be26f257c4e0627fbfed29d322b5266956b3643f3c1 + languageName: node + linkType: hard + "classnames@npm:*, classnames@npm:^2.2.6, classnames@npm:^2.3.1, classnames@npm:^2.5.1": version: 2.5.1 resolution: "classnames@npm:2.5.1" @@ -26498,14 +26851,14 @@ __metadata: languageName: node linkType: hard -"collect-v8-coverage@npm:^1.0.0": - version: 1.0.0 - resolution: "collect-v8-coverage@npm:1.0.0" - checksum: 10/99d6059eb0e04bf792e27824d43d1139ede28914b7f55ddedd9c43594926221579fa6925ecc7e2f47dec14f5199e5ea3afbfc1da9a32ad542f859022d57f9d80 +"collect-v8-coverage@npm:^1.0.2": + version: 1.0.3 + resolution: "collect-v8-coverage@npm:1.0.3" + checksum: 10/656443261fb7b79cf79e89cba4b55622b07c1d4976c630829d7c5c585c73cda1c2ff101f316bfb19bb9e2c58d724c7db1f70a21e213dcd14099227c5e6019860 languageName: node linkType: hard -"color-convert@npm:^1.9.0, color-convert@npm:^1.9.1": +"color-convert@npm:^1.9.0": version: 1.9.3 resolution: "color-convert@npm:1.9.3" dependencies: @@ -26523,6 +26876,15 @@ __metadata: languageName: node linkType: hard +"color-convert@npm:^3.1.3": + version: 3.1.3 + resolution: "color-convert@npm:3.1.3" + dependencies: + color-name: "npm:^2.0.0" + checksum: 10/36b9b99c138f90eb11a28d1ad911054a9facd6cffde4f00dc49a34ebde7cae28454b2285ede64f273b6a8df9c3228b80e4352f4471978fa8b5005fe91341a67b + languageName: node + linkType: hard + "color-name@npm:1.1.3": version: 1.1.3 resolution: "color-name@npm:1.1.3" @@ -26530,20 +26892,26 @@ __metadata: languageName: node linkType: hard -"color-name@npm:^1.0.0, color-name@npm:^1.1.4, color-name@npm:~1.1.4": +"color-name@npm:^1.1.4, color-name@npm:~1.1.4": version: 1.1.4 resolution: "color-name@npm:1.1.4" checksum: 10/b0445859521eb4021cd0fb0cc1a75cecf67fceecae89b63f62b201cca8d345baf8b952c966862a9d9a2632987d4f6581f0ec8d957dfacece86f0a7919316f610 languageName: node linkType: hard -"color-string@npm:^1.5.2": - version: 1.9.0 - resolution: "color-string@npm:1.9.0" +"color-name@npm:^2.0.0": + version: 2.1.0 + resolution: "color-name@npm:2.1.0" + checksum: 10/eb014f71d87408e318e95d3f554f188370d354ba8e0ffa4341d0fd19de391bfe2bc96e563d4f6614644d676bc24f475560dffee3fe310c2d6865d007410a9a2b + languageName: node + linkType: hard + +"color-string@npm:^2.1.3": + version: 2.1.4 + resolution: "color-string@npm:2.1.4" dependencies: - color-name: "npm:^1.0.0" - simple-swizzle: "npm:^0.2.2" - checksum: 10/6e347b463aa8e40eb193d6ee21ef501c88dad9c20c4607f5394f3b3c4ce40d828c87a35ac4acdc94696d8dae00a04cb30f0bc73f001ccc812f1d58dccaf26591 + color-name: "npm:^2.0.0" + checksum: 10/689a8688ac3cd55247792c83a9db9bfe675343c7412fedba1eb748ac6a8867dd2bb3d406e309ebfe90336809ee5067c7f2cccfbd10133c5cc9ef1dba5aad58f2 languageName: node linkType: hard @@ -26556,13 +26924,13 @@ __metadata: languageName: node linkType: hard -"color@npm:3.0.x": - version: 3.0.0 - resolution: "color@npm:3.0.0" +"color@npm:^5.0.2": + version: 5.0.3 + resolution: "color@npm:5.0.3" dependencies: - color-convert: "npm:^1.9.1" - color-string: "npm:^1.5.2" - checksum: 10/17ca34cc7d1aa1b41cb414c388ed0376e70401b42e9ca0320ee095f664373bc76f5934d81cb8e118ab6795994ca8abe396261da6ad308d5151b4dcf03cfc9cf9 + color-convert: "npm:^3.1.3" + color-string: "npm:^2.1.3" + checksum: 10/88063ee058b995e5738092b5aa58888666275d1e967333f3814ff4fa334ce9a9e71de78a16fb1838f17c80793ea87f4878c20192037662809fe14eab2d474fd9 languageName: node linkType: hard @@ -26594,16 +26962,6 @@ __metadata: languageName: node linkType: hard -"colorspace@npm:1.1.x": - version: 1.1.2 - resolution: "colorspace@npm:1.1.2" - dependencies: - color: "npm:3.0.x" - text-hex: "npm:1.0.x" - checksum: 10/a959ec1669176aa72185067b7d04dae1cef2698456e1a452a035ce8adcac95673fbb1547e3240903355bcbaa67e031cca0b8b4f7d42c256b3dd94dcead8e1405 - languageName: node - linkType: hard - "combined-stream@npm:^1.0.8": version: 1.0.8 resolution: "combined-stream@npm:1.0.8" @@ -26690,7 +27048,7 @@ __metadata: languageName: node linkType: hard -"commander@npm:^4.0.0, commander@npm:^4.1.1": +"commander@npm:^4.0.0": version: 4.1.1 resolution: "commander@npm:4.1.1" checksum: 10/3b2dc4125f387dab73b3294dbcb0ab2a862f9c0ad748ee2b27e3544d25325b7a8cdfbcc228d103a98a716960b14478114a5206b5415bd48cdafa38797891562c @@ -26725,17 +27083,17 @@ __metadata: languageName: node linkType: hard -"compare-versions@npm:4.1.4": - version: 4.1.4 - resolution: "compare-versions@npm:4.1.4" - checksum: 10/0c4f0d943477b824234f5c6600ea7404a86ef506c696b9d91ee67979bd32c08371a8b6532cc17e6e17cf2916e46ef16d499dce70245a4f6786c3c055afcea697 +"compare-versions@npm:6.1.1": + version: 6.1.1 + resolution: "compare-versions@npm:6.1.1" + checksum: 10/9325c0fadfba81afa0ec17e6fc2ef823ba785c693089698b8d9374e5460509f1916a88591644d4cb4045c9a58e47fafbcc0724fe8bf446d2a875a3d6eeddf165 languageName: node linkType: hard -"component-emitter@npm:^1.3.0": - version: 1.3.0 - resolution: "component-emitter@npm:1.3.0" - checksum: 10/dfc1ec2e7aa2486346c068f8d764e3eefe2e1ca0b24f57506cd93b2ae3d67829a7ebd7cc16e2bf51368fac2f45f78fcff231718e40b1975647e4a86be65e1d05 +"component-emitter@npm:^1.3.1": + version: 1.3.1 + resolution: "component-emitter@npm:1.3.1" + checksum: 10/94550aa462c7bd5a61c1bc480e28554aa306066930152d1b1844a0dd3845d4e5db7e261ddec62ae184913b3e59b55a2ad84093b9d3596a8f17c341514d6c483d languageName: node linkType: hard @@ -26762,17 +27120,17 @@ __metadata: linkType: hard "compression@npm:^1.7.4": - version: 1.7.5 - resolution: "compression@npm:1.7.5" + version: 1.8.1 + resolution: "compression@npm:1.8.1" dependencies: bytes: "npm:3.1.2" compressible: "npm:~2.0.18" debug: "npm:2.6.9" negotiator: "npm:~0.6.4" - on-headers: "npm:~1.0.2" + on-headers: "npm:~1.1.0" safe-buffer: "npm:5.2.1" vary: "npm:~1.1.2" - checksum: 10/c69cf6da151db6f9db2e242b6a0039ad41975ee886c385cff2920c5f8f7050678e0ee9a021437af033536c451791de529de376851b8d31fee42ca2d6adca03f0 + checksum: 10/e7552bfbd780f2003c6fe8decb44561f5cc6bc82f0c61e81122caff5ec656f37824084f52155b1e8ef31d7656cecbec9a2499b7a68e92e20780ffb39b479abb7 languageName: node linkType: hard @@ -26834,21 +27192,20 @@ __metadata: languageName: node linkType: hard -"concurrently@npm:6.5.1": - version: 6.5.1 - resolution: "concurrently@npm:6.5.1" +"concurrently@npm:9.2.1": + version: 9.2.1 + resolution: "concurrently@npm:9.2.1" dependencies: - chalk: "npm:^4.1.0" - date-fns: "npm:^2.16.1" - lodash: "npm:^4.17.21" - rxjs: "npm:^6.6.3" - spawn-command: "npm:^0.0.2-1" - supports-color: "npm:^8.1.0" - tree-kill: "npm:^1.2.2" - yargs: "npm:^16.2.0" + chalk: "npm:4.1.2" + rxjs: "npm:7.8.2" + shell-quote: "npm:1.8.3" + supports-color: "npm:8.1.1" + tree-kill: "npm:1.2.2" + yargs: "npm:17.7.2" bin: - concurrently: bin/concurrently.js - checksum: 10/9ea52a75547418b64fd9d6a956f2f6ffc5b5262d99958b258dce4403b041e81dc79ae09dd9edeb4ba81df1fd6bf62d73e779b8a23c1a76e5464b151830bd92d8 + conc: dist/bin/concurrently.js + concurrently: dist/bin/concurrently.js + checksum: 10/2a6b1acbcdbeb478926b80fd81d0b7e075fa16d78a76ceb43f0478b8aeea1c70781379be2f7d6a2528e51fac48ce4ebb686ae2328e4b35e0b1d17234f121c700 languageName: node linkType: hard @@ -27096,9 +27453,9 @@ __metadata: linkType: hard "core-js@npm:^3.6.5": - version: 3.39.0 - resolution: "core-js@npm:3.39.0" - checksum: 10/a3d34e669783dfc878e545f1983f60d9ff48a3867cd1d7ff8839b849e053002a208c7c14a5ca354b8e0b54982901e2f83dc87c3d9b95de0a94b4071d1c74e5f6 + version: 3.47.0 + resolution: "core-js@npm:3.47.0" + checksum: 10/c02dc6a091c7e6799e3527dc06a428c44bbcff7f8f6ee700ff818b90aa2ebaf1f17b0234146e692811da97cda5a39a6095ecadec9fd1a74b1135103eb0e96cb1 languageName: node linkType: hard @@ -27260,23 +27617,6 @@ __metadata: languageName: node linkType: hard -"create-jest@npm:^29.7.0": - version: 29.7.0 - resolution: "create-jest@npm:29.7.0" - dependencies: - "@jest/types": "npm:^29.6.3" - chalk: "npm:^4.0.0" - exit: "npm:^0.1.2" - graceful-fs: "npm:^4.2.9" - jest-config: "npm:^29.7.0" - jest-util: "npm:^29.7.0" - prompts: "npm:^2.0.1" - bin: - create-jest: bin/create-jest.js - checksum: 10/847b4764451672b4174be4d5c6d7d63442ec3aa5f3de52af924e4d996d87d7801c18e125504f25232fc75840f6625b3ac85860fac6ce799b5efae7bdcaf4a2b7 - languageName: node - linkType: hard - "create-require@npm:^1.1.0, create-require@npm:^1.1.1": version: 1.1.1 resolution: "create-require@npm:1.1.1" @@ -27301,21 +27641,21 @@ __metadata: linkType: hard "cron@npm:^3.0.0": - version: 3.3.2 - resolution: "cron@npm:3.3.2" + version: 3.5.0 + resolution: "cron@npm:3.5.0" dependencies: "@types/luxon": "npm:~3.4.0" luxon: "npm:~3.5.0" - checksum: 10/6be3309a2c56c75a90862987649e45d6ae17b45ef7949cc1ef3b5559665193efde2880c2729bf84ff4c9dc64a6e210d525e1e4f0a7ece4abe3acb9de2726386a + checksum: 10/0e667d87c9acc162db835439bff2664483f1fcbd471ae30a26c7426c736fa1798d27067cc4d0294d8a27890a1bc6c9deeefe47811cc339f11a8ba8288f51886d languageName: node linkType: hard "cronstrue@npm:^2.32.0": - version: 2.52.0 - resolution: "cronstrue@npm:2.52.0" + version: 2.59.0 + resolution: "cronstrue@npm:2.59.0" bin: cronstrue: bin/cli.js - checksum: 10/123725180e7bd6e77a1fbe6205cd6c3d55f45edd7bf4ddeabee85a277e905d55bbde73efc98369c8011db198a65f5d629f6709e5d968e5e46eba87ede1a1ba65 + checksum: 10/daa7a1ea7e4a40cdb533df754489142358ecdc23462ec57309fec61e539b84ae886d3ac4666a6133403f1b13a98834ca107a09f5f78d31e6cfac8625dd3422c3 languageName: node linkType: hard @@ -27332,20 +27672,20 @@ __metadata: linkType: hard "cross-fetch@npm:^3.1.5": - version: 3.1.8 - resolution: "cross-fetch@npm:3.1.8" + version: 3.2.0 + resolution: "cross-fetch@npm:3.2.0" dependencies: - node-fetch: "npm:^2.6.12" - checksum: 10/ac8c4ca87d2ac0e17a19b6a293a67ee8934881aee5ec9a5a8323c30e9a9a60a0f5291d3c0d633ec2a2f970cbc60978d628804dfaf03add92d7e720b6d37f392c + node-fetch: "npm:^2.7.0" + checksum: 10/e4ab1d390a5b6ca8bb0605f028af2ffc1127d2e407b954654949f506d04873c4863ece264662c074865d7874060e35f938cec74fe7b5736d46d545e2685f6aec languageName: node linkType: hard "cross-fetch@npm:^4.0.0": - version: 4.0.0 - resolution: "cross-fetch@npm:4.0.0" + version: 4.1.0 + resolution: "cross-fetch@npm:4.1.0" dependencies: - node-fetch: "npm:^2.6.12" - checksum: 10/e231a71926644ef122d334a3a4e73d9ba3ba4b480a8a277fb9badc434c1ba905b3d60c8034e18b348361a09afbec40ba9371036801ba2b675a7b84588f9f55d8 + node-fetch: "npm:^2.7.0" + checksum: 10/07624940607b64777d27ec9c668ddb6649e8c59ee0a5a10e63a51ce857e2bbb1294a45854a31c10eccb91b65909a5b199fcb0217339b44156f85900a7384f489 languageName: node linkType: hard @@ -27536,6 +27876,16 @@ __metadata: languageName: node linkType: hard +"css-tree@npm:^3.1.0": + version: 3.1.0 + resolution: "css-tree@npm:3.1.0" + dependencies: + mdn-data: "npm:2.12.2" + source-map-js: "npm:^1.0.1" + checksum: 10/e8c5c8e98e3aa4a620fda0b813ce57ccf99281652bf9d23e5cdfc9961c9a93a6769941f9a92e31e65d90f446f42fa83879ab0185206dc7a178d9f656d0913e14 + languageName: node + linkType: hard + "css-vendor@npm:^2.0.8": version: 2.0.8 resolution: "css-vendor@npm:2.0.8" @@ -27640,35 +27990,24 @@ __metadata: languageName: node linkType: hard -"cssom@npm:^0.5.0": - version: 0.5.0 - resolution: "cssom@npm:0.5.0" - checksum: 10/b502a315b1ce020a692036cc38cb36afa44157219b80deadfa040ab800aa9321fcfbecf02fd2e6ec87db169715e27978b4ab3701f916461e9cf7808899f23b54 - languageName: node - linkType: hard - -"cssom@npm:~0.3.6": - version: 0.3.8 - resolution: "cssom@npm:0.3.8" - checksum: 10/49eacc88077555e419646c0ea84ddc73c97e3a346ad7cb95e22f9413a9722d8964b91d781ce21d378bd5ae058af9a745402383fa4e35e9cdfd19654b63f892a9 - languageName: node - linkType: hard - -"cssstyle@npm:^2.3.0": - version: 2.3.0 - resolution: "cssstyle@npm:2.3.0" - dependencies: - cssom: "npm:~0.3.6" - checksum: 10/46f7f05a153446c4018b0454ee1464b50f606cb1803c90d203524834b7438eb52f3b173ba0891c618f380ced34ee12020675dc0052a7f1be755fe4ebc27ee977 - languageName: node - linkType: hard - "cssstyle@npm:^4.1.0": - version: 4.1.0 - resolution: "cssstyle@npm:4.1.0" + version: 4.6.0 + resolution: "cssstyle@npm:4.6.0" dependencies: - rrweb-cssom: "npm:^0.7.1" - checksum: 10/8ca9e2d1f1b24f93bb5f3f20a7a1e271e58060957880e985ee55614e196a798ffab309ec6bac105af8a439a6764546761813835ebb7f929d60823637ee838a8f + "@asamuzakjp/css-color": "npm:^3.2.0" + rrweb-cssom: "npm:^0.8.0" + checksum: 10/1cb25c9d66b87adb165f978b75cdeb6f225d7e31ba30a8934666046a0be037e4e7200d359bfa79d4f1a4aef1083ea09633b81bcdb36a2f2ac888e8c73ea3a289 + languageName: node + linkType: hard + +"cssstyle@npm:^5.3.4": + version: 5.3.4 + resolution: "cssstyle@npm:5.3.4" + dependencies: + "@asamuzakjp/css-color": "npm:^4.1.0" + "@csstools/css-syntax-patches-for-csstree": "npm:1.0.14" + css-tree: "npm:^3.1.0" + checksum: 10/4eeb85cbaba47c2e4eb9f9a9dea9633e311f1cb706258f582fc8d099edc0b8c0deea93a6943981960d7f920ac0f3bbb5277cc4c355915406c17a95d0049a073d languageName: node linkType: hard @@ -27694,9 +28033,9 @@ __metadata: linkType: hard "ctrlc-windows@npm:^2.1.0": - version: 2.1.0 - resolution: "ctrlc-windows@npm:2.1.0" - checksum: 10/518015cf2ac9a12bc327d4eb68f5d5c9d17b7ee369b80d8bc94473a08343587f7a39cf32074bd9b4d4e4b441fad6399475cf353e1470eb443e4d230b80fa9c5f + version: 2.2.0 + resolution: "ctrlc-windows@npm:2.2.0" + checksum: 10/3d044eda5aa8c58d35e34b05249f9330e7258bec88999e50f25fd21807c2bedabbcab28e10a24e60c15748267ef0ebf9a915d4e430f484d5ce2ec5c75663c352 languageName: node linkType: hard @@ -27829,17 +28168,6 @@ __metadata: languageName: node linkType: hard -"data-urls@npm:^3.0.2": - version: 3.0.2 - resolution: "data-urls@npm:3.0.2" - dependencies: - abab: "npm:^2.0.6" - whatwg-mimetype: "npm:^3.0.0" - whatwg-url: "npm:^11.0.0" - checksum: 10/033fc3dd0fba6d24bc9a024ddcf9923691dd24f90a3d26f6545d6a2f71ec6956f93462f2cdf2183cc46f10dc01ed3bcb36731a8208456eb1a08147e571fe2a76 - languageName: node - linkType: hard - "data-urls@npm:^5.0.0": version: 5.0.0 resolution: "data-urls@npm:5.0.0" @@ -27850,6 +28178,16 @@ __metadata: languageName: node linkType: hard +"data-urls@npm:^6.0.0": + version: 6.0.0 + resolution: "data-urls@npm:6.0.0" + dependencies: + whatwg-mimetype: "npm:^4.0.0" + whatwg-url: "npm:^15.0.0" + checksum: 10/a47f0dde184337c4f168d455aedf0b486fed87b6ca583b4b9ad55d1515f4836b418d4bdc5b5b6fc55e321feb826029586a0d47e1c9a9e7ac4d52a78faceb7fb0 + languageName: node + linkType: hard + "data-view-buffer@npm:^1.0.2": version: 1.0.2 resolution: "data-view-buffer@npm:1.0.2" @@ -27952,7 +28290,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:4.4.3, debug@npm:^4, debug@npm:^4.0.0, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4, debug@npm:^4.3.5, debug@npm:^4.3.6, debug@npm:^4.4.0, debug@npm:^4.4.3": +"debug@npm:4, debug@npm:4.4.3, debug@npm:^4, debug@npm:^4.0.0, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4, debug@npm:^4.3.5, debug@npm:^4.3.6, debug@npm:^4.3.7, debug@npm:^4.4.0, debug@npm:^4.4.1, debug@npm:^4.4.3": version: 4.4.3 resolution: "debug@npm:4.4.3" dependencies: @@ -27992,10 +28330,10 @@ __metadata: languageName: node linkType: hard -"decimal.js@npm:10, decimal.js@npm:^10.3.1, decimal.js@npm:^10.4.3": - version: 10.4.3 - resolution: "decimal.js@npm:10.4.3" - checksum: 10/de663a7bc4d368e3877db95fcd5c87b965569b58d16cdc4258c063d231ca7118748738df17cd638f7e9dd0be8e34cec08d7234b20f1f2a756a52fc5a38b188d0 +"decimal.js@npm:10, decimal.js@npm:^10.4.3, decimal.js@npm:^10.6.0": + version: 10.6.0 + resolution: "decimal.js@npm:10.6.0" + checksum: 10/c0d45842d47c311d11b38ce7ccc911121953d4df3ebb1465d92b31970eb4f6738a065426a06094af59bee4b0d64e42e7c8984abd57b6767c64ea90cf90bb4a69 languageName: node linkType: hard @@ -28026,15 +28364,15 @@ __metadata: languageName: node linkType: hard -"dedent@npm:^1.0.0": - version: 1.5.3 - resolution: "dedent@npm:1.5.3" +"dedent@npm:^1.6.0": + version: 1.7.0 + resolution: "dedent@npm:1.7.0" peerDependencies: babel-plugin-macros: ^3.1.0 peerDependenciesMeta: babel-plugin-macros: optional: true - checksum: 10/e5277f6268f288649503125b781a7b7a2c9b22d011139688c0b3619fe40121e600eb1f077c891938d4b2428bdb6326cc3c77a763e4b1cc681bd9666ab1bad2a1 + checksum: 10/c902f3e7e828923bd642c12c1d8996616ff5588f8279a2951790bd7c7e479fa4dd7f016b55ce2c9ea1aa2895fc503e7d6c0cde6ebc95ca683ac0230f7c911fd7 languageName: node linkType: hard @@ -28196,16 +28534,17 @@ __metadata: linkType: hard "del@npm:^8.0.0": - version: 8.0.0 - resolution: "del@npm:8.0.0" + version: 8.0.1 + resolution: "del@npm:8.0.1" dependencies: globby: "npm:^14.0.2" is-glob: "npm:^4.0.3" is-path-cwd: "npm:^3.0.0" is-path-inside: "npm:^4.0.0" p-map: "npm:^7.0.2" + presentable-error: "npm:^0.0.1" slash: "npm:^5.1.0" - checksum: 10/502dea7a846f989e1d921733f5d41ae4ae9b3eff168d335bfc050c9ce938ddc46198180be133814269268c4b0aed441a82fbace948c0ec5eed4ed086a4ad3b0e + checksum: 10/53ed4a379a68c90e7d6d3bcce09c49229e77de9a946d0a5fc25f45b16c950cb8665986b7d0d0423416c03bfd43e0f31e528c5a19c558fe47449be9d6fae7f846 languageName: node linkType: hard @@ -28308,7 +28647,7 @@ __metadata: languageName: node linkType: hard -"destroyable-server@npm:^1.0.0, destroyable-server@npm:^1.0.2": +"destroyable-server@npm:^1.0.0, destroyable-server@npm:^1.1.1": version: 1.1.1 resolution: "destroyable-server@npm:1.1.1" dependencies: @@ -28338,7 +28677,7 @@ __metadata: languageName: node linkType: hard -"detect-newline@npm:^3.0.0": +"detect-newline@npm:^3.1.0": version: 3.1.0 resolution: "detect-newline@npm:3.1.0" checksum: 10/ae6cd429c41ad01b164c59ea36f264a2c479598e61cba7c99da24175a7ab80ddf066420f2bec9a1c57a6bead411b4655ff15ad7d281c000a89791f48cbe939e7 @@ -28692,15 +29031,6 @@ __metadata: languageName: node linkType: hard -"domexception@npm:^4.0.0": - version: 4.0.0 - resolution: "domexception@npm:4.0.0" - dependencies: - webidl-conversions: "npm:^7.0.0" - checksum: 10/4ed443227d2871d76c58d852b2e93c68e0443815b2741348f20881bedee8c1ad4f9bfc5d30c7dec433cd026b57da63407c010260b1682fef4c8847e7181ea43f - languageName: node - linkType: hard - "domhandler@npm:^4.0.0, domhandler@npm:^4.2.0, domhandler@npm:^4.3.1": version: 4.3.1 resolution: "domhandler@npm:4.3.1" @@ -28719,19 +29049,7 @@ __metadata: languageName: node linkType: hard -"dompurify@npm:=3.2.4": - version: 3.2.4 - resolution: "dompurify@npm:3.2.4" - dependencies: - "@types/trusted-types": "npm:^2.0.7" - dependenciesMeta: - "@types/trusted-types": - optional: true - checksum: 10/98570c53385518a2f9b617f796926338856acfdd3369c88b5905bddf96bd7d391bf8a5433127155e0046e6faa2bfb767185fcd571b865dfabe624c099e2537f5 - languageName: node - linkType: hard - -"dompurify@npm:^3.1.7, dompurify@npm:^3.2.4": +"dompurify@npm:=3.2.6": version: 3.2.6 resolution: "dompurify@npm:3.2.6" dependencies: @@ -28743,6 +29061,18 @@ __metadata: languageName: node linkType: hard +"dompurify@npm:^3.1.7, dompurify@npm:^3.2.4": + version: 3.3.1 + resolution: "dompurify@npm:3.3.1" + dependencies: + "@types/trusted-types": "npm:^2.0.7" + dependenciesMeta: + "@types/trusted-types": + optional: true + checksum: 10/f71cca489e628591165d16e8cf4fa4f0d3e2ee48db4d73e9d2c5bedc6f915c92f9e9f101f8c4ba790bec0cdffe7f4e1747f5e31c69dc53ce7ae20a81ff6b0022 + languageName: node + linkType: hard + "domutils@npm:^2.5.2, domutils@npm:^2.8.0": version: 2.8.0 resolution: "domutils@npm:2.8.0" @@ -28916,19 +29246,6 @@ __metadata: languageName: node linkType: hard -"easy-table@npm:1.2.0": - version: 1.2.0 - resolution: "easy-table@npm:1.2.0" - dependencies: - ansi-regex: "npm:^5.0.1" - wcwidth: "npm:^1.0.1" - dependenciesMeta: - wcwidth: - optional: true - checksum: 10/0d1be7cd9419cd1b56ca5a978646b3cff241ccd8cf95bdb2742f36854084b3aef2e9af6ec14142855aa80e4cab1f4baad0f610a99c77509f23676b8330730177 - languageName: node - linkType: hard - "ebnf@npm:^1.9.1": version: 1.9.1 resolution: "ebnf@npm:1.9.1" @@ -28966,18 +29283,11 @@ __metadata: linkType: hard "elastic-builder@npm:^2.16.0": - version: 2.30.0 - resolution: "elastic-builder@npm:2.30.0" + version: 2.31.1 + resolution: "elastic-builder@npm:2.31.1" dependencies: - lodash.has: "npm:^4.5.2" - lodash.hasin: "npm:^4.5.2" - lodash.head: "npm:^4.0.1" - lodash.isempty: "npm:^4.4.0" - lodash.isnil: "npm:^4.0.0" - lodash.isobject: "npm:^3.0.2" - lodash.isstring: "npm:^4.0.1" - lodash.omit: "npm:^4.5.0" - checksum: 10/10b3e0cd3b24c680a9be6a480e4eb7869daf52ff536b56132f9b906fd577cea8eabfd5baf691768ed92cbb23454575b85ec760a72f7a743ee35b43d199749a4e + lodash: "npm:^4.17.21" + checksum: 10/8aadd17710114ddd313c9ed3d023769985257877888e466783230d7bdcc5a7747ce0542ad27802af62a0a99791099e470e2f2b83c114007c445d6d0061496719 languageName: node linkType: hard @@ -29038,6 +29348,13 @@ __metadata: languageName: node linkType: hard +"empathic@npm:^2.0.0": + version: 2.0.0 + resolution: "empathic@npm:2.0.0" + checksum: 10/90f47d93f8d1db3aa00ce1bfae2940bf76379dbb34bd562edbd92c3564a173cb1d6bd3cadb645fad0224839c25886abde801155d9b972dda6add7a5cc8b35d48 + languageName: node + linkType: hard + "enabled@npm:2.0.x": version: 2.0.0 resolution: "enabled@npm:2.0.0" @@ -29129,6 +29446,13 @@ __metadata: languageName: node linkType: hard +"entities@npm:^6.0.0": + version: 6.0.1 + resolution: "entities@npm:6.0.1" + checksum: 10/62af1307202884349d2867f0aac5c60d8b57102ea0b0e768b16246099512c28e239254ad772d6834e7e14cb1b6f153fc3d0c031934e3183b086c86d3838d874a + languageName: node + linkType: hard + "entities@npm:~2.1.0": version: 2.1.0 resolution: "entities@npm:2.1.0" @@ -29182,7 +29506,7 @@ __metadata: languageName: node linkType: hard -"es-abstract@npm:^1.17.5, es-abstract@npm:^1.20.4, es-abstract@npm:^1.22.1, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3, es-abstract@npm:^1.23.5, es-abstract@npm:^1.23.6, es-abstract@npm:^1.24.0": +"es-abstract@npm:^1.17.5, es-abstract@npm:^1.20.4, es-abstract@npm:^1.22.1, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3, es-abstract@npm:^1.23.5, es-abstract@npm:^1.23.6, es-abstract@npm:^1.23.9, es-abstract@npm:^1.24.0": version: 1.24.0 resolution: "es-abstract@npm:1.24.0" dependencies: @@ -29321,7 +29645,7 @@ __metadata: languageName: node linkType: hard -"es-module-lexer@npm:^1.2.1, es-module-lexer@npm:^1.3.1": +"es-module-lexer@npm:^1.2.1, es-module-lexer@npm:^1.6.0": version: 1.7.0 resolution: "es-module-lexer@npm:1.7.0" checksum: 10/b6f3e576a3fed4d82b0d0ad4bbf6b3a5ad694d2e7ce8c4a069560da3db6399381eaba703616a182b16dde50ce998af64e07dcf49f2ae48153b9e07be3f107087 @@ -29349,7 +29673,7 @@ __metadata: languageName: node linkType: hard -"es-shim-unscopables@npm:^1.0.2": +"es-shim-unscopables@npm:^1.0.2, es-shim-unscopables@npm:^1.1.0": version: 1.1.0 resolution: "es-shim-unscopables@npm:1.1.0" dependencies: @@ -29422,200 +29746,20 @@ __metadata: linkType: hard "esbuild-loader@npm:^4.0.0": - version: 4.2.2 - resolution: "esbuild-loader@npm:4.2.2" + version: 4.4.0 + resolution: "esbuild-loader@npm:4.4.0" dependencies: - esbuild: "npm:^0.21.0" - get-tsconfig: "npm:^4.7.0" + esbuild: "npm:^0.25.0" + get-tsconfig: "npm:^4.10.1" loader-utils: "npm:^2.0.4" webpack-sources: "npm:^1.4.3" peerDependencies: webpack: ^4.40.0 || ^5.0.0 - checksum: 10/235d06c60e26827333c3c66df6e2f13fef31e1b84b8310ba36ebdb6aaa31abdf7628a940326e4923824cdb501c8ce6a6e9129c4e465daaeab112f0b5db3423f4 + checksum: 10/ec1ba490af711b63ff0b5d157aed9c28cfd1ddc3d570996376e86b296558def07e50219b4727dd4674566a18d8df4c75d468cc0188f922688fa5bb1d7c8621ce languageName: node linkType: hard -"esbuild-register@npm:^3.5.0": - version: 3.6.0 - resolution: "esbuild-register@npm:3.6.0" - dependencies: - debug: "npm:^4.3.4" - peerDependencies: - esbuild: ">=0.12 <1" - checksum: 10/4ae1a016e3dad5b53c3d68cf07e31d8c1cec1a0b584038ece726097ac80bd33ab48fb224c766c9b341c04793837e652461eaca9327a116e7564f553b61ccca71 - languageName: node - linkType: hard - -"esbuild@npm:^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0, esbuild@npm:^0.25.0": - version: 0.25.8 - resolution: "esbuild@npm:0.25.8" - dependencies: - "@esbuild/aix-ppc64": "npm:0.25.8" - "@esbuild/android-arm": "npm:0.25.8" - "@esbuild/android-arm64": "npm:0.25.8" - "@esbuild/android-x64": "npm:0.25.8" - "@esbuild/darwin-arm64": "npm:0.25.8" - "@esbuild/darwin-x64": "npm:0.25.8" - "@esbuild/freebsd-arm64": "npm:0.25.8" - "@esbuild/freebsd-x64": "npm:0.25.8" - "@esbuild/linux-arm": "npm:0.25.8" - "@esbuild/linux-arm64": "npm:0.25.8" - "@esbuild/linux-ia32": "npm:0.25.8" - "@esbuild/linux-loong64": "npm:0.25.8" - "@esbuild/linux-mips64el": "npm:0.25.8" - "@esbuild/linux-ppc64": "npm:0.25.8" - "@esbuild/linux-riscv64": "npm:0.25.8" - "@esbuild/linux-s390x": "npm:0.25.8" - "@esbuild/linux-x64": "npm:0.25.8" - "@esbuild/netbsd-arm64": "npm:0.25.8" - "@esbuild/netbsd-x64": "npm:0.25.8" - "@esbuild/openbsd-arm64": "npm:0.25.8" - "@esbuild/openbsd-x64": "npm:0.25.8" - "@esbuild/openharmony-arm64": "npm:0.25.8" - "@esbuild/sunos-x64": "npm:0.25.8" - "@esbuild/win32-arm64": "npm:0.25.8" - "@esbuild/win32-ia32": "npm:0.25.8" - "@esbuild/win32-x64": "npm:0.25.8" - 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-arm64": - optional: true - "@esbuild/netbsd-x64": - optional: true - "@esbuild/openbsd-arm64": - optional: true - "@esbuild/openbsd-x64": - optional: true - "@esbuild/openharmony-arm64": - 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: 10/9897411732768e652d90fa5dfadae965e8f420d24e5f23fa0604331a1441769e2c7ee4e41ca53e926f1fb51a53af52e01fc9070fdc1a4edf3e9ec9208ee41273 - languageName: node - linkType: hard - -"esbuild@npm:^0.21.0": - version: 0.21.5 - resolution: "esbuild@npm:0.21.5" - dependencies: - "@esbuild/aix-ppc64": "npm:0.21.5" - "@esbuild/android-arm": "npm:0.21.5" - "@esbuild/android-arm64": "npm:0.21.5" - "@esbuild/android-x64": "npm:0.21.5" - "@esbuild/darwin-arm64": "npm:0.21.5" - "@esbuild/darwin-x64": "npm:0.21.5" - "@esbuild/freebsd-arm64": "npm:0.21.5" - "@esbuild/freebsd-x64": "npm:0.21.5" - "@esbuild/linux-arm": "npm:0.21.5" - "@esbuild/linux-arm64": "npm:0.21.5" - "@esbuild/linux-ia32": "npm:0.21.5" - "@esbuild/linux-loong64": "npm:0.21.5" - "@esbuild/linux-mips64el": "npm:0.21.5" - "@esbuild/linux-ppc64": "npm:0.21.5" - "@esbuild/linux-riscv64": "npm:0.21.5" - "@esbuild/linux-s390x": "npm:0.21.5" - "@esbuild/linux-x64": "npm:0.21.5" - "@esbuild/netbsd-x64": "npm:0.21.5" - "@esbuild/openbsd-x64": "npm:0.21.5" - "@esbuild/sunos-x64": "npm:0.21.5" - "@esbuild/win32-arm64": "npm:0.21.5" - "@esbuild/win32-ia32": "npm:0.21.5" - "@esbuild/win32-x64": "npm: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: 10/d2ff2ca84d30cce8e871517374d6c2290835380dc7cd413b2d49189ed170d45e407be14de2cb4794cf76f75cf89955c4714726ebd3de7444b3046f5cab23ab6b - languageName: node - linkType: hard - -"esbuild@npm:^0.27.0": +"esbuild@npm:^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0 || ^0.26.0 || ^0.27.0, esbuild@npm:^0.27.0": version: 0.27.1 resolution: "esbuild@npm:0.27.1" dependencies: @@ -29704,6 +29848,95 @@ __metadata: languageName: node linkType: hard +"esbuild@npm:^0.25.0": + version: 0.25.8 + resolution: "esbuild@npm:0.25.8" + dependencies: + "@esbuild/aix-ppc64": "npm:0.25.8" + "@esbuild/android-arm": "npm:0.25.8" + "@esbuild/android-arm64": "npm:0.25.8" + "@esbuild/android-x64": "npm:0.25.8" + "@esbuild/darwin-arm64": "npm:0.25.8" + "@esbuild/darwin-x64": "npm:0.25.8" + "@esbuild/freebsd-arm64": "npm:0.25.8" + "@esbuild/freebsd-x64": "npm:0.25.8" + "@esbuild/linux-arm": "npm:0.25.8" + "@esbuild/linux-arm64": "npm:0.25.8" + "@esbuild/linux-ia32": "npm:0.25.8" + "@esbuild/linux-loong64": "npm:0.25.8" + "@esbuild/linux-mips64el": "npm:0.25.8" + "@esbuild/linux-ppc64": "npm:0.25.8" + "@esbuild/linux-riscv64": "npm:0.25.8" + "@esbuild/linux-s390x": "npm:0.25.8" + "@esbuild/linux-x64": "npm:0.25.8" + "@esbuild/netbsd-arm64": "npm:0.25.8" + "@esbuild/netbsd-x64": "npm:0.25.8" + "@esbuild/openbsd-arm64": "npm:0.25.8" + "@esbuild/openbsd-x64": "npm:0.25.8" + "@esbuild/openharmony-arm64": "npm:0.25.8" + "@esbuild/sunos-x64": "npm:0.25.8" + "@esbuild/win32-arm64": "npm:0.25.8" + "@esbuild/win32-ia32": "npm:0.25.8" + "@esbuild/win32-x64": "npm:0.25.8" + 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-arm64": + optional: true + "@esbuild/netbsd-x64": + optional: true + "@esbuild/openbsd-arm64": + optional: true + "@esbuild/openbsd-x64": + optional: true + "@esbuild/openharmony-arm64": + 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: 10/9897411732768e652d90fa5dfadae965e8f420d24e5f23fa0604331a1441769e2c7ee4e41ca53e926f1fb51a53af52e01fc9070fdc1a4edf3e9ec9208ee41273 + languageName: node + linkType: hard + "esbuild@npm:esbuild-wasm@^0.23.0": version: 0.23.1 resolution: "esbuild-wasm@npm:0.23.1" @@ -29781,7 +30014,7 @@ __metadata: languageName: node linkType: hard -"escodegen@npm:^2.0.0, escodegen@npm:^2.1.0": +"escodegen@npm:^2.1.0": version: 2.1.0 resolution: "escodegen@npm:2.1.0" dependencies: @@ -29834,15 +30067,15 @@ __metadata: languageName: node linkType: hard -"eslint-module-utils@npm:^2.12.0": - version: 2.12.0 - resolution: "eslint-module-utils@npm:2.12.0" +"eslint-module-utils@npm:^2.12.1": + version: 2.12.1 + resolution: "eslint-module-utils@npm:2.12.1" dependencies: debug: "npm:^3.2.7" peerDependenciesMeta: eslint: optional: true - checksum: 10/dd27791147eca17366afcb83f47d6825b6ce164abb256681e5de4ec1d7e87d8605641eb869298a0dbc70665e2446dbcc2f40d3e1631a9475dd64dd23d4ca5dee + checksum: 10/bd25d6610ec3abaa50e8f1beb0119541562bbb8dd02c035c7e887976fe1e0c5dd8175f4607ca8d86d1146df24d52a071bd3d1dd329f6902bd58df805a8ca16d3 languageName: node linkType: hard @@ -29861,37 +30094,37 @@ __metadata: linkType: hard "eslint-plugin-import@npm:^2.31.0": - version: 2.31.0 - resolution: "eslint-plugin-import@npm:2.31.0" + version: 2.32.0 + resolution: "eslint-plugin-import@npm:2.32.0" dependencies: "@rtsao/scc": "npm:^1.1.0" - array-includes: "npm:^3.1.8" - array.prototype.findlastindex: "npm:^1.2.5" - array.prototype.flat: "npm:^1.3.2" - array.prototype.flatmap: "npm:^1.3.2" + array-includes: "npm:^3.1.9" + array.prototype.findlastindex: "npm:^1.2.6" + array.prototype.flat: "npm:^1.3.3" + array.prototype.flatmap: "npm:^1.3.3" debug: "npm:^3.2.7" doctrine: "npm:^2.1.0" eslint-import-resolver-node: "npm:^0.3.9" - eslint-module-utils: "npm:^2.12.0" + eslint-module-utils: "npm:^2.12.1" hasown: "npm:^2.0.2" - is-core-module: "npm:^2.15.1" + is-core-module: "npm:^2.16.1" is-glob: "npm:^4.0.3" minimatch: "npm:^3.1.2" object.fromentries: "npm:^2.0.8" object.groupby: "npm:^1.0.3" - object.values: "npm:^1.2.0" + object.values: "npm:^1.2.1" semver: "npm:^6.3.1" - string.prototype.trimend: "npm:^1.0.8" + string.prototype.trimend: "npm:^1.0.9" tsconfig-paths: "npm:^3.15.0" peerDependencies: eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9 - checksum: 10/6b76bd009ac2db0615d9019699d18e2a51a86cb8c1d0855a35fb1b418be23b40239e6debdc6e8c92c59f1468ed0ea8d7b85c817117a113d5cc225be8a02ad31c + checksum: 10/1bacf4967e9ebf99e12176a795f0d6d3a87d1c9a030c2207f27b267e10d96a1220be2647504c7fc13ab543cdf13ffef4b8f5620e0447032dba4ff0d3922f7c9e languageName: node linkType: hard "eslint-plugin-jest@npm:^28.9.0": - version: 28.9.0 - resolution: "eslint-plugin-jest@npm:28.9.0" + version: 28.14.0 + resolution: "eslint-plugin-jest@npm:28.14.0" dependencies: "@typescript-eslint/utils": "npm:^6.0.0 || ^7.0.0 || ^8.0.0" peerDependencies: @@ -29903,7 +30136,7 @@ __metadata: optional: true jest: optional: true - checksum: 10/399dd882205da996c2d46b768b744093346ffe4f730972825c72a3f85cc2e26bc08ccd73a7b487f8da4c39fa0178c58b571d5d611a22ced5518b5dfccb48d906 + checksum: 10/6032497bd97d6dd010450d5fdf535b8613a2789f4f83764ae04361c48d06d92f3d9b2e4350914b8fd857b6e611ba2b5282a1133ab8ec51b3e7053f9d336058e6 languageName: node linkType: hard @@ -29982,15 +30215,15 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-storybook@npm:^9.1.7": - version: 9.1.7 - resolution: "eslint-plugin-storybook@npm:9.1.7" +"eslint-plugin-storybook@npm:^10.1.9": + version: 10.1.9 + resolution: "eslint-plugin-storybook@npm:10.1.9" dependencies: "@typescript-eslint/utils": "npm:^8.8.1" peerDependencies: eslint: ">=8" - storybook: ^9.1.7 - checksum: 10/9e8d82bf504bc40cac67ce62dd9213cb672240a1c4184a702eb7c027290cd3604239fd3663a1c985b2569f4e9cab1cd1cf57dcb7d3b3dba119d8d42dfb509925 + storybook: ^10.1.9 + checksum: 10/65ea272cf450373d8b1f718f6c1ab878309f88b7cb2b27071b941d2b9d3402b0a102c1a83565c3bec64a9bc4a99ccbc8c25860fdf3112fed4dbfbe56361b0213 languageName: node linkType: hard @@ -30006,30 +30239,31 @@ __metadata: linkType: hard "eslint-plugin-unused-imports@npm:^4.1.4": - version: 4.1.4 - resolution: "eslint-plugin-unused-imports@npm:4.1.4" + version: 4.3.0 + resolution: "eslint-plugin-unused-imports@npm:4.3.0" peerDependencies: "@typescript-eslint/eslint-plugin": ^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0 eslint: ^9.0.0 || ^8.0.0 peerDependenciesMeta: "@typescript-eslint/eslint-plugin": optional: true - checksum: 10/8e987028ad925ce1e04c01dcae70adbf44c2878a8b15c4327b33a2861e471d7fe00f6fe213fbd2b936f3fcefc8ccabb0d778aa1d6e0e0387a3dc7fe150cd4ed4 + checksum: 10/64ec1f686d90f18a27c27273a0338bad6964a611f497b81c5e7eace9d9a4f38d96070d7c389c2626095a9e5e7dbcafccc6444fa2933c9a7649996a7ca875738f languageName: node linkType: hard "eslint-rspack-plugin@npm:^4.2.1": - version: 4.2.1 - resolution: "eslint-rspack-plugin@npm:4.2.1" + version: 4.3.0 + resolution: "eslint-rspack-plugin@npm:4.3.0" dependencies: "@types/eslint": "npm:^8.56.10" jest-worker: "npm:^29.7.0" micromatch: "npm:^4.0.8" normalize-path: "npm:^3.0.0" schema-utils: "npm:^4.2.0" + tinyglobby: "npm:^0.2.15" peerDependencies: eslint: ^8.0.0 || ^9.0.0 - checksum: 10/c45639e660d13af63c58f8f80103a033f607b9d635d9315d7d859408134cc35e2e3f981805f7abdd6061ec9d8207cfc7c0d5a097df9ac8c7ccd707ca5aa14583 + checksum: 10/e312c993474cd4df180f6790359936b581391ac660769ce94b7e00e96322aedbbebc8d9132969db72b04d4588ccf40dd17c45d8f5d48df625a015a819c215ae3 languageName: node linkType: hard @@ -30060,7 +30294,7 @@ __metadata: languageName: node linkType: hard -"eslint-visitor-keys@npm:^4.2.0, eslint-visitor-keys@npm:^4.2.1": +"eslint-visitor-keys@npm:^4.2.1": version: 4.2.1 resolution: "eslint-visitor-keys@npm:4.2.1" checksum: 10/3ee00fc6a7002d4b0ffd9dc99e13a6a7882c557329e6c25ab254220d71e5c9c4f89dca4695352949ea678eb1f3ba912a18ef8aac0a7fe094196fd92f441bfce2 @@ -30313,14 +30547,14 @@ __metadata: languageName: node linkType: hard -"eventsource-parser@npm:^3.0.1": - version: 3.0.1 - resolution: "eventsource-parser@npm:3.0.1" - checksum: 10/2730c54c3cb47d55d2967f2ece843f9fc95d8a11c2fef6fece8d17d9080193cbe3cd9ac7b04a325977f63cbf8c1664fdd0512dec1aec601666a5c5bd8564b61f +"eventsource-parser@npm:^3.0.0, eventsource-parser@npm:^3.0.1": + version: 3.0.6 + resolution: "eventsource-parser@npm:3.0.6" + checksum: 10/febf7058b9c2168ecbb33e92711a1646e06bd1568f60b6eb6a01a8bf9f8fcd29cc8320d57247059cacf657a296280159f21306d2e3ff33309a9552b2ef889387 languageName: node linkType: hard -"eventsource@npm:^3.0.2, eventsource@npm:^3.0.6": +"eventsource@npm:^3.0.2": version: 3.0.7 resolution: "eventsource@npm:3.0.7" dependencies: @@ -30329,6 +30563,15 @@ __metadata: languageName: node linkType: hard +"eventsource@npm:^4.0.0": + version: 4.1.0 + resolution: "eventsource@npm:4.1.0" + dependencies: + eventsource-parser: "npm:^3.0.1" + checksum: 10/d23b1c2a56a1dd7344a151ca57d70ebc624972150395c1c82110bda1d2918487260e8ec76c1c79677406184ecb1847509a675d4ee5367925ef77f03c9cae594d + languageName: node + linkType: hard + "evp_bytestokey@npm:^1.0.0, evp_bytestokey@npm:^1.0.3": version: 1.0.3 resolution: "evp_bytestokey@npm:1.0.3" @@ -30547,7 +30790,7 @@ __metadata: languageName: node linkType: hard -"execa@npm:^5.0.0": +"execa@npm:^5.0.0, execa@npm:^5.1.1": version: 5.1.1 resolution: "execa@npm:5.1.1" dependencies: @@ -30595,10 +30838,10 @@ __metadata: languageName: node linkType: hard -"exit@npm:^0.1.2": - version: 0.1.2 - resolution: "exit@npm:0.1.2" - checksum: 10/387555050c5b3c10e7a9e8df5f43194e95d7737c74532c409910e585d5554eaff34960c166643f5e23d042196529daad059c292dcf1fb61b8ca878d3677f4b87 +"exit-x@npm:^0.2.2": + version: 0.2.2 + resolution: "exit-x@npm:0.2.2" + checksum: 10/ee043053e6c1e237adf5ad9c4faf9f085b606f64a4ff859e2b138fab63fe642711d00c9af452a9134c4c92c55f752e818bfabab78c24d345022db163f3137027 languageName: node linkType: hard @@ -30618,16 +30861,17 @@ __metadata: languageName: node linkType: hard -"expect@npm:>28.1.3, expect@npm:^29.0.0, expect@npm:^29.7.0": - version: 29.7.0 - resolution: "expect@npm:29.7.0" +"expect@npm:30.2.0, expect@npm:>28.1.3, expect@npm:^30.0.0": + version: 30.2.0 + resolution: "expect@npm:30.2.0" dependencies: - "@jest/expect-utils": "npm:^29.7.0" - jest-get-type: "npm:^29.6.3" - jest-matcher-utils: "npm:^29.7.0" - jest-message-util: "npm:^29.7.0" - jest-util: "npm:^29.7.0" - checksum: 10/63f97bc51f56a491950fb525f9ad94f1916e8a014947f8d8445d3847a665b5471b768522d659f5e865db20b6c2033d2ac10f35fcbd881a4d26407a4f6f18451a + "@jest/expect-utils": "npm:30.2.0" + "@jest/get-type": "npm:30.1.0" + jest-matcher-utils: "npm:30.2.0" + jest-message-util: "npm:30.2.0" + jest-mock: "npm:30.2.0" + jest-util: "npm:30.2.0" + checksum: 10/cf98ab45ab2e9f2fb9943a3ae0097f72d63a94be179a19fd2818d8fdc3b7681d31cc8ef540606eb8dd967d9c44d73fef263a614e9de260c22943ffb122ad66fd languageName: node linkType: hard @@ -30639,11 +30883,11 @@ __metadata: linkType: hard "express-openapi-validator@npm:^5.5.8": - version: 5.5.8 - resolution: "express-openapi-validator@npm:5.5.8" + version: 5.6.0 + resolution: "express-openapi-validator@npm:5.6.0" dependencies: "@apidevtools/json-schema-ref-parser": "npm:^14.0.3" - "@types/multer": "npm:^1.4.12" + "@types/multer": "npm:^1.4.13" ajv: "npm:^8.17.1" ajv-draft-04: "npm:^1.0.0" ajv-formats: "npm:^3.0.1" @@ -30658,7 +30902,7 @@ __metadata: qs: "npm:^6.14.0" peerDependencies: express: "*" - checksum: 10/0396d4fd253fcd61725b632adcd805ac4ced940c34907775bedce39701d3b884e7a60357fa29c59d282407381c1fdcecceae6d0011684103e7ffe104038cb661 + checksum: 10/03b5d26f16d9b1cc4742b9bd87570c6429fabb856b385658c0f0b323d53d241969c1572bda068ba59e694e45ded094d085674f860665aacf0a6a820f0317cef4 languageName: node linkType: hard @@ -30801,17 +31045,6 @@ __metadata: languageName: node linkType: hard -"external-editor@npm:^3.0.3, external-editor@npm:^3.1.0": - version: 3.1.0 - resolution: "external-editor@npm:3.1.0" - dependencies: - chardet: "npm:^0.7.0" - iconv-lite: "npm:^0.4.24" - tmp: "npm:^0.0.33" - checksum: 10/776dff1d64a1d28f77ff93e9e75421a81c062983fd1544279d0a32f563c0b18c52abbb211f31262e2827e48edef5c9dc8f960d06dd2d42d1654443b88568056b - languageName: node - linkType: hard - "extract-files@npm:^11.0.0": version: 11.0.0 resolution: "extract-files@npm:11.0.0" @@ -30977,7 +31210,7 @@ __metadata: languageName: node linkType: hard -"fastq@npm:^1.15.0, fastq@npm:^1.6.0": +"fastq@npm:^1.6.0": version: 1.18.0 resolution: "fastq@npm:1.18.0" dependencies: @@ -31004,12 +31237,12 @@ __metadata: languageName: node linkType: hard -"fb-watchman@npm:^2.0.0": - version: 2.0.1 - resolution: "fb-watchman@npm:2.0.1" +"fb-watchman@npm:^2.0.2": + version: 2.0.2 + resolution: "fb-watchman@npm:2.0.2" dependencies: bser: "npm:2.1.1" - checksum: 10/9a03efc7d41ce3ca3d799d63505a1f7312caddf4e7737d39f2165bfe4872cbd4b87eccc9e6c57229ea08f14b4d7187896da31a7270b8da7a4aaa8fba2d3d1c42 + checksum: 10/4f95d336fb805786759e383fd7fff342ceb7680f53efcc0ef82f502eb479ce35b98e8b207b6dfdfeea0eba845862107dc73813775fc6b56b3098c6e90a2dad77 languageName: node linkType: hard @@ -31044,6 +31277,15 @@ __metadata: languageName: node linkType: hard +"fd-package-json@npm:^2.0.0": + version: 2.0.0 + resolution: "fd-package-json@npm:2.0.0" + dependencies: + walk-up-path: "npm:^4.0.0" + checksum: 10/e595a1a23f8e208815cdcf26c92218240da00acce80468324408dc4a5cb6c26b6efb5076f0458a02f044562a1e60253731187a627d5416b4961468ddfc0ae426 + languageName: node + linkType: hard + "fdir@npm:^6.5.0": version: 6.5.0 resolution: "fdir@npm:6.5.0" @@ -31098,15 +31340,15 @@ __metadata: languageName: node linkType: hard -"file-type@npm:21.0.0": - version: 21.0.0 - resolution: "file-type@npm:21.0.0" +"file-type@npm:21.1.0": + version: 21.1.0 + resolution: "file-type@npm:21.1.0" dependencies: - "@tokenizer/inflate": "npm:^0.2.7" - strtok3: "npm:^10.2.2" + "@tokenizer/inflate": "npm:^0.3.1" + strtok3: "npm:^10.3.1" token-types: "npm:^6.0.0" uint8array-extras: "npm:^1.4.0" - checksum: 10/6980e8b0ef870a98b51ab2eac5db94a1884de8476fe49dc02d2f7e0c1d1d7d44d42b6c59e67867ae90f321ddf4edd00fcfda01821591e2fa05385d0e438a9dc1 + checksum: 10/951d1e224c643e961c2b51fce236526b9a4789ea59fee53da3bdf5d29de8cc58ffa4b4601f83739fd0df22324108eb4b55f2b7cefbe93489e554a9e5de95ce3f languageName: node linkType: hard @@ -31326,17 +31568,6 @@ __metadata: languageName: node linkType: hard -"find-up@npm:^7.0.0": - version: 7.0.0 - resolution: "find-up@npm:7.0.0" - dependencies: - locate-path: "npm:^7.2.0" - path-exists: "npm:^5.0.0" - unicorn-magic: "npm:^0.1.0" - checksum: 10/7e6b08fbc05a10677e25e74bb0a020054a86b31d1806c5e6a9e32e75472bbf177210bc16e5f97453be8bda7ae2e3d97669dbb2901f8c30b39ce53929cbea6746 - languageName: node - linkType: hard - "find-yarn-workspace-root2@npm:1.2.16": version: 1.2.16 resolution: "find-yarn-workspace-root2@npm:1.2.16" @@ -31450,8 +31681,8 @@ __metadata: linkType: hard "fork-ts-checker-webpack-plugin@npm:^6.5.0": - version: 6.5.0 - resolution: "fork-ts-checker-webpack-plugin@npm:6.5.0" + version: 6.5.3 + resolution: "fork-ts-checker-webpack-plugin@npm:6.5.3" dependencies: "@babel/code-frame": "npm:^7.8.3" "@types/json-schema": "npm:^7.0.5" @@ -31476,17 +31707,17 @@ __metadata: optional: true vue-template-compiler: optional: true - checksum: 10/165af8617ff639781d0da76de9899bfcfdf9db4758d8f1dde435aa81efcf963ff776bb5b16f2f371d919faaba7d1037e046ec985d2b2bae4031c2c10eae9b6c9 + checksum: 10/415263839afe11c291be60e3335ece3ccdc80c5e0d91eeecf0d3060cfb72c7b0cb33be326dd24b325939357d53215e10c41e8187edb5db8a08fe9aaa8aa6c510 languageName: node linkType: hard "fork-ts-checker-webpack-plugin@npm:^9.0.0": - version: 9.0.2 - resolution: "fork-ts-checker-webpack-plugin@npm:9.0.2" + version: 9.1.0 + resolution: "fork-ts-checker-webpack-plugin@npm:9.1.0" dependencies: "@babel/code-frame": "npm:^7.16.7" chalk: "npm:^4.1.2" - chokidar: "npm:^3.5.3" + chokidar: "npm:^4.0.1" cosmiconfig: "npm:^8.2.0" deepmerge: "npm:^4.2.2" fs-extra: "npm:^10.0.0" @@ -31499,7 +31730,7 @@ __metadata: peerDependencies: typescript: ">3.6.0" webpack: ^5.11.0 - checksum: 10/3399ea114d9397da5e51baaa1cf2ca704f4616c8255df672889cafc2a823f77e8bf9913133852d29d676657b1d40e4a2fba8eb9fafee09e00faeda924289220e + checksum: 10/1d24387224f7d49a17f7e44c9150971172f34ae30c4b1f581b8af967e73e8f36a434ed56f78aa45fd8cf0833c73a1b020102cc61070d7dc630b70c21c9770a1b languageName: node linkType: hard @@ -31551,6 +31782,17 @@ __metadata: languageName: node linkType: hard +"formatly@npm:^0.3.0": + version: 0.3.0 + resolution: "formatly@npm:0.3.0" + dependencies: + fd-package-json: "npm:^2.0.0" + bin: + formatly: bin/index.mjs + checksum: 10/0e5a9cbb826d93171b00c283e20e6a564a16e7bc3839e695790347a1f23e3536a88d613f5cabd07403d60b7bdffe179987c88b1fc2900a9be49eea01ffbe4244 + languageName: node + linkType: hard + "formdata-node@npm:^4.3.2, formdata-node@npm:^4.3.3": version: 4.4.1 resolution: "formdata-node@npm:4.4.1" @@ -31570,7 +31812,7 @@ __metadata: languageName: node linkType: hard -"formidable@npm:^3.5.1": +"formidable@npm:^3.5.4": version: 3.5.4 resolution: "formidable@npm:3.5.4" dependencies: @@ -31668,14 +31910,14 @@ __metadata: languageName: node linkType: hard -"fs-extra@npm:11.3.0": - version: 11.3.0 - resolution: "fs-extra@npm:11.3.0" +"fs-extra@npm:11.3.2, fs-extra@npm:^11.0.0, fs-extra@npm:^11.1.0, fs-extra@npm:^11.2.0, fs-extra@npm:~11.3.0": + version: 11.3.2 + resolution: "fs-extra@npm:11.3.2" dependencies: graceful-fs: "npm:^4.2.0" jsonfile: "npm:^6.0.1" universalify: "npm:^2.0.0" - checksum: 10/c9fe7b23dded1efe7bbae528d685c3206477e20cc60e9aaceb3f024f9b9ff2ee1f62413c161cb88546cc564009ab516dec99e9781ba782d869bb37e4fe04a97f + checksum: 10/d559545c73fda69c75aa786f345c2f738b623b42aea850200b1582e006a35278f63787179e3194ba19413c26a280441758952b0c7e88dd96762d497e365a6c3e languageName: node linkType: hard @@ -31702,17 +31944,6 @@ __metadata: languageName: node linkType: hard -"fs-extra@npm:^11.0.0, fs-extra@npm:^11.1.0, fs-extra@npm:^11.2.0, fs-extra@npm:~11.3.0": - version: 11.3.2 - resolution: "fs-extra@npm:11.3.2" - dependencies: - graceful-fs: "npm:^4.2.0" - jsonfile: "npm:^6.0.1" - universalify: "npm:^2.0.0" - checksum: 10/d559545c73fda69c75aa786f345c2f738b623b42aea850200b1582e006a35278f63787179e3194ba19413c26a280441758952b0c7e88dd96762d497e365a6c3e - languageName: node - linkType: hard - "fs-extra@npm:^7.0.1": version: 7.0.1 resolution: "fs-extra@npm:7.0.1" @@ -31784,7 +32015,7 @@ __metadata: languageName: node linkType: hard -"fsevents@npm:^2.3.2, fsevents@npm:~2.3.2, fsevents@npm:~2.3.3": +"fsevents@npm:^2.3.3, fsevents@npm:~2.3.2, fsevents@npm:~2.3.3": version: 2.3.3 resolution: "fsevents@npm:2.3.3" dependencies: @@ -31803,7 +32034,7 @@ __metadata: languageName: node linkType: hard -"fsevents@patch:fsevents@npm%3A^2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.3#optional!builtin": +"fsevents@patch:fsevents@npm%3A^2.3.3#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.3#optional!builtin": version: 2.3.3 resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" dependencies: @@ -31894,7 +32125,7 @@ __metadata: languageName: node linkType: hard -"gaxios@npm:^7.0.0, gaxios@npm:^7.0.0-rc.4": +"gaxios@npm:^7.0.0, gaxios@npm:^7.0.0-rc.4, gaxios@npm:^7.1.3": version: 7.1.3 resolution: "gaxios@npm:7.1.3" dependencies: @@ -31936,6 +32167,13 @@ __metadata: languageName: node linkType: hard +"generator-function@npm:^2.0.0": + version: 2.0.1 + resolution: "generator-function@npm:2.0.1" + checksum: 10/eb7e7eb896c5433f3d40982b2ccacdb3dd990dd3499f14040e002b5d54572476513be8a2e6f9609f6e41ab29f2c4469307611ddbfc37ff4e46b765c326663805 + languageName: node + linkType: hard + "generic-names@npm:^2.0.1": version: 2.0.1 resolution: "generic-names@npm:2.0.1" @@ -31983,7 +32221,7 @@ __metadata: languageName: node linkType: hard -"get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2, get-intrinsic@npm:^1.2.4, get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6, get-intrinsic@npm:^1.3.0": +"get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.4, get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6, get-intrinsic@npm:^1.3.0": version: 1.3.0 resolution: "get-intrinsic@npm:1.3.0" dependencies: @@ -32001,6 +32239,27 @@ __metadata: languageName: node linkType: hard +"get-intrinsic@npm:^1.2.2": + version: 1.3.1 + resolution: "get-intrinsic@npm:1.3.1" + dependencies: + async-function: "npm:^1.0.0" + async-generator-function: "npm:^1.0.0" + call-bind-apply-helpers: "npm:^1.0.2" + es-define-property: "npm:^1.0.1" + es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.1.1" + function-bind: "npm:^1.1.2" + generator-function: "npm:^2.0.0" + get-proto: "npm:^1.0.1" + gopd: "npm:^1.2.0" + has-symbols: "npm:^1.1.0" + hasown: "npm:^2.0.2" + math-intrinsics: "npm:^1.1.0" + checksum: 10/bb579dda84caa4a3a41611bdd483dade7f00f246f2a7992eb143c5861155290df3fdb48a8406efa3dfb0b434e2c8fafa4eebd469e409d0439247f85fc3fa2cc1 + languageName: node + linkType: hard + "get-nonce@npm:^1.0.0": version: 1.0.1 resolution: "get-nonce@npm:1.0.1" @@ -32106,12 +32365,12 @@ __metadata: languageName: node linkType: hard -"get-tsconfig@npm:^4.7.0, get-tsconfig@npm:^4.7.2": - version: 4.7.3 - resolution: "get-tsconfig@npm:4.7.3" +"get-tsconfig@npm:^4.10.0, get-tsconfig@npm:^4.10.1": + version: 4.13.0 + resolution: "get-tsconfig@npm:4.13.0" dependencies: resolve-pkg-maps: "npm:^1.0.0" - checksum: 10/7397bb4f8aef936df4d9016555b662dcf5279f3c46428b7c7c1ff5e94ab2b87d018b3dda0f4bc1a28b154d5affd0eac5d014511172c085fd8a9cdff9ea7fe043 + checksum: 10/3603c6da30e312636e4c20461e779114c9126601d1eca70ee4e36e3e3c00e3c21892d2d920027333afa2cc9e20998a436b14abe03a53cde40742581cb0e9ceb2 languageName: node linkType: hard @@ -32219,25 +32478,20 @@ __metadata: languageName: node linkType: hard -"glob@npm:11.0.3": - version: 11.0.3 - resolution: "glob@npm:11.0.3" +"glob@npm:13.0.0": + version: 13.0.0 + resolution: "glob@npm:13.0.0" dependencies: - foreground-child: "npm:^3.3.1" - jackspeak: "npm:^4.1.1" - minimatch: "npm:^10.0.3" + minimatch: "npm:^10.1.1" minipass: "npm:^7.1.2" - package-json-from-dist: "npm:^1.0.0" path-scurry: "npm:^2.0.0" - bin: - glob: dist/esm/bin.mjs - checksum: 10/2ae536c1360c0266b523b2bfa6aadc10144a8b7e08869b088e37ac3c27cd30774f82e4bfb291cde796776e878f9e13200c7ff44010eb7054e00f46f649397893 + checksum: 10/de390721d29ee1c9ea41e40ec2aa0de2cabafa68022e237dc4297665a5e4d650776f2573191984ea1640aba1bf0ea34eddef2d8cbfbfc2ad24b5fb0af41d8846 languageName: node linkType: hard "glob@npm:^10.0.0, glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7, glob@npm:^10.4.1": - version: 10.4.5 - resolution: "glob@npm:10.4.5" + version: 10.5.0 + resolution: "glob@npm:10.5.0" dependencies: foreground-child: "npm:^3.1.0" jackspeak: "npm:^3.1.2" @@ -32247,11 +32501,11 @@ __metadata: path-scurry: "npm:^1.11.1" bin: glob: dist/esm/bin.mjs - checksum: 10/698dfe11828b7efd0514cd11e573eaed26b2dff611f0400907281ce3eab0c1e56143ef9b35adc7c77ecc71fba74717b510c7c223d34ca8a98ec81777b293d4ac + checksum: 10/ab3bccfefcc0afaedbd1f480cd0c4a2c0e322eb3f0aa7ceaa31b3f00b825069f17cf0f1fc8b6f256795074b903f37c0ade37ddda6a176aa57f1c2bbfe7240653 languageName: node linkType: hard -"glob@npm:^11.0.1": +"glob@npm:^11.0.1, glob@npm:^11.1.0": version: 11.1.0 resolution: "glob@npm:11.1.0" dependencies: @@ -32449,7 +32703,7 @@ __metadata: languageName: node linkType: hard -"google-auth-library@npm:^10.0.0, google-auth-library@npm:^10.0.0-rc.1": +"google-auth-library@npm:^10.0.0-rc.1, google-auth-library@npm:^10.5.0": version: 10.5.0 resolution: "google-auth-library@npm:10.5.0" dependencies: @@ -32688,16 +32942,16 @@ __metadata: linkType: hard "graphql@npm:^14.0.2 || ^15.5": - version: 15.9.0 - resolution: "graphql@npm:15.9.0" - checksum: 10/ce1f50672bcb369395d07a47048bcbb429ed1ce06dbcafb7a0999df791cb7aa7206be21497907973dbc8a01df3cd7f632f43c583f248538f186f5adfa1a0d1c5 + version: 15.10.1 + resolution: "graphql@npm:15.10.1" + checksum: 10/49177f52c1fbac022866d39bb15040122da4c3ccd12644233b20edfcb1f76aa92aa92f2a82af4668101d8f726112fda111cb11a12feb05635cd689443a7aafb8 languageName: node linkType: hard "graphql@npm:^16.0.0, graphql@npm:^16.8.1": - version: 16.10.0 - resolution: "graphql@npm:16.10.0" - checksum: 10/d42cf81ddcf3a61dfb213217576bf33c326f15b02c4cee369b373dc74100cbdcdc4479b3b797e79b654dabd8fddf50ef65ff75420e9ce5596c02e21f24c9126a + version: 16.12.0 + resolution: "graphql@npm:16.12.0" + checksum: 10/e299bc97cca178e549c8c1ed4cb164f631f07be987d3657f76cdf18c0250040cc0d456d4b6d41c87b855cac97b15a62ed345557527efcb0546492895a893bb87 languageName: node linkType: hard @@ -32914,6 +33168,15 @@ __metadata: languageName: node linkType: hard +"hast-util-parse-selector@npm:^4.0.0": + version: 4.0.0 + resolution: "hast-util-parse-selector@npm:4.0.0" + dependencies: + "@types/hast": "npm:^3.0.0" + checksum: 10/76087670d3b0b50b23a6cb70bca53a6176d6608307ccdbb3ed18b650b82e7c3513bfc40348f1389dc0c5ae872b9a768851f4335f44654abd7deafd6974c52402 + languageName: node + linkType: hard + "hast-util-whitespace@npm:^2.0.0": version: 2.0.0 resolution: "hast-util-whitespace@npm:2.0.0" @@ -32934,6 +33197,19 @@ __metadata: languageName: node linkType: hard +"hastscript@npm:^9.0.0": + version: 9.0.1 + resolution: "hastscript@npm:9.0.1" + dependencies: + "@types/hast": "npm:^3.0.0" + comma-separated-tokens: "npm:^2.0.0" + hast-util-parse-selector: "npm:^4.0.0" + property-information: "npm:^7.0.0" + space-separated-tokens: "npm:^2.0.0" + checksum: 10/9aa8135faf0307807cca4075bef4e3403ae1ce959ad4b9e6720892ba957d58ff98b2f60b5eb3ac67d88ae897dc918997299cd4249d7ac602a0066dd46442c5d4 + languageName: node + linkType: hard + "he@npm:1.2.0, he@npm:^1.2.0": version: 1.2.0 resolution: "he@npm:1.2.0" @@ -32965,9 +33241,9 @@ __metadata: linkType: hard "helmet@npm:^6.0.0": - version: 6.0.1 - resolution: "helmet@npm:6.0.1" - checksum: 10/0eec311e1a3820e206226563e55d7115fa66e9a34922229472c1dac407c5d00f0d5c4f5f7afed714fba40287aac1c30dcbfa9b3c096f1146f9d6a55c4527d65d + version: 6.2.0 + resolution: "helmet@npm:6.2.0" + checksum: 10/f112fcd0d8494e6c8ad10e9307e182f1be9c9c4917a3f9a3718c13ae120d4c4e1f251e735297d6a9266e068dcc0463ab101c8d7f2b809c0ceabcef4681f81a2a languageName: node linkType: hard @@ -33030,6 +33306,13 @@ __metadata: languageName: node linkType: hard +"hookified@npm:^1.10.0": + version: 1.12.2 + resolution: "hookified@npm:1.12.2" + checksum: 10/d445956d47ea8a3d30b29a9c1fe9945536577fa027d83c69eff9de4d47e22167fbe2b0721a8c4df6a0a2b53f0cc0b9eeda3a311ea9b4f20e09b2bb556105b035 + languageName: node + linkType: hard + "hoopy@npm:^0.1.4": version: 0.1.4 resolution: "hoopy@npm:0.1.4" @@ -33072,15 +33355,6 @@ __metadata: languageName: node linkType: hard -"html-encoding-sniffer@npm:^3.0.0": - version: 3.0.0 - resolution: "html-encoding-sniffer@npm:3.0.0" - dependencies: - whatwg-encoding: "npm:^2.0.0" - checksum: 10/707a812ec2acaf8bb5614c8618dc81e2fb6b4399d03e95ff18b65679989a072f4e919b9bef472039301a1bbfba64063ba4c79ea6e851c653ac9db80dbefe8fe5 - languageName: node - linkType: hard - "html-encoding-sniffer@npm:^4.0.0": version: 4.0.0 resolution: "html-encoding-sniffer@npm:4.0.0" @@ -33122,8 +33396,8 @@ __metadata: linkType: hard "html-webpack-plugin@npm:^5.6.3": - version: 5.6.3 - resolution: "html-webpack-plugin@npm:5.6.3" + version: 5.6.5 + resolution: "html-webpack-plugin@npm:5.6.5" dependencies: "@types/html-minifier-terser": "npm:^6.0.0" html-minifier-terser: "npm:^6.0.2" @@ -33138,7 +33412,7 @@ __metadata: optional: true webpack: optional: true - checksum: 10/fd2bf1ac04823526c8b609555d027b38b9d61b4ba9f5c8116a37cc6b62d5b86cab1f478616e8c5344fee13663d2566f5c470c66265ecb1e9574dc38d0459889d + checksum: 10/89e84f6ede068242348b2c2f09da67bf39a6b22d14399eaf16e399be05a4e2bb1f3f1c71ec03b7193aed96ebe2cf61d45a70565408b271661f7ea8635b237701 languageName: node linkType: hard @@ -33411,9 +33685,9 @@ __metadata: linkType: hard "humanize-duration@npm:^3.25.1": - version: 3.32.2 - resolution: "humanize-duration@npm:3.32.2" - checksum: 10/2dfe847085c7586d2cc83613b8643a4cca70966a16522e3786be07f0283087502e5340e98a79867c7b019ea22ae85c3fa9d1ca1be587eb19ccf03710c986d41d + version: 3.33.2 + resolution: "humanize-duration@npm:3.33.2" + checksum: 10/ac6bc74b095d53e6ff320126d64c0998de213d0e38d0996f23389603c034c8f825915d4318fc19cfdb0612c4963d72d200da43cd7c28ac865bbf9a61f53418f4 languageName: node linkType: hard @@ -33467,15 +33741,6 @@ __metadata: languageName: node linkType: hard -"iconv-lite@npm:^0.4.24, iconv-lite@npm:~0.4.24": - version: 0.4.24 - resolution: "iconv-lite@npm:0.4.24" - dependencies: - safer-buffer: "npm:>= 2.1.2 < 3" - checksum: 10/6d3a2dac6e5d1fb126d25645c25c3a1209f70cceecc68b8ef51ae0da3cdc078c151fade7524a30b12a3094926336831fca09c666ef55b37e2c69638b5d6bd2e3 - languageName: node - linkType: hard - "iconv-lite@npm:^0.7.0": version: 0.7.0 resolution: "iconv-lite@npm:0.7.0" @@ -33485,6 +33750,15 @@ __metadata: languageName: node linkType: hard +"iconv-lite@npm:~0.4.24": + version: 0.4.24 + resolution: "iconv-lite@npm:0.4.24" + dependencies: + safer-buffer: "npm:>= 2.1.2 < 3" + checksum: 10/6d3a2dac6e5d1fb126d25645c25c3a1209f70cceecc68b8ef51ae0da3cdc078c151fade7524a30b12a3094926336831fca09c666ef55b37e2c69638b5d6bd2e3 + languageName: node + linkType: hard + "icss-replace-symbols@npm:^1.1.0": version: 1.1.0 resolution: "icss-replace-symbols@npm:1.1.0" @@ -33551,13 +33825,20 @@ __metadata: languageName: node linkType: hard -"ignore@npm:^5.1.4, ignore@npm:^5.1.8, ignore@npm:^5.2.0, ignore@npm:^5.2.4, ignore@npm:^5.3.1": +"ignore@npm:^5.1.4, ignore@npm:^5.2.0, ignore@npm:^5.2.4": version: 5.3.2 resolution: "ignore@npm:5.3.2" checksum: 10/cceb6a457000f8f6a50e1196429750d782afce5680dd878aa4221bd79972d68b3a55b4b1458fc682be978f4d3c6a249046aa0880637367216444ab7b014cfc98 languageName: node linkType: hard +"ignore@npm:^7.0.0": + version: 7.0.5 + resolution: "ignore@npm:7.0.5" + checksum: 10/f134b96a4de0af419196f52c529d5c6120c4456ff8a6b5a14ceaaa399f883e15d58d2ce651c9b69b9388491d4669dda47285d307e827de9304a53a1824801bc6 + languageName: node + linkType: hard + "immediate@npm:~3.0.5": version: 3.0.6 resolution: "immediate@npm:3.0.6" @@ -33633,15 +33914,15 @@ __metadata: languageName: node linkType: hard -"import-local@npm:^3.0.2": - version: 3.0.2 - resolution: "import-local@npm:3.0.2" +"import-local@npm:^3.2.0": + version: 3.2.0 + resolution: "import-local@npm:3.2.0" dependencies: pkg-dir: "npm:^4.2.0" resolve-cwd: "npm:^3.0.0" bin: import-local-fixture: fixtures/cli.js - checksum: 10/c74d9f9484c878cda1de3434613c7ff72d5dadcf20e5482542232d7c2575b713ff88701d6675fcf09a3684cb23fb407c8b333b9cbc59438712723d058d8e976c + checksum: 10/0b0b0b412b2521739fbb85eeed834a3c34de9bc67e670b3d0b86248fc460d990a7b116ad056c084b87a693ef73d1f17268d6a5be626bb43c998a8b1c8a230004 languageName: node linkType: hard @@ -33783,30 +34064,7 @@ __metadata: languageName: node linkType: hard -"inquirer@npm:8.2.6": - version: 8.2.6 - resolution: "inquirer@npm:8.2.6" - dependencies: - ansi-escapes: "npm:^4.2.1" - chalk: "npm:^4.1.1" - cli-cursor: "npm:^3.1.0" - cli-width: "npm:^3.0.0" - external-editor: "npm:^3.0.3" - figures: "npm:^3.0.0" - lodash: "npm:^4.17.21" - mute-stream: "npm:0.0.8" - ora: "npm:^5.4.1" - run-async: "npm:^2.4.0" - rxjs: "npm:^7.5.5" - string-width: "npm:^4.1.0" - strip-ansi: "npm:^6.0.0" - through: "npm:^2.3.6" - wrap-ansi: "npm:^6.0.1" - checksum: 10/f642b9e5a94faaba54f277bdda2af0e0a6b592bd7f88c60e1614b5795b19336c7025e0c2923915d5f494f600a02fe8517413779a794415bb79a9563b061d68ab - languageName: node - linkType: hard - -"inquirer@npm:^8.0.0, inquirer@npm:^8.2.0": +"inquirer@npm:8.2.7, inquirer@npm:^8.0.0, inquirer@npm:^8.2.0": version: 8.2.7 resolution: "inquirer@npm:8.2.7" dependencies: @@ -34011,13 +34269,6 @@ __metadata: languageName: node linkType: hard -"is-arrayish@npm:^0.3.1": - version: 0.3.2 - resolution: "is-arrayish@npm:0.3.2" - checksum: 10/81a78d518ebd8b834523e25d102684ee0f7e98637136d3bdc93fd09636350fa06f1d8ca997ea28143d4d13cb1b69c0824f082db0ac13e1ab3311c10ffea60ade - languageName: node - linkType: hard - "is-async-function@npm:^2.0.0": version: 2.0.0 resolution: "is-async-function@npm:2.0.0" @@ -34089,7 +34340,7 @@ __metadata: languageName: node linkType: hard -"is-core-module@npm:^2.13.0, is-core-module@npm:^2.15.1, is-core-module@npm:^2.16.0": +"is-core-module@npm:^2.13.0, is-core-module@npm:^2.16.0, is-core-module@npm:^2.16.1": version: 2.16.1 resolution: "is-core-module@npm:2.16.1" dependencies: @@ -34207,7 +34458,7 @@ __metadata: languageName: node linkType: hard -"is-generator-fn@npm:^2.0.0": +"is-generator-fn@npm:^2.1.0": version: 2.1.0 resolution: "is-generator-fn@npm:2.1.0" checksum: 10/a6ad5492cf9d1746f73b6744e0c43c0020510b59d56ddcb78a91cbc173f09b5e6beff53d75c9c5a29feb618bfef2bf458e025ecf3a57ad2268e2fb2569f56215 @@ -34736,9 +34987,9 @@ __metadata: linkType: hard "isbinaryfile@npm:^5.0.0": - version: 5.0.4 - resolution: "isbinaryfile@npm:5.0.4" - checksum: 10/6162e900b17e6c73da6138667d6b195ed234f9fd9d073e7c8c07ee36657e63b6a69d73da55f522d45a1928f5da4642b5d25d27e24ebd3bb68b83647d594bee79 + version: 5.0.7 + resolution: "isbinaryfile@npm:5.0.7" + checksum: 10/af240b2a80db5cffbb3ddcb4d89403802d6b67d21b63fbcc0be5cefcefc013f499477c5837a5b2f029ba3d163543eab36eaee7cd701f2c44ee5ac890f0fadac5 languageName: node linkType: hard @@ -34785,8 +35036,8 @@ __metadata: linkType: hard "isomorphic-git@npm:^1.23.0": - version: 1.27.2 - resolution: "isomorphic-git@npm:1.27.2" + version: 1.35.1 + resolution: "isomorphic-git@npm:1.35.1" dependencies: async-lock: "npm:^1.4.1" clean-git-ref: "npm:^2.0.1" @@ -34795,14 +35046,13 @@ __metadata: ignore: "npm:^5.1.4" minimisted: "npm:^2.0.0" pako: "npm:^1.0.10" - path-browserify: "npm:^1.0.1" pify: "npm:^4.0.1" - readable-stream: "npm:^3.4.0" - sha.js: "npm:^2.4.9" + readable-stream: "npm:^4.0.0" + sha.js: "npm:^2.4.12" simple-get: "npm:^4.0.1" bin: isogit: cli.cjs - checksum: 10/da4fa5ae6180e4a528b84f24ad4144c1a7587d5e79ed3f323b936809dc23b133615b96d7ecbb363009a30a2c9518bdf5efd572f918ddad801edc81693ddbb175 + checksum: 10/8f9244ef09a02c2779aaf682b8db40b208860d57f1bf9deed3c35641a87221f56e490b3f94178579f95d46e6a4e1bb593590994d8138649b32d60d03f9e1f5f8 languageName: node linkType: hard @@ -34847,29 +35097,16 @@ __metadata: languageName: node linkType: hard -"istanbul-lib-instrument@npm:^5.0.4": - version: 5.1.0 - resolution: "istanbul-lib-instrument@npm:5.1.0" +"istanbul-lib-instrument@npm:^6.0.0, istanbul-lib-instrument@npm:^6.0.2": + version: 6.0.3 + resolution: "istanbul-lib-instrument@npm:6.0.3" dependencies: - "@babel/core": "npm:^7.12.3" - "@babel/parser": "npm:^7.14.7" - "@istanbuljs/schema": "npm:^0.1.2" - istanbul-lib-coverage: "npm:^3.2.0" - semver: "npm:^6.3.0" - checksum: 10/7447ba3f8049f331d5b4a1c450183e88c2fdad044149ad0d9830f71bc8da90d841c393b830bc33237ae75122c3b0e03ca845701873d6c51690bc25caa1f13a94 - languageName: node - linkType: hard - -"istanbul-lib-instrument@npm:^6.0.0": - version: 6.0.1 - resolution: "istanbul-lib-instrument@npm:6.0.1" - dependencies: - "@babel/core": "npm:^7.12.3" - "@babel/parser": "npm:^7.14.7" - "@istanbuljs/schema": "npm:^0.1.2" + "@babel/core": "npm:^7.23.9" + "@babel/parser": "npm:^7.23.9" + "@istanbuljs/schema": "npm:^0.1.3" istanbul-lib-coverage: "npm:^3.2.0" semver: "npm:^7.5.4" - checksum: 10/95fd8c66e586840989cb3c7819c6da66c4742a6fedbf16b51a5c7f1898941ad07b79ddff020f479d3a1d76743ecdbf255d93c35221875687477d4b118026e7e7 + checksum: 10/aa5271c0008dfa71b6ecc9ba1e801bf77b49dc05524e8c30d58aaf5b9505e0cd12f25f93165464d4266a518c5c75284ecb598fbd89fec081ae77d2c9d3327695 languageName: node linkType: hard @@ -34884,14 +35121,14 @@ __metadata: languageName: node linkType: hard -"istanbul-lib-source-maps@npm:^4.0.0": - version: 4.0.0 - resolution: "istanbul-lib-source-maps@npm:4.0.0" +"istanbul-lib-source-maps@npm:^5.0.0": + version: 5.0.6 + resolution: "istanbul-lib-source-maps@npm:5.0.6" dependencies: + "@jridgewell/trace-mapping": "npm:^0.3.23" debug: "npm:^4.1.1" istanbul-lib-coverage: "npm:^3.0.0" - source-map: "npm:^0.6.1" - checksum: 10/765252abc6b5c9d29905fc97ce04b92da87d198f2c0161e62fe0aac8bb74fb7bd472a5e1d90fe3e78723d8cad43913f08d8eefa0339536fcc33b3a1922cf5fc3 + checksum: 10/569dd0a392ee3464b1fe1accbaef5cc26de3479eacb5b91d8c67ebb7b425d39fd02247d85649c3a0e9c29b600809fa60b5af5a281a75a89c01f385b1e24823a2 languageName: node linkType: hard @@ -34986,106 +35223,110 @@ __metadata: languageName: node linkType: hard -"jest-changed-files@npm:^29.7.0": - version: 29.7.0 - resolution: "jest-changed-files@npm:29.7.0" +"jest-changed-files@npm:30.2.0": + version: 30.2.0 + resolution: "jest-changed-files@npm:30.2.0" dependencies: - execa: "npm:^5.0.0" - jest-util: "npm:^29.7.0" + execa: "npm:^5.1.1" + jest-util: "npm:30.2.0" p-limit: "npm:^3.1.0" - checksum: 10/3d93742e56b1a73a145d55b66e96711fbf87ef89b96c2fab7cfdfba8ec06612591a982111ca2b712bb853dbc16831ec8b43585a2a96b83862d6767de59cbf83d + checksum: 10/ff2275ed5839b88c12ffa66fdc5c17ba02d3e276be6b558bed92872c282d050c3fdd1a275a81187cbe35c16d6d40337b85838772836463c7a2fbd1cba9785ca0 languageName: node linkType: hard -"jest-circus@npm:^29.7.0": - version: 29.7.0 - resolution: "jest-circus@npm:29.7.0" +"jest-circus@npm:30.2.0": + version: 30.2.0 + resolution: "jest-circus@npm:30.2.0" dependencies: - "@jest/environment": "npm:^29.7.0" - "@jest/expect": "npm:^29.7.0" - "@jest/test-result": "npm:^29.7.0" - "@jest/types": "npm:^29.6.3" + "@jest/environment": "npm:30.2.0" + "@jest/expect": "npm:30.2.0" + "@jest/test-result": "npm:30.2.0" + "@jest/types": "npm:30.2.0" "@types/node": "npm:*" - chalk: "npm:^4.0.0" + chalk: "npm:^4.1.2" co: "npm:^4.6.0" - dedent: "npm:^1.0.0" - is-generator-fn: "npm:^2.0.0" - jest-each: "npm:^29.7.0" - jest-matcher-utils: "npm:^29.7.0" - jest-message-util: "npm:^29.7.0" - jest-runtime: "npm:^29.7.0" - jest-snapshot: "npm:^29.7.0" - jest-util: "npm:^29.7.0" + dedent: "npm:^1.6.0" + is-generator-fn: "npm:^2.1.0" + jest-each: "npm:30.2.0" + jest-matcher-utils: "npm:30.2.0" + jest-message-util: "npm:30.2.0" + jest-runtime: "npm:30.2.0" + jest-snapshot: "npm:30.2.0" + jest-util: "npm:30.2.0" p-limit: "npm:^3.1.0" - pretty-format: "npm:^29.7.0" - pure-rand: "npm:^6.0.0" + pretty-format: "npm:30.2.0" + pure-rand: "npm:^7.0.0" slash: "npm:^3.0.0" - stack-utils: "npm:^2.0.3" - checksum: 10/716a8e3f40572fd0213bcfc1da90274bf30d856e5133af58089a6ce45089b63f4d679bd44e6be9d320e8390483ebc3ae9921981993986d21639d9019b523123d + stack-utils: "npm:^2.0.6" + checksum: 10/68bfc65d92385db1017643988215e4ff5af0b10bcab86fb749a063be6bb7d5eb556dc53dd21bedf833a19aa6ae1a781a8d27b2bea25562de02d294b3017435a9 languageName: node linkType: hard -"jest-cli@npm:^29.7.0": - version: 29.7.0 - resolution: "jest-cli@npm:29.7.0" +"jest-cli@npm:30.2.0": + version: 30.2.0 + resolution: "jest-cli@npm:30.2.0" dependencies: - "@jest/core": "npm:^29.7.0" - "@jest/test-result": "npm:^29.7.0" - "@jest/types": "npm:^29.6.3" - chalk: "npm:^4.0.0" - create-jest: "npm:^29.7.0" - exit: "npm:^0.1.2" - import-local: "npm:^3.0.2" - jest-config: "npm:^29.7.0" - jest-util: "npm:^29.7.0" - jest-validate: "npm:^29.7.0" - yargs: "npm:^17.3.1" + "@jest/core": "npm:30.2.0" + "@jest/test-result": "npm:30.2.0" + "@jest/types": "npm:30.2.0" + chalk: "npm:^4.1.2" + exit-x: "npm:^0.2.2" + import-local: "npm:^3.2.0" + jest-config: "npm:30.2.0" + jest-util: "npm:30.2.0" + jest-validate: "npm:30.2.0" + yargs: "npm:^17.7.2" peerDependencies: node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 peerDependenciesMeta: node-notifier: optional: true bin: - jest: bin/jest.js - checksum: 10/6cc62b34d002c034203065a31e5e9a19e7c76d9e8ef447a6f70f759c0714cb212c6245f75e270ba458620f9c7b26063cd8cf6cd1f7e3afd659a7cc08add17307 + jest: ./bin/jest.js + checksum: 10/1cc8304f0e2608801c84cdecce9565a6178f668a6475aed3767a1d82cc539915f98e7404d7c387510313684011dc3095c15397d6725f73aac80fbd96c4155faa languageName: node linkType: hard -"jest-config@npm:^29.7.0": - version: 29.7.0 - resolution: "jest-config@npm:29.7.0" +"jest-config@npm:30.2.0": + version: 30.2.0 + resolution: "jest-config@npm:30.2.0" dependencies: - "@babel/core": "npm:^7.11.6" - "@jest/test-sequencer": "npm:^29.7.0" - "@jest/types": "npm:^29.6.3" - babel-jest: "npm:^29.7.0" - chalk: "npm:^4.0.0" - ci-info: "npm:^3.2.0" - deepmerge: "npm:^4.2.2" - glob: "npm:^7.1.3" - graceful-fs: "npm:^4.2.9" - jest-circus: "npm:^29.7.0" - jest-environment-node: "npm:^29.7.0" - jest-get-type: "npm:^29.6.3" - jest-regex-util: "npm:^29.6.3" - jest-resolve: "npm:^29.7.0" - jest-runner: "npm:^29.7.0" - jest-util: "npm:^29.7.0" - jest-validate: "npm:^29.7.0" - micromatch: "npm:^4.0.4" + "@babel/core": "npm:^7.27.4" + "@jest/get-type": "npm:30.1.0" + "@jest/pattern": "npm:30.0.1" + "@jest/test-sequencer": "npm:30.2.0" + "@jest/types": "npm:30.2.0" + babel-jest: "npm:30.2.0" + chalk: "npm:^4.1.2" + ci-info: "npm:^4.2.0" + deepmerge: "npm:^4.3.1" + glob: "npm:^10.3.10" + graceful-fs: "npm:^4.2.11" + jest-circus: "npm:30.2.0" + jest-docblock: "npm:30.2.0" + jest-environment-node: "npm:30.2.0" + jest-regex-util: "npm:30.0.1" + jest-resolve: "npm:30.2.0" + jest-runner: "npm:30.2.0" + jest-util: "npm:30.2.0" + jest-validate: "npm:30.2.0" + micromatch: "npm:^4.0.8" parse-json: "npm:^5.2.0" - pretty-format: "npm:^29.7.0" + pretty-format: "npm:30.2.0" slash: "npm:^3.0.0" strip-json-comments: "npm:^3.1.1" peerDependencies: "@types/node": "*" + esbuild-register: ">=3.4.0" ts-node: ">=9.0.0" peerDependenciesMeta: "@types/node": optional: true + esbuild-register: + optional: true ts-node: optional: true - checksum: 10/6bdf570e9592e7d7dd5124fc0e21f5fe92bd15033513632431b211797e3ab57eaa312f83cc6481b3094b72324e369e876f163579d60016677c117ec4853cf02b + checksum: 10/296786b0a3d62de77e2f691f208d54ab541c1a73f87747d922eda643c6f25b89125ef3150170c07a6c8a316a30c15428e46237d499f688b0777f38de8a61ad16 languageName: node linkType: hard @@ -35098,7 +35339,19 @@ __metadata: languageName: node linkType: hard -"jest-diff@npm:^29.2.0, jest-diff@npm:^29.7.0": +"jest-diff@npm:30.2.0": + version: 30.2.0 + resolution: "jest-diff@npm:30.2.0" + dependencies: + "@jest/diff-sequences": "npm:30.0.1" + "@jest/get-type": "npm:30.1.0" + chalk: "npm:^4.1.2" + pretty-format: "npm:30.2.0" + checksum: 10/1fb9e4fb7dff81814b4f69eaa7db28e184d62306a3a8ea2447d02ca53d2cfa771e83ede513f67ec5239dffacfaac32ff2b49866d211e4c7516f51c1fc06ede42 + languageName: node + linkType: hard + +"jest-diff@npm:^29.2.0": version: 29.7.0 resolution: "jest-diff@npm:29.7.0" dependencies: @@ -35110,60 +35363,40 @@ __metadata: languageName: node linkType: hard -"jest-docblock@npm:^29.7.0": - version: 29.7.0 - resolution: "jest-docblock@npm:29.7.0" +"jest-docblock@npm:30.2.0": + version: 30.2.0 + resolution: "jest-docblock@npm:30.2.0" dependencies: - detect-newline: "npm:^3.0.0" - checksum: 10/8d48818055bc96c9e4ec2e217a5a375623c0d0bfae8d22c26e011074940c202aa2534a3362294c81d981046885c05d304376afba9f2874143025981148f3e96d + detect-newline: "npm:^3.1.0" + checksum: 10/e01a7d1193947ed0f9713c26bfc7852e51cb758cafec807e5665a0a8d582473a43778bee099f8aa5c70b2941963e5341f4b10bd86b036a4fa3bcec0f4c04e099 languageName: node linkType: hard -"jest-each@npm:^29.7.0": - version: 29.7.0 - resolution: "jest-each@npm:29.7.0" +"jest-each@npm:30.2.0": + version: 30.2.0 + resolution: "jest-each@npm:30.2.0" dependencies: - "@jest/types": "npm:^29.6.3" - chalk: "npm:^4.0.0" - jest-get-type: "npm:^29.6.3" - jest-util: "npm:^29.7.0" - pretty-format: "npm:^29.7.0" - checksum: 10/bd1a077654bdaa013b590deb5f7e7ade68f2e3289180a8c8f53bc8a49f3b40740c0ec2d3a3c1aee906f682775be2bebbac37491d80b634d15276b0aa0f2e3fda + "@jest/get-type": "npm:30.1.0" + "@jest/types": "npm:30.2.0" + chalk: "npm:^4.1.2" + jest-util: "npm:30.2.0" + pretty-format: "npm:30.2.0" + checksum: 10/f95e7dc1cef4b6a77899325702a214834ae25d01276cc31279654dc7e04f63c1925a37848dd16a0d16508c0fd3d182145f43c10af93952b7a689df3aeac198e9 languageName: node linkType: hard -"jest-environment-jsdom@npm:^29.0.2": - version: 29.7.0 - resolution: "jest-environment-jsdom@npm:29.7.0" +"jest-environment-node@npm:30.2.0": + version: 30.2.0 + resolution: "jest-environment-node@npm:30.2.0" dependencies: - "@jest/environment": "npm:^29.7.0" - "@jest/fake-timers": "npm:^29.7.0" - "@jest/types": "npm:^29.6.3" - "@types/jsdom": "npm:^20.0.0" + "@jest/environment": "npm:30.2.0" + "@jest/fake-timers": "npm:30.2.0" + "@jest/types": "npm:30.2.0" "@types/node": "npm:*" - jest-mock: "npm:^29.7.0" - jest-util: "npm:^29.7.0" - jsdom: "npm:^20.0.0" - peerDependencies: - canvas: ^2.5.0 - peerDependenciesMeta: - canvas: - optional: true - checksum: 10/23bbfc9bca914baef4b654f7983175a4d49b0f515a5094ebcb8f819f28ec186f53c0ba06af1855eac04bab1457f4ea79dae05f70052cf899863e8096daa6e0f5 - languageName: node - linkType: hard - -"jest-environment-node@npm:^29.7.0": - version: 29.7.0 - resolution: "jest-environment-node@npm:29.7.0" - dependencies: - "@jest/environment": "npm:^29.7.0" - "@jest/fake-timers": "npm:^29.7.0" - "@jest/types": "npm:^29.6.3" - "@types/node": "npm:*" - jest-mock: "npm:^29.7.0" - jest-util: "npm:^29.7.0" - checksum: 10/9cf7045adf2307cc93aed2f8488942e39388bff47ec1df149a997c6f714bfc66b2056768973770d3f8b1bf47396c19aa564877eb10ec978b952c6018ed1bd637 + jest-mock: "npm:30.2.0" + jest-util: "npm:30.2.0" + jest-validate: "npm:30.2.0" + checksum: 10/7918bfea7367bd3e12dbbc4ea5afb193b5c47e480a6d1382512f051e2f028458fc9f5ef2f6260737ad41a0b1894661790ff3aaf3cbb4148a33ce2ce7aec64847 languageName: node linkType: hard @@ -35174,232 +35407,223 @@ __metadata: languageName: node linkType: hard -"jest-haste-map@npm:29.7.0": - version: 29.7.0 - resolution: "jest-haste-map@npm:29.7.0" +"jest-haste-map@npm:30.2.0": + version: 30.2.0 + resolution: "jest-haste-map@npm:30.2.0" dependencies: - "@jest/types": "npm:^29.6.3" - "@types/graceful-fs": "npm:^4.1.3" + "@jest/types": "npm:30.2.0" "@types/node": "npm:*" - anymatch: "npm:^3.0.3" - fb-watchman: "npm:^2.0.0" - fsevents: "npm:^2.3.2" - graceful-fs: "npm:^4.2.9" - jest-regex-util: "npm:^29.6.3" - jest-util: "npm:^29.7.0" - jest-worker: "npm:^29.7.0" - micromatch: "npm:^4.0.4" + anymatch: "npm:^3.1.3" + fb-watchman: "npm:^2.0.2" + fsevents: "npm:^2.3.3" + graceful-fs: "npm:^4.2.11" + jest-regex-util: "npm:30.0.1" + jest-util: "npm:30.2.0" + jest-worker: "npm:30.2.0" + micromatch: "npm:^4.0.8" walker: "npm:^1.0.8" dependenciesMeta: fsevents: optional: true - checksum: 10/8531b42003581cb18a69a2774e68c456fb5a5c3280b1b9b77475af9e346b6a457250f9d756bfeeae2fe6cbc9ef28434c205edab9390ee970a919baddfa08bb85 + checksum: 10/a88be6b0b672144aa30fe2d72e630d639c8d8729ee2cef84d0f830eac2005ac021cd8354f8ed8ecd74223f6a8b281efb62f466f5c9e01ed17650e38761051f4c languageName: node linkType: hard -"jest-haste-map@patch:jest-haste-map@npm%3A29.7.0#./.yarn/patches/jest-haste-map-npm-29.7.0-e3be419eff.patch::locator=root%40workspace%3A.": - version: 29.7.0 - resolution: "jest-haste-map@patch:jest-haste-map@npm%3A29.7.0#./.yarn/patches/jest-haste-map-npm-29.7.0-e3be419eff.patch::version=29.7.0&hash=feed88&locator=root%40workspace%3A." +"jest-leak-detector@npm:30.2.0": + version: 30.2.0 + resolution: "jest-leak-detector@npm:30.2.0" dependencies: - "@jest/types": "npm:^29.6.3" - "@types/graceful-fs": "npm:^4.1.3" - "@types/node": "npm:*" - anymatch: "npm:^3.0.3" - fb-watchman: "npm:^2.0.0" - fsevents: "npm:^2.3.2" - graceful-fs: "npm:^4.2.9" - jest-regex-util: "npm:^29.6.3" - jest-util: "npm:^29.7.0" - jest-worker: "npm:^29.7.0" - micromatch: "npm:^4.0.4" - walker: "npm:^1.0.8" - dependenciesMeta: - fsevents: - optional: true - checksum: 10/e93fab6316f0cdb5e930491efe87e9957a83200a58c37acedbea84472fbf67472675e3235d249b04726aaf09a23a5eadc4a7890e85969e2a8c7bf6b402c1ff5e + "@jest/get-type": "npm:30.1.0" + pretty-format: "npm:30.2.0" + checksum: 10/c430d6ed7910b2174738fbdca4ea64cbfe805216414c0d143c1090148f1389fec99d0733c0a8ed0a86709c89b4a4085b4749ac3a2cbc7deaf3ca87457afd24fc languageName: node linkType: hard -"jest-leak-detector@npm:^29.7.0": - version: 29.7.0 - resolution: "jest-leak-detector@npm:29.7.0" +"jest-matcher-utils@npm:30.2.0": + version: 30.2.0 + resolution: "jest-matcher-utils@npm:30.2.0" dependencies: - jest-get-type: "npm:^29.6.3" - pretty-format: "npm:^29.7.0" - checksum: 10/e3950e3ddd71e1d0c22924c51a300a1c2db6cf69ec1e51f95ccf424bcc070f78664813bef7aed4b16b96dfbdeea53fe358f8aeaaea84346ae15c3735758f1605 + "@jest/get-type": "npm:30.1.0" + chalk: "npm:^4.1.2" + jest-diff: "npm:30.2.0" + pretty-format: "npm:30.2.0" + checksum: 10/f3f1ecf68ca63c9d1d80a175637a8fc655edfd1ee83220f6e3f6bd464ecbe2f93148fdd440a5a5e5a2b0b2cc8ee84ddc3dcef58a6dbc66821c792f48d260c6d4 languageName: node linkType: hard -"jest-matcher-utils@npm:^29.7.0": - version: 29.7.0 - resolution: "jest-matcher-utils@npm:29.7.0" +"jest-message-util@npm:30.2.0": + version: 30.2.0 + resolution: "jest-message-util@npm:30.2.0" dependencies: - chalk: "npm:^4.0.0" - jest-diff: "npm:^29.7.0" - jest-get-type: "npm:^29.6.3" - pretty-format: "npm:^29.7.0" - checksum: 10/981904a494299cf1e3baed352f8a3bd8b50a8c13a662c509b6a53c31461f94ea3bfeffa9d5efcfeb248e384e318c87de7e3baa6af0f79674e987482aa189af40 - languageName: node - linkType: hard - -"jest-message-util@npm:^29.7.0": - version: 29.7.0 - resolution: "jest-message-util@npm:29.7.0" - dependencies: - "@babel/code-frame": "npm:^7.12.13" - "@jest/types": "npm:^29.6.3" - "@types/stack-utils": "npm:^2.0.0" - chalk: "npm:^4.0.0" - graceful-fs: "npm:^4.2.9" - micromatch: "npm:^4.0.4" - pretty-format: "npm:^29.7.0" + "@babel/code-frame": "npm:^7.27.1" + "@jest/types": "npm:30.2.0" + "@types/stack-utils": "npm:^2.0.3" + chalk: "npm:^4.1.2" + graceful-fs: "npm:^4.2.11" + micromatch: "npm:^4.0.8" + pretty-format: "npm:30.2.0" slash: "npm:^3.0.0" - stack-utils: "npm:^2.0.3" - checksum: 10/31d53c6ed22095d86bab9d14c0fa70c4a92c749ea6ceece82cf30c22c9c0e26407acdfbdb0231435dc85a98d6d65ca0d9cbcd25cd1abb377fe945e843fb770b9 + stack-utils: "npm:^2.0.6" + checksum: 10/e29ec76e8c8e4da5f5b25198be247535626ccf3a940e93fdd51fc6a6bcf70feaa2921baae3806182a090431d90b08c939eb13fb64249b171d2e9ae3a452a8fd2 languageName: node linkType: hard -"jest-mock@npm:^29.7.0": - version: 29.7.0 - resolution: "jest-mock@npm:29.7.0" +"jest-mock@npm:30.2.0": + version: 30.2.0 + resolution: "jest-mock@npm:30.2.0" dependencies: - "@jest/types": "npm:^29.6.3" + "@jest/types": "npm:30.2.0" "@types/node": "npm:*" - jest-util: "npm:^29.7.0" - checksum: 10/ae51d1b4f898724be5e0e52b2268a68fcd876d9b20633c864a6dd6b1994cbc48d62402b0f40f3a1b669b30ebd648821f086c26c08ffde192ced951ff4670d51c + jest-util: "npm:30.2.0" + checksum: 10/cde9b56805f90bf811a9231873ee88a0fb83bf4bf50972ae76960725da65220fcb119688f2e90e1ef33fbfd662194858d7f43809d881f1c41bb55d94e62adeab languageName: node linkType: hard -"jest-pnp-resolver@npm:^1.2.2": - version: 1.2.2 - resolution: "jest-pnp-resolver@npm:1.2.2" +"jest-pnp-resolver@npm:^1.2.3": + version: 1.2.3 + resolution: "jest-pnp-resolver@npm:1.2.3" peerDependencies: jest-resolve: "*" peerDependenciesMeta: jest-resolve: optional: true - checksum: 10/bd85dcc0e76e0eb0c3d56382ec140f08d25ff4068cda9d0e360bb78fb176cb726d0beab82dc0e8694cafd09f55fee7622b8bcb240afa5fad301f4ed3eebb4f47 + checksum: 10/db1a8ab2cb97ca19c01b1cfa9a9c8c69a143fde833c14df1fab0766f411b1148ff0df878adea09007ac6a2085ec116ba9a996a6ad104b1e58c20adbf88eed9b2 languageName: node linkType: hard -"jest-regex-util@npm:^29.6.3": - version: 29.6.3 - resolution: "jest-regex-util@npm:29.6.3" - checksum: 10/0518beeb9bf1228261695e54f0feaad3606df26a19764bc19541e0fc6e2a3737191904607fb72f3f2ce85d9c16b28df79b7b1ec9443aa08c3ef0e9efda6f8f2a +"jest-regex-util@npm:30.0.1": + version: 30.0.1 + resolution: "jest-regex-util@npm:30.0.1" + checksum: 10/fa8dac80c3e94db20d5e1e51d1bdf101cf5ede8f4e0b8f395ba8b8ea81e71804ffd747452a6bb6413032865de98ac656ef8ae43eddd18d980b6442a2764ed562 languageName: node linkType: hard -"jest-resolve-dependencies@npm:^29.7.0": - version: 29.7.0 - resolution: "jest-resolve-dependencies@npm:29.7.0" +"jest-resolve-dependencies@npm:30.2.0": + version: 30.2.0 + resolution: "jest-resolve-dependencies@npm:30.2.0" dependencies: - jest-regex-util: "npm:^29.6.3" - jest-snapshot: "npm:^29.7.0" - checksum: 10/1e206f94a660d81e977bcfb1baae6450cb4a81c92e06fad376cc5ea16b8e8c6ea78c383f39e95591a9eb7f925b6a1021086c38941aa7c1b8a6a813c2f6e93675 + jest-regex-util: "npm:30.0.1" + jest-snapshot: "npm:30.2.0" + checksum: 10/0ff1a574f8c07f2e54a4ac8ab17aea00dfe2982e99b03fbd44f4211a94b8e5a59fdc43a59f9d6c0578a10a7b56a0611ad5ab40e4893973ff3f40dd414433b194 languageName: node linkType: hard -"jest-resolve@npm:^29.7.0": - version: 29.7.0 - resolution: "jest-resolve@npm:29.7.0" +"jest-resolve@npm:30.2.0": + version: 30.2.0 + resolution: "jest-resolve@npm:30.2.0" dependencies: - chalk: "npm:^4.0.0" - graceful-fs: "npm:^4.2.9" - jest-haste-map: "npm:^29.7.0" - jest-pnp-resolver: "npm:^1.2.2" - jest-util: "npm:^29.7.0" - jest-validate: "npm:^29.7.0" - resolve: "npm:^1.20.0" - resolve.exports: "npm:^2.0.0" + chalk: "npm:^4.1.2" + graceful-fs: "npm:^4.2.11" + jest-haste-map: "npm:30.2.0" + jest-pnp-resolver: "npm:^1.2.3" + jest-util: "npm:30.2.0" + jest-validate: "npm:30.2.0" slash: "npm:^3.0.0" - checksum: 10/faa466fd9bc69ea6c37a545a7c6e808e073c66f46ab7d3d8a6ef084f8708f201b85d5fe1799789578b8b47fa1de47b9ee47b414d1863bc117a49e032ba77b7c7 + unrs-resolver: "npm:^1.7.11" + checksum: 10/e1f03da6811a946f5d885ea739a973975d099cc760641f9e1f90ac9c6621408538ba1e909f789d45d6e8d2411b78fb09230f16f15669621aa407aed7511fdf01 languageName: node linkType: hard -"jest-runner@npm:^29.7.0": - version: 29.7.0 - resolution: "jest-runner@npm:29.7.0" +"jest-runner@npm:30.2.0": + version: 30.2.0 + resolution: "jest-runner@npm:30.2.0" dependencies: - "@jest/console": "npm:^29.7.0" - "@jest/environment": "npm:^29.7.0" - "@jest/test-result": "npm:^29.7.0" - "@jest/transform": "npm:^29.7.0" - "@jest/types": "npm:^29.6.3" + "@jest/console": "npm:30.2.0" + "@jest/environment": "npm:30.2.0" + "@jest/test-result": "npm:30.2.0" + "@jest/transform": "npm:30.2.0" + "@jest/types": "npm:30.2.0" "@types/node": "npm:*" - chalk: "npm:^4.0.0" + chalk: "npm:^4.1.2" emittery: "npm:^0.13.1" - graceful-fs: "npm:^4.2.9" - jest-docblock: "npm:^29.7.0" - jest-environment-node: "npm:^29.7.0" - jest-haste-map: "npm:^29.7.0" - jest-leak-detector: "npm:^29.7.0" - jest-message-util: "npm:^29.7.0" - jest-resolve: "npm:^29.7.0" - jest-runtime: "npm:^29.7.0" - jest-util: "npm:^29.7.0" - jest-watcher: "npm:^29.7.0" - jest-worker: "npm:^29.7.0" + exit-x: "npm:^0.2.2" + graceful-fs: "npm:^4.2.11" + jest-docblock: "npm:30.2.0" + jest-environment-node: "npm:30.2.0" + jest-haste-map: "npm:30.2.0" + jest-leak-detector: "npm:30.2.0" + jest-message-util: "npm:30.2.0" + jest-resolve: "npm:30.2.0" + jest-runtime: "npm:30.2.0" + jest-util: "npm:30.2.0" + jest-watcher: "npm:30.2.0" + jest-worker: "npm:30.2.0" p-limit: "npm:^3.1.0" source-map-support: "npm:0.5.13" - checksum: 10/9d8748a494bd90f5c82acea99be9e99f21358263ce6feae44d3f1b0cd90991b5df5d18d607e73c07be95861ee86d1cbab2a3fc6ca4b21805f07ac29d47c1da1e + checksum: 10/d3706aa70e64a7ef8b38360d34ea6c261ba4d0b42136d7fb603c4fa71c24fa81f22c39ed2e39ee0db2363a42827810291f3ceb6a299e5996b41d701ad9b24184 languageName: node linkType: hard -"jest-runtime@npm:^29.0.2, jest-runtime@npm:^29.7.0": - version: 29.7.0 - resolution: "jest-runtime@npm:29.7.0" +"jest-runtime@npm:30.2.0": + version: 30.2.0 + resolution: "jest-runtime@npm:30.2.0" dependencies: - "@jest/environment": "npm:^29.7.0" - "@jest/fake-timers": "npm:^29.7.0" - "@jest/globals": "npm:^29.7.0" - "@jest/source-map": "npm:^29.6.3" - "@jest/test-result": "npm:^29.7.0" - "@jest/transform": "npm:^29.7.0" - "@jest/types": "npm:^29.6.3" + "@jest/environment": "npm:30.2.0" + "@jest/fake-timers": "npm:30.2.0" + "@jest/globals": "npm:30.2.0" + "@jest/source-map": "npm:30.0.1" + "@jest/test-result": "npm:30.2.0" + "@jest/transform": "npm:30.2.0" + "@jest/types": "npm:30.2.0" "@types/node": "npm:*" - chalk: "npm:^4.0.0" - cjs-module-lexer: "npm:^1.0.0" - collect-v8-coverage: "npm:^1.0.0" - glob: "npm:^7.1.3" - graceful-fs: "npm:^4.2.9" - jest-haste-map: "npm:^29.7.0" - jest-message-util: "npm:^29.7.0" - jest-mock: "npm:^29.7.0" - jest-regex-util: "npm:^29.6.3" - jest-resolve: "npm:^29.7.0" - jest-snapshot: "npm:^29.7.0" - jest-util: "npm:^29.7.0" + chalk: "npm:^4.1.2" + cjs-module-lexer: "npm:^2.1.0" + collect-v8-coverage: "npm:^1.0.2" + glob: "npm:^10.3.10" + graceful-fs: "npm:^4.2.11" + jest-haste-map: "npm:30.2.0" + jest-message-util: "npm:30.2.0" + jest-mock: "npm:30.2.0" + jest-regex-util: "npm:30.0.1" + jest-resolve: "npm:30.2.0" + jest-snapshot: "npm:30.2.0" + jest-util: "npm:30.2.0" slash: "npm:^3.0.0" strip-bom: "npm:^4.0.0" - checksum: 10/59eb58eb7e150e0834a2d0c0d94f2a0b963ae7182cfa6c63f2b49b9c6ef794e5193ef1634e01db41420c36a94cefc512cdd67a055cd3e6fa2f41eaf0f82f5a20 + checksum: 10/81a3a9951420863f001e74c510bf35b85ae983f636f43ee1ffa1618b5a8ddafb681bc2810f71814bc8c8373e9593c89576b2325daf3c765e50057e48d5941df3 languageName: node linkType: hard -"jest-snapshot@npm:^29.7.0": - version: 29.7.0 - resolution: "jest-snapshot@npm:29.7.0" +"jest-snapshot@npm:30.2.0": + version: 30.2.0 + resolution: "jest-snapshot@npm:30.2.0" dependencies: - "@babel/core": "npm:^7.11.6" - "@babel/generator": "npm:^7.7.2" - "@babel/plugin-syntax-jsx": "npm:^7.7.2" - "@babel/plugin-syntax-typescript": "npm:^7.7.2" - "@babel/types": "npm:^7.3.3" - "@jest/expect-utils": "npm:^29.7.0" - "@jest/transform": "npm:^29.7.0" - "@jest/types": "npm:^29.6.3" - babel-preset-current-node-syntax: "npm:^1.0.0" - chalk: "npm:^4.0.0" - expect: "npm:^29.7.0" - graceful-fs: "npm:^4.2.9" - jest-diff: "npm:^29.7.0" - jest-get-type: "npm:^29.6.3" - jest-matcher-utils: "npm:^29.7.0" - jest-message-util: "npm:^29.7.0" - jest-util: "npm:^29.7.0" - natural-compare: "npm:^1.4.0" - pretty-format: "npm:^29.7.0" - semver: "npm:^7.5.3" - checksum: 10/cb19a3948256de5f922d52f251821f99657339969bf86843bd26cf3332eae94883e8260e3d2fba46129a27c3971c1aa522490e460e16c7fad516e82d10bbf9f8 + "@babel/core": "npm:^7.27.4" + "@babel/generator": "npm:^7.27.5" + "@babel/plugin-syntax-jsx": "npm:^7.27.1" + "@babel/plugin-syntax-typescript": "npm:^7.27.1" + "@babel/types": "npm:^7.27.3" + "@jest/expect-utils": "npm:30.2.0" + "@jest/get-type": "npm:30.1.0" + "@jest/snapshot-utils": "npm:30.2.0" + "@jest/transform": "npm:30.2.0" + "@jest/types": "npm:30.2.0" + babel-preset-current-node-syntax: "npm:^1.2.0" + chalk: "npm:^4.1.2" + expect: "npm:30.2.0" + graceful-fs: "npm:^4.2.11" + jest-diff: "npm:30.2.0" + jest-matcher-utils: "npm:30.2.0" + jest-message-util: "npm:30.2.0" + jest-util: "npm:30.2.0" + pretty-format: "npm:30.2.0" + semver: "npm:^7.7.2" + synckit: "npm:^0.11.8" + checksum: 10/119390b49f397ed622ba7c375fc15f97af67c4fc49a34cf829c86ee732be2b06ad3c7171c76bb842a0e84a234783f1a4c721909aa316fbe00c6abc7c5962dfbc + languageName: node + linkType: hard + +"jest-util@npm:30.2.0": + version: 30.2.0 + resolution: "jest-util@npm:30.2.0" + dependencies: + "@jest/types": "npm:30.2.0" + "@types/node": "npm:*" + chalk: "npm:^4.1.2" + ci-info: "npm:^4.2.0" + graceful-fs: "npm:^4.2.11" + picomatch: "npm:^4.0.2" + checksum: 10/cf2f2fb83417ea69f9992121561c95cf4e9aad7946819b771b8b52addf78811101b33b51d0a39fa0c305f2751dab262feed7699de052659ff03d51827c8862f5 languageName: node linkType: hard @@ -35417,33 +35641,33 @@ __metadata: languageName: node linkType: hard -"jest-validate@npm:^29.7.0": - version: 29.7.0 - resolution: "jest-validate@npm:29.7.0" +"jest-validate@npm:30.2.0": + version: 30.2.0 + resolution: "jest-validate@npm:30.2.0" dependencies: - "@jest/types": "npm:^29.6.3" - camelcase: "npm:^6.2.0" - chalk: "npm:^4.0.0" - jest-get-type: "npm:^29.6.3" + "@jest/get-type": "npm:30.1.0" + "@jest/types": "npm:30.2.0" + camelcase: "npm:^6.3.0" + chalk: "npm:^4.1.2" leven: "npm:^3.1.0" - pretty-format: "npm:^29.7.0" - checksum: 10/8ee1163666d8eaa16d90a989edba2b4a3c8ab0ffaa95ad91b08ca42b015bfb70e164b247a5b17f9de32d096987cada63ed8491ab82761bfb9a28bc34b27ae161 + pretty-format: "npm:30.2.0" + checksum: 10/61e66c6df29a1e181f8de063678dd2096bb52cc8a8ead3c9a3f853d54eca458ad04c7fb81931d9274affb67d0504a91a2a520456a139a26665810c3bf039b677 languageName: node linkType: hard -"jest-watcher@npm:^29.7.0": - version: 29.7.0 - resolution: "jest-watcher@npm:29.7.0" +"jest-watcher@npm:30.2.0": + version: 30.2.0 + resolution: "jest-watcher@npm:30.2.0" dependencies: - "@jest/test-result": "npm:^29.7.0" - "@jest/types": "npm:^29.6.3" + "@jest/test-result": "npm:30.2.0" + "@jest/types": "npm:30.2.0" "@types/node": "npm:*" - ansi-escapes: "npm:^4.2.1" - chalk: "npm:^4.0.0" + ansi-escapes: "npm:^4.3.2" + chalk: "npm:^4.1.2" emittery: "npm:^0.13.1" - jest-util: "npm:^29.7.0" - string-length: "npm:^4.0.1" - checksum: 10/4f616e0345676631a7034b1d94971aaa719f0cd4a6041be2aa299be437ea047afd4fe05c48873b7963f5687a2f6c7cbf51244be8b14e313b97bfe32b1e127e55 + jest-util: "npm:30.2.0" + string-length: "npm:^4.0.2" + checksum: 10/fa38d06dcc59dbbd6a9ff22dea499d3c81ed376d9993b82d01797a99bf466d48641a99b9f3670a4b5480ca31144c5e017b96b7059e4d7541358fb48cf517a2db languageName: node linkType: hard @@ -35466,6 +35690,19 @@ __metadata: languageName: node linkType: hard +"jest-worker@npm:30.2.0": + version: 30.2.0 + resolution: "jest-worker@npm:30.2.0" + dependencies: + "@types/node": "npm:*" + "@ungap/structured-clone": "npm:^1.3.0" + jest-util: "npm:30.2.0" + merge-stream: "npm:^2.0.0" + supports-color: "npm:^8.1.1" + checksum: 10/9354b0c71c80173f673da6bbc0ddaad26e4395b06532f7332e0c1e93e855b873b10139b040e01eda77f3dc5a0b67613e2bd7c56c4947ee771acfc3611de2ca29 + languageName: node + linkType: hard + "jest-worker@npm:^27.4.5": version: 27.5.1 resolution: "jest-worker@npm:27.5.1" @@ -35489,26 +35726,26 @@ __metadata: languageName: node linkType: hard -"jest@npm:^29.7.0": - version: 29.7.0 - resolution: "jest@npm:29.7.0" +"jest@npm:^30.2.0": + version: 30.2.0 + resolution: "jest@npm:30.2.0" dependencies: - "@jest/core": "npm:^29.7.0" - "@jest/types": "npm:^29.6.3" - import-local: "npm:^3.0.2" - jest-cli: "npm:^29.7.0" + "@jest/core": "npm:30.2.0" + "@jest/types": "npm:30.2.0" + import-local: "npm:^3.2.0" + jest-cli: "npm:30.2.0" peerDependencies: node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 peerDependenciesMeta: node-notifier: optional: true bin: - jest: bin/jest.js - checksum: 10/97023d78446098c586faaa467fbf2c6b07ff06e2c85a19e3926adb5b0effe9ac60c4913ae03e2719f9c01ae8ffd8d92f6b262cedb9555ceeb5d19263d8c6362a + jest: ./bin/jest.js + checksum: 10/61c9d100750e4354cd7305d1f3ba253ffde4deaf12cb4be4d42d54f2dd5986e383a39c4a8691dbdc3839c69094a52413ed36f1886540ac37b71914a990b810d0 languageName: node linkType: hard -"jiti@npm:^2.0.0, jiti@npm:^2.4.2": +"jiti@npm:^2.0.0, jiti@npm:^2.6.0": version: 2.6.1 resolution: "jiti@npm:2.6.1" bin: @@ -35539,23 +35776,23 @@ __metadata: linkType: hard "jose@npm:^5.0.0": - version: 5.8.0 - resolution: "jose@npm:5.8.0" - checksum: 10/d5a11135754aeb7e3dcfbfb33ae1087541a081002cedb533e4705a9d71237a2c22f21085a291a0847939257a7b2f2374b589d306be17c3330049aefb62719c5e + version: 5.10.0 + resolution: "jose@npm:5.10.0" + checksum: 10/03881d1dfb390dcf50926402edcfe233bf557b5a77321fcb1bdb53453bc1cdd26d2d0a9ab28c7445cbb826881f84fdf5074179700f10c2711ccb9880f51065d7 languageName: node linkType: hard -"jose@npm:^6.0.10": - version: 6.0.10 - resolution: "jose@npm:6.0.10" - checksum: 10/8ba0d1aca94bdf780247c737328114fab3e394e1531e881dfe3fdd1d4a293b08cf7c0242769e72c8c8eee15c95761b542cf10730c3dfbb108084762df7d25cec +"jose@npm:^6.0.10, jose@npm:^6.1.1": + version: 6.1.3 + resolution: "jose@npm:6.1.3" + checksum: 10/9626c51e8c3792b505e954f3094698c182208617b62dfb27269230f31e57560b083985ed8128b8a9753aa92daf18d3a2341cc826d149503f14569abe87d42389 languageName: node linkType: hard "js-base64@npm:^3.6.0": - version: 3.7.7 - resolution: "js-base64@npm:3.7.7" - checksum: 10/185e34c536a6b1c4e1ad8bd96d25b49a9ea4e6803e259eaaaca95f1b392a0d590b2933c5ca8580c776f7279507944b81ff1faf889d84baa5e31f026e96d676a5 + version: 3.7.8 + resolution: "js-base64@npm:3.7.8" + checksum: 10/4baa9a222bc094b072933e4894735653b59992477c731879784e3112f21862b08dd5c56b8b23b0b8e43bc5bb514d957621d1892a6c58950f29e12b731fe087b6 languageName: node linkType: hard @@ -35594,30 +35831,7 @@ __metadata: languageName: node linkType: hard -"js-yaml@npm:=4.1.0": - version: 4.1.0 - resolution: "js-yaml@npm:4.1.0" - dependencies: - argparse: "npm:^2.0.1" - bin: - js-yaml: bin/js-yaml.js - checksum: 10/c138a34a3fd0d08ebaf71273ad4465569a483b8a639e0b118ff65698d257c2791d3199e3f303631f2cb98213fa7b5f5d6a4621fd0fff819421b990d30d967140 - languageName: node - linkType: hard - -"js-yaml@npm:^3.10.0, js-yaml@npm:^3.13.0, js-yaml@npm:^3.13.1, js-yaml@npm:^3.6.1, js-yaml@npm:^3.8.3": - version: 3.14.1 - resolution: "js-yaml@npm:3.14.1" - dependencies: - argparse: "npm:^1.0.7" - esprima: "npm:^4.0.0" - bin: - js-yaml: bin/js-yaml.js - checksum: 10/9e22d80b4d0105b9899135365f746d47466ed53ef4223c529b3c0f7a39907743fdbd3c4379f94f1106f02755b5e90b2faaf84801a891135544e1ea475d1a1379 - languageName: node - linkType: hard - -"js-yaml@npm:^4.0.0, js-yaml@npm:^4.1.0, js-yaml@npm:^4.1.1, js-yaml@npm:~4.1.0": +"js-yaml@npm:=4.1.1, js-yaml@npm:^4.0.0, js-yaml@npm:^4.1.0, js-yaml@npm:^4.1.1, js-yaml@npm:~4.1.0": version: 4.1.1 resolution: "js-yaml@npm:4.1.1" dependencies: @@ -35628,6 +35842,18 @@ __metadata: languageName: node linkType: hard +"js-yaml@npm:^3.10.0, js-yaml@npm:^3.13.0, js-yaml@npm:^3.13.1, js-yaml@npm:^3.6.1, js-yaml@npm:^3.8.3": + version: 3.14.2 + resolution: "js-yaml@npm:3.14.2" + dependencies: + argparse: "npm:^1.0.7" + esprima: "npm:^4.0.0" + bin: + js-yaml: bin/js-yaml.js + checksum: 10/172e0b6007b0bf0fc8d2469c94424f7dd765c64a047d2b790831fecef2204a4054eabf4d911eb73ab8c9a3256ab8ba1ee8d655b789bf24bf059c772acc2075a1 + languageName: node + linkType: hard + "jsbn@npm:1.1.0, jsbn@npm:^1.1.0": version: 1.1.0 resolution: "jsbn@npm:1.1.0" @@ -35690,46 +35916,6 @@ __metadata: languageName: node linkType: hard -"jsdom@npm:^20.0.0": - version: 20.0.0 - resolution: "jsdom@npm:20.0.0" - dependencies: - abab: "npm:^2.0.6" - acorn: "npm:^8.7.1" - acorn-globals: "npm:^6.0.0" - cssom: "npm:^0.5.0" - cssstyle: "npm:^2.3.0" - data-urls: "npm:^3.0.2" - decimal.js: "npm:^10.3.1" - domexception: "npm:^4.0.0" - escodegen: "npm:^2.0.0" - form-data: "npm:^4.0.0" - html-encoding-sniffer: "npm:^3.0.0" - http-proxy-agent: "npm:^5.0.0" - https-proxy-agent: "npm:^5.0.1" - is-potential-custom-element-name: "npm:^1.0.1" - nwsapi: "npm:^2.2.0" - parse5: "npm:^7.0.0" - saxes: "npm:^6.0.0" - symbol-tree: "npm:^3.2.4" - tough-cookie: "npm:^4.0.0" - w3c-hr-time: "npm:^1.0.2" - w3c-xmlserializer: "npm:^3.0.0" - webidl-conversions: "npm:^7.0.0" - whatwg-encoding: "npm:^2.0.0" - whatwg-mimetype: "npm:^3.0.0" - whatwg-url: "npm:^11.0.0" - ws: "npm:^8.8.0" - xml-name-validator: "npm:^4.0.0" - peerDependencies: - canvas: ^2.5.0 - peerDependenciesMeta: - canvas: - optional: true - checksum: 10/5492ef8f496183bbce738977a0fb43b57a269d9d79fe12ea03d33ce9821a5ef54cb1580b94a662bf2d5ba463790fb61a9e892a87eb95d02e72bdf4068280a737 - languageName: node - linkType: hard - "jsdom@npm:^25.0.1": version: 25.0.1 resolution: "jsdom@npm:25.0.1" @@ -35764,6 +35950,39 @@ __metadata: languageName: node linkType: hard +"jsdom@npm:^27.1.0": + version: 27.3.0 + resolution: "jsdom@npm:27.3.0" + dependencies: + "@acemir/cssom": "npm:^0.9.28" + "@asamuzakjp/dom-selector": "npm:^6.7.6" + cssstyle: "npm:^5.3.4" + data-urls: "npm:^6.0.0" + decimal.js: "npm:^10.6.0" + html-encoding-sniffer: "npm:^4.0.0" + http-proxy-agent: "npm:^7.0.2" + https-proxy-agent: "npm:^7.0.6" + is-potential-custom-element-name: "npm:^1.0.1" + parse5: "npm:^8.0.0" + saxes: "npm:^6.0.0" + symbol-tree: "npm:^3.2.4" + tough-cookie: "npm:^6.0.0" + w3c-xmlserializer: "npm:^5.0.0" + webidl-conversions: "npm:^8.0.0" + whatwg-encoding: "npm:^3.1.1" + whatwg-mimetype: "npm:^4.0.0" + whatwg-url: "npm:^15.1.0" + ws: "npm:^8.18.3" + xml-name-validator: "npm:^5.0.0" + peerDependencies: + canvas: ^3.0.0 + peerDependenciesMeta: + canvas: + optional: true + checksum: 10/c650e954df04a80e7309984450ce764ae2a840810b9575b20204194dee3c5cff42e65526519cb58b946ffe66a058b7b763bad4814b3903a9c86a2c1651b8b74b + languageName: node + linkType: hard + "jsep@npm:^1.2.0, jsep@npm:^1.3.6, jsep@npm:^1.4.0": version: 1.4.0 resolution: "jsep@npm:1.4.0" @@ -36209,45 +36428,45 @@ __metadata: languageName: node linkType: hard -"jwa@npm:^1.4.1": - version: 1.4.1 - resolution: "jwa@npm:1.4.1" +"jwa@npm:^1.4.2": + version: 1.4.2 + resolution: "jwa@npm:1.4.2" dependencies: - buffer-equal-constant-time: "npm:1.0.1" + buffer-equal-constant-time: "npm:^1.0.1" ecdsa-sig-formatter: "npm:1.0.11" safe-buffer: "npm:^5.0.1" - checksum: 10/0bc002b71dd70480fedc7d442a4d2b9185a9947352a027dcb4935864ad2323c57b5d391adf968a3622b61e940cef4f3484d5813b95864539272d41cac145d6f3 + checksum: 10/a46c9ddbcc226d9e85e13ef96328c7d331abddd66b5a55ec44bcf4350464a6125385ac9c1e64faa0fae8d586d90a14d6b5e96c73f0388970a3918d5252efb0f3 languageName: node linkType: hard -"jwa@npm:^2.0.0": - version: 2.0.0 - resolution: "jwa@npm:2.0.0" +"jwa@npm:^2.0.1": + version: 2.0.1 + resolution: "jwa@npm:2.0.1" dependencies: - buffer-equal-constant-time: "npm:1.0.1" + buffer-equal-constant-time: "npm:^1.0.1" ecdsa-sig-formatter: "npm:1.0.11" safe-buffer: "npm:^5.0.1" - checksum: 10/ab983f6685d99d13ddfbffef9b1c66309a536362a8412d49ba6e687d834a1240ce39290f30ac7dbe241e0ab6c76fee7ff795776ce534e11d148158c9b7193498 + checksum: 10/b04312a1de85f912b96aa3a7211717b8336945fab5b4f7cbc7800f4c80934060c0a3111576fad8d76e41ad62887d6da4b21fd4c47e45c174197f8be7dc0c1694 languageName: node linkType: hard "jws@npm:^3.2.2": - version: 3.2.2 - resolution: "jws@npm:3.2.2" + version: 3.2.3 + resolution: "jws@npm:3.2.3" dependencies: - jwa: "npm:^1.4.1" + jwa: "npm:^1.4.2" safe-buffer: "npm:^5.0.1" - checksum: 10/70b016974af8a76d25030c80a0097b24ed5b17a9cf10f43b163c11cb4eb248d5d04a3fe48c0d724d2884c32879d878ccad7be0663720f46b464f662f7ed778fe + checksum: 10/707387dd1cabcc3d9c2818f773cfaac7ede66e79ca11bbd159285a88cf5d8e8f355afcb8ee373e7bb0fcf9b7a2df015b22c50f27842f2c77453f04cd9f8f4009 languageName: node linkType: hard "jws@npm:^4.0.0": - version: 4.0.0 - resolution: "jws@npm:4.0.0" + version: 4.0.1 + resolution: "jws@npm:4.0.1" dependencies: - jwa: "npm:^2.0.0" + jwa: "npm:^2.0.1" safe-buffer: "npm:^5.0.1" - checksum: 10/1d15f4cdea376c6bd6a81002bd2cb0bf3d51d83da8f0727947b5ba3e10cf366721b8c0d099bf8c1eb99eb036e2c55e5fd5efd378ccff75a2b4e0bd10002348b9 + checksum: 10/75d7b157489fa9a72023712c58a7a7706c7e2b10eec27fabd3bb9cae0c9e492251ab72527d20a8a5f5726196f0508c320c643fddff7076657f6bca16d0ceeeeb languageName: node linkType: hard @@ -36275,11 +36494,11 @@ __metadata: linkType: hard "keyv@npm:*, keyv@npm:^5.2.1": - version: 5.3.4 - resolution: "keyv@npm:5.3.4" + version: 5.5.5 + resolution: "keyv@npm:5.5.5" dependencies: - "@keyv/serialize": "npm:^1.0.3" - checksum: 10/3e294eb1168af78ad3430d0cc47b6839fd3e70593238d35226a0a1e4094abe397ea378b7bce35cfcb314e55b5d1b4fcdae3c19bee5610e78d283b3cb5b279c8b + "@keyv/serialize": "npm:^1.1.1" + checksum: 10/4bbc2119151d67bfc04d3a08fc98f4efac5e171e8c99519fc7bc9ae9e05df4d1c6c835a5d133d563ed109a20db4688f3f9738400cbd3674f6303cdfc4490d429 languageName: node linkType: hard @@ -36372,32 +36591,28 @@ __metadata: linkType: hard "knip@npm:^5.42.0": - version: 5.42.2 - resolution: "knip@npm:5.42.2" + version: 5.71.0 + resolution: "knip@npm:5.71.0" dependencies: - "@nodelib/fs.walk": "npm:3.0.1" - "@snyk/github-codeowners": "npm:1.1.0" - easy-table: "npm:1.2.0" - enhanced-resolve: "npm:^5.18.0" + "@nodelib/fs.walk": "npm:^1.2.3" fast-glob: "npm:^3.3.3" - jiti: "npm:^2.4.2" - js-yaml: "npm:^4.1.0" + formatly: "npm:^0.3.0" + jiti: "npm:^2.6.0" + js-yaml: "npm:^4.1.1" minimist: "npm:^1.2.8" - picocolors: "npm:^1.1.0" + oxc-resolver: "npm:^11.13.2" + picocolors: "npm:^1.1.1" picomatch: "npm:^4.0.1" - pretty-ms: "npm:^9.0.0" - smol-toml: "npm:^1.3.1" - strip-json-comments: "npm:5.0.1" - summary: "npm:2.1.0" - zod: "npm:^3.22.4" - zod-validation-error: "npm:^3.0.3" + smol-toml: "npm:^1.5.2" + strip-json-comments: "npm:5.0.3" + zod: "npm:^4.1.11" peerDependencies: "@types/node": ">=18" - typescript: ">=5.0.4" + typescript: ">=5.0.4 <7" bin: knip: bin/knip.js knip-bun: bin/knip-bun.js - checksum: 10/1e540ad66e8e5cd2dfceb0c333ca46446300f4e40a51599ca6cd8de705bf0f928332ca108de28306ae7b54cc8fc1f66667135193baf32d4ccd30560797825935 + checksum: 10/68c1508be9db70865559f5ebc106f8a6aced8e4799949655e92a59fbb3f530c042087e50565cfdd698b619f69f584ee214cc7b315f3241d483d09e4fd200c45b languageName: node linkType: hard @@ -36450,14 +36665,14 @@ __metadata: linkType: hard "kubernetes-models@npm:^4.1.0, kubernetes-models@npm:^4.3.1": - version: 4.4.2 - resolution: "kubernetes-models@npm:4.4.2" + version: 4.5.1 + resolution: "kubernetes-models@npm:4.5.1" dependencies: - "@kubernetes-models/apimachinery": "npm:^2.0.2" + "@kubernetes-models/apimachinery": "npm:^2.2.0" "@kubernetes-models/base": "npm:^5.0.1" "@kubernetes-models/validate": "npm:^4.0.0" "@swc/helpers": "npm:^0.5.8" - checksum: 10/67956c3be831d02a0de3742809f1f8c89382eb11a9d66e7161f314413a1ddfce963513aa4eeba451a07a814b2f2afa959984a891f6e504e23e12825285a70a4e + checksum: 10/65a7b2064dcfbc719a80da7fd24b44775f68423170eb7abef3d4946604acdb5c8a3b2c8fded1d7212e2725b10ccf13abc94adf3091dc8005e25cd5321577ae92 languageName: node linkType: hard @@ -36513,15 +36728,15 @@ __metadata: linkType: hard "ldapts@npm:^8.0.6": - version: 8.0.16 - resolution: "ldapts@npm:8.0.16" + version: 8.0.25 + resolution: "ldapts@npm:8.0.25" dependencies: "@types/asn1": "npm:>=0.2.4" asn1: "npm:0.2.6" debug: "npm:4.4.3" strict-event-emitter-types: "npm:2.0.0" whatwg-url: "npm:15.1.0" - checksum: 10/06f4780f9fccdcfbb1610bb1cd119e3ac6bf6355c364ac0f8f287d43b9dc0ee82ad7347383864136a1c211d60b5a594787acae9fcf01fb4c9214879962b882a6 + checksum: 10/75fb390d5b4154b2d8c5da11e9d8123b1ae1bf50842a62a99309b90e96529939e2816c36f250dc6fb8e6f248e5da8012fe61522c058fe767f2429645649e51f5 languageName: node linkType: hard @@ -36593,92 +36808,102 @@ __metadata: languageName: node linkType: hard -"lightningcss-darwin-arm64@npm:1.30.1": - version: 1.30.1 - resolution: "lightningcss-darwin-arm64@npm:1.30.1" +"lightningcss-android-arm64@npm:1.30.2": + version: 1.30.2 + resolution: "lightningcss-android-arm64@npm:1.30.2" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"lightningcss-darwin-arm64@npm:1.30.2": + version: 1.30.2 + resolution: "lightningcss-darwin-arm64@npm:1.30.2" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"lightningcss-darwin-x64@npm:1.30.1": - version: 1.30.1 - resolution: "lightningcss-darwin-x64@npm:1.30.1" +"lightningcss-darwin-x64@npm:1.30.2": + version: 1.30.2 + resolution: "lightningcss-darwin-x64@npm:1.30.2" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"lightningcss-freebsd-x64@npm:1.30.1": - version: 1.30.1 - resolution: "lightningcss-freebsd-x64@npm:1.30.1" +"lightningcss-freebsd-x64@npm:1.30.2": + version: 1.30.2 + resolution: "lightningcss-freebsd-x64@npm:1.30.2" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"lightningcss-linux-arm-gnueabihf@npm:1.30.1": - version: 1.30.1 - resolution: "lightningcss-linux-arm-gnueabihf@npm:1.30.1" +"lightningcss-linux-arm-gnueabihf@npm:1.30.2": + version: 1.30.2 + resolution: "lightningcss-linux-arm-gnueabihf@npm:1.30.2" conditions: os=linux & cpu=arm languageName: node linkType: hard -"lightningcss-linux-arm64-gnu@npm:1.30.1": - version: 1.30.1 - resolution: "lightningcss-linux-arm64-gnu@npm:1.30.1" +"lightningcss-linux-arm64-gnu@npm:1.30.2": + version: 1.30.2 + resolution: "lightningcss-linux-arm64-gnu@npm:1.30.2" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"lightningcss-linux-arm64-musl@npm:1.30.1": - version: 1.30.1 - resolution: "lightningcss-linux-arm64-musl@npm:1.30.1" +"lightningcss-linux-arm64-musl@npm:1.30.2": + version: 1.30.2 + resolution: "lightningcss-linux-arm64-musl@npm:1.30.2" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"lightningcss-linux-x64-gnu@npm:1.30.1": - version: 1.30.1 - resolution: "lightningcss-linux-x64-gnu@npm:1.30.1" +"lightningcss-linux-x64-gnu@npm:1.30.2": + version: 1.30.2 + resolution: "lightningcss-linux-x64-gnu@npm:1.30.2" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"lightningcss-linux-x64-musl@npm:1.30.1": - version: 1.30.1 - resolution: "lightningcss-linux-x64-musl@npm:1.30.1" +"lightningcss-linux-x64-musl@npm:1.30.2": + version: 1.30.2 + resolution: "lightningcss-linux-x64-musl@npm:1.30.2" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"lightningcss-win32-arm64-msvc@npm:1.30.1": - version: 1.30.1 - resolution: "lightningcss-win32-arm64-msvc@npm:1.30.1" +"lightningcss-win32-arm64-msvc@npm:1.30.2": + version: 1.30.2 + resolution: "lightningcss-win32-arm64-msvc@npm:1.30.2" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"lightningcss-win32-x64-msvc@npm:1.30.1": - version: 1.30.1 - resolution: "lightningcss-win32-x64-msvc@npm:1.30.1" +"lightningcss-win32-x64-msvc@npm:1.30.2": + version: 1.30.2 + resolution: "lightningcss-win32-x64-msvc@npm:1.30.2" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "lightningcss@npm:^1.29.1": - version: 1.30.1 - resolution: "lightningcss@npm:1.30.1" + version: 1.30.2 + resolution: "lightningcss@npm:1.30.2" dependencies: detect-libc: "npm:^2.0.3" - lightningcss-darwin-arm64: "npm:1.30.1" - lightningcss-darwin-x64: "npm:1.30.1" - lightningcss-freebsd-x64: "npm:1.30.1" - lightningcss-linux-arm-gnueabihf: "npm:1.30.1" - lightningcss-linux-arm64-gnu: "npm:1.30.1" - lightningcss-linux-arm64-musl: "npm:1.30.1" - lightningcss-linux-x64-gnu: "npm:1.30.1" - lightningcss-linux-x64-musl: "npm:1.30.1" - lightningcss-win32-arm64-msvc: "npm:1.30.1" - lightningcss-win32-x64-msvc: "npm:1.30.1" + lightningcss-android-arm64: "npm:1.30.2" + lightningcss-darwin-arm64: "npm:1.30.2" + lightningcss-darwin-x64: "npm:1.30.2" + lightningcss-freebsd-x64: "npm:1.30.2" + lightningcss-linux-arm-gnueabihf: "npm:1.30.2" + lightningcss-linux-arm64-gnu: "npm:1.30.2" + lightningcss-linux-arm64-musl: "npm:1.30.2" + lightningcss-linux-x64-gnu: "npm:1.30.2" + lightningcss-linux-x64-musl: "npm:1.30.2" + lightningcss-win32-arm64-msvc: "npm:1.30.2" + lightningcss-win32-x64-msvc: "npm:1.30.2" dependenciesMeta: + lightningcss-android-arm64: + optional: true lightningcss-darwin-arm64: optional: true lightningcss-darwin-x64: @@ -36699,7 +36924,7 @@ __metadata: optional: true lightningcss-win32-x64-msvc: optional: true - checksum: 10/6c921135216cc498dfcb87e35dffe8432e99306cbd58009c598b1daf20c81cc14535abbd4c1066e5d1faf4080ed44a2995e8ecc343633db4897a2d041b76fb05 + checksum: 10/d6cc06d9bac295589a49446e9c45a241dfa16f4f81a7318c26cbc0be3e189003ec0da5d9a0fd9bdffc63a3ce05878cc7329277eaac77a826e8b68c73dc96cfda languageName: node linkType: hard @@ -36800,10 +37025,10 @@ __metadata: languageName: node linkType: hard -"load-esm@npm:1.0.2": - version: 1.0.2 - resolution: "load-esm@npm:1.0.2" - checksum: 10/1b4adb40c28c6fdbd4ca8c97942c04debddb3c93ae91413540ff5a21ca3511a651988c835cb80cad7288d1ecb869c4794b8a787ab02e09cc07ec951ad1eefcf9 +"load-esm@npm:1.0.3": + version: 1.0.3 + resolution: "load-esm@npm:1.0.3" + checksum: 10/6949e8c253dddccca2a0ded1e9e0bbbc81924439d99e3a7d0f946ba6cdcd16de22c3cef28d997fd950befda0826ca65c3f913d9ba893d50e9cfc0bbd9a2a1e90 languageName: node linkType: hard @@ -36892,15 +37117,6 @@ __metadata: languageName: node linkType: hard -"locate-path@npm:^7.2.0": - version: 7.2.0 - resolution: "locate-path@npm:7.2.0" - dependencies: - p-locate: "npm:^6.0.0" - checksum: 10/1c6d269d4efec555937081be964e8a9b4a136319c79ca1d45ac6382212a8466113c75bd89e44521ca8ecd1c47fb08523b56eee5c0712bc7d14fec5f729deeb42 - languageName: node - linkType: hard - "lodash-es@npm:^4.17.21": version: 4.17.21 resolution: "lodash-es@npm:4.17.21" @@ -37027,20 +37243,6 @@ __metadata: languageName: node linkType: hard -"lodash.hasin@npm:^4.5.2": - version: 4.5.2 - resolution: "lodash.hasin@npm:4.5.2" - checksum: 10/d491be2eb53bcd004ac7eeefdc072fe6b76c701088bf95e8ca406a0b00e45739507ca6ffbce3829bdc9bc13e034877a2bbc08229e3f24d4095c3aa75f927d96a - languageName: node - linkType: hard - -"lodash.head@npm:^4.0.1": - version: 4.0.1 - resolution: "lodash.head@npm:4.0.1" - checksum: 10/37666c4f96ad907025754a0e76db49adab148bd2d1a1f4597c4bf7a006d4daad802453e162dffe08d2a488c1283a29f5366c1fc3a1bd2300423c32b0ecb26156 - languageName: node - linkType: hard - "lodash.isarguments@npm:^3.1.0": version: 3.1.0 resolution: "lodash.isarguments@npm:3.1.0" @@ -37069,20 +37271,6 @@ __metadata: languageName: node linkType: hard -"lodash.isnil@npm:^4.0.0": - version: 4.0.0 - resolution: "lodash.isnil@npm:4.0.0" - checksum: 10/ebf8df69879badd6ad99c4f64c54c470248df5cf92b208ca730861b1d8ac058da7b632ac811d18b0929d93cbac8d8fc866e781ee816b0142c56952e85edc682f - languageName: node - linkType: hard - -"lodash.isobject@npm:^3.0.2": - version: 3.0.2 - resolution: "lodash.isobject@npm:3.0.2" - checksum: 10/6c1667cbc4494d0a13a3617a4b23278d6d02dac520311f2bbb43f16f2cf71d2e6eb9dec8057315b77459df4890c756a256a087d3f4baa44a79ab5d6c968b060e - languageName: node - linkType: hard - "lodash.isstring@npm:^4.0.1": version: 4.0.1 resolution: "lodash.isstring@npm:4.0.1" @@ -37292,7 +37480,7 @@ __metadata: languageName: node linkType: hard -"logform@npm:^2.3.2, logform@npm:^2.6.0, logform@npm:^2.7.0": +"logform@npm:^2.3.2, logform@npm:^2.7.0": version: 2.7.0 resolution: "logform@npm:2.7.0" dependencies: @@ -37392,17 +37580,17 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^10.0.0, lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": +"lru-cache@npm:^10.0.0, lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0, lru-cache@npm:^10.4.3": version: 10.4.3 resolution: "lru-cache@npm:10.4.3" checksum: 10/e6e90267360476720fa8e83cc168aa2bf0311f3f2eea20a6ba78b90a885ae72071d9db132f40fda4129c803e7dcec3a6b6a6fbb44ca90b081630b810b5d6a41a languageName: node linkType: hard -"lru-cache@npm:^11.0.0": - version: 11.0.2 - resolution: "lru-cache@npm:11.0.2" - checksum: 10/25fcb66e9d91eaf17227c6abfe526a7bed5903de74f93bfde380eb8a13410c5e8d3f14fe447293f3f322a7493adf6f9f015c6f1df7a235ff24ec30f366e1c058 +"lru-cache@npm:^11.0.0, lru-cache@npm:^11.2.2, lru-cache@npm:^11.2.4": + version: 11.2.4 + resolution: "lru-cache@npm:11.2.4" + checksum: 10/3b2da74c0b6653767f8164c38c4c4f4d7f0cc10c62bfa512663d94a830191ae6a5af742a8d88a8b30d5f9974652d3adae53931f32069139ad24fa2a18a199aca languageName: node linkType: hard @@ -37461,7 +37649,14 @@ __metadata: languageName: node linkType: hard -"luxon@npm:^3.0.0, luxon@npm:^3.2.1, luxon@npm:^3.4.3, luxon@npm:^3.5.0, luxon@npm:~3.5.0": +"luxon@npm:^3.0.0, luxon@npm:^3.2.1, luxon@npm:^3.4.3, luxon@npm:^3.5.0": + version: 3.7.2 + resolution: "luxon@npm:3.7.2" + checksum: 10/b24cd205ed306ce7415991687897dcc4027921ae413c9116590bc33a95f93b86ce52cf74ba72b4f5c5ab1c10090517f54ac8edfb127c049e0bf55b90dc2260be + languageName: node + linkType: hard + +"luxon@npm:~3.5.0": version: 3.5.0 resolution: "luxon@npm:3.5.0" checksum: 10/48f86e6c1c96815139f8559456a3354a276ba79bcef0ae0d4f2172f7652f3ba2be2237b0e103b8ea0b79b47715354ac9fac04eb1db3485dcc72d5110491dd47f @@ -37513,7 +37708,7 @@ __metadata: languageName: node linkType: hard -"magic-string@npm:^0.30.0, magic-string@npm:^0.30.10, magic-string@npm:^0.30.17, magic-string@npm:^0.30.3": +"magic-string@npm:^0.30.0, magic-string@npm:^0.30.17, magic-string@npm:^0.30.21, magic-string@npm:^0.30.3": version: 0.30.21 resolution: "magic-string@npm:0.30.21" dependencies: @@ -37936,6 +38131,13 @@ __metadata: languageName: node linkType: hard +"mdn-data@npm:2.12.2": + version: 2.12.2 + resolution: "mdn-data@npm:2.12.2" + checksum: 10/854e41715a9358e69f9a530117cd6ca7e71d06176469de8d70b1e629753b6827f5bd730995c16ad3750f3c9bad92230f8e4e178de2b34926b05f5205d27d76af + languageName: node + linkType: hard + "mdurl@npm:^1.0.0, mdurl@npm:^1.0.1": version: 1.0.1 resolution: "mdurl@npm:1.0.1" @@ -38018,7 +38220,7 @@ __metadata: languageName: node linkType: hard -"memfs@npm:^4.28.0, memfs@npm:^4.6.0": +"memfs@npm:^4.51.1, memfs@npm:^4.6.0": version: 4.51.1 resolution: "memfs@npm:4.51.1" dependencies: @@ -38117,8 +38319,8 @@ __metadata: linkType: hard "micromark-core-commonmark@npm:^1.0.0, micromark-core-commonmark@npm:^1.0.1": - version: 1.0.6 - resolution: "micromark-core-commonmark@npm:1.0.6" + version: 1.1.0 + resolution: "micromark-core-commonmark@npm:1.1.0" dependencies: decode-named-character-reference: "npm:^1.0.0" micromark-factory-destination: "npm:^1.0.0" @@ -38136,25 +38338,25 @@ __metadata: micromark-util-symbol: "npm:^1.0.0" micromark-util-types: "npm:^1.0.1" uvu: "npm:^0.5.0" - checksum: 10/20daa4b78b88afea7658c2bd428c830734c72fbb2184c1f0761bb4c1e5fcf266509e7d46ad5f7b2a2aeb32cd17951788733cad458632457b52397534d930030a + checksum: 10/a73694d223ac8baad8ff00597a3c39d61f5b32bfd56fe4bcf295d75b2a4e8e67fb2edbfc7cc287b362b9d7f6d24fce08b6a7e8b5b155d79bcc1e4d9b2756ffb2 languageName: node linkType: hard "micromark-extension-gfm-autolink-literal@npm:^1.0.0": - version: 1.0.0 - resolution: "micromark-extension-gfm-autolink-literal@npm:1.0.0" + version: 1.0.5 + resolution: "micromark-extension-gfm-autolink-literal@npm:1.0.5" dependencies: micromark-util-character: "npm:^1.0.0" micromark-util-sanitize-uri: "npm:^1.0.0" micromark-util-symbol: "npm:^1.0.0" micromark-util-types: "npm:^1.0.0" - checksum: 10/4bb5841980725bbbe59b311b5b5efbab74b363da00669b96e7744ea76532d972720d1ce92a024baeafbac2c92dbf90b5595a18212415a59ced7610202304ce13 + checksum: 10/1e0ccc758baef3cd0478ba84ff86fa1ec2b389042421c7cade9485b775456c1a9c3bd797393002b2c6f6abd9bdf829cb114874557bbcb8e43d16d06a464811c0 languageName: node linkType: hard "micromark-extension-gfm-footnote@npm:^1.0.0": - version: 1.0.3 - resolution: "micromark-extension-gfm-footnote@npm:1.0.3" + version: 1.1.2 + resolution: "micromark-extension-gfm-footnote@npm:1.1.2" dependencies: micromark-core-commonmark: "npm:^1.0.0" micromark-factory-space: "npm:^1.0.0" @@ -38162,60 +38364,64 @@ __metadata: micromark-util-normalize-identifier: "npm:^1.0.0" micromark-util-sanitize-uri: "npm:^1.0.0" micromark-util-symbol: "npm:^1.0.0" + micromark-util-types: "npm:^1.0.0" uvu: "npm:^0.5.0" - checksum: 10/1e8920582a2d365eebe48239daaeade3b88d7f6b800f1dd7e7b0d6add730105048d7d1fd68138955b397d572d410c280345560e407328c07fa334e17a965a578 + checksum: 10/8777073fb76d2fd01f6b2405106af6c349c1e25660c4d37cadcc61c187d71c8444870f73cefaaa67f12884d5e45c78ee3c5583561a0b330bd91c6d997113584a languageName: node linkType: hard "micromark-extension-gfm-strikethrough@npm:^1.0.0": - version: 1.0.1 - resolution: "micromark-extension-gfm-strikethrough@npm:1.0.1" + version: 1.0.7 + resolution: "micromark-extension-gfm-strikethrough@npm:1.0.7" dependencies: micromark-util-chunked: "npm:^1.0.0" micromark-util-classify-character: "npm:^1.0.0" micromark-util-resolve-all: "npm:^1.0.0" micromark-util-symbol: "npm:^1.0.0" micromark-util-types: "npm:^1.0.0" - checksum: 10/720aa4e47ac4701faf5640be40a97a249b880d5f8f2787106a0d12bd11dd8ab9e29a513af738743be07d42a02734e024184114b719435160e012c4ba9f7464bd + uvu: "npm:^0.5.0" + checksum: 10/8411ef1aa5dc83f662e8b45b085f70ddff29deb3c4259269e8a1ff656397abb755d8ea841a14be23e8585a31d3c0a5de1bd2c05f3453b66670e499d4a0004f5e languageName: node linkType: hard "micromark-extension-gfm-table@npm:^1.0.0": - version: 1.0.0 - resolution: "micromark-extension-gfm-table@npm:1.0.0" + version: 1.0.7 + resolution: "micromark-extension-gfm-table@npm:1.0.7" dependencies: micromark-factory-space: "npm:^1.0.0" micromark-util-character: "npm:^1.0.0" micromark-util-symbol: "npm:^1.0.0" micromark-util-types: "npm:^1.0.0" - checksum: 10/220e2d5c66e4dcd8565cc067d584136fc91dbf249bcee69c6a6cb5656b536144d29734d922602bdfd82242dad2a3d128b25f57e93c50091fd96d7071618eedd9 + uvu: "npm:^0.5.0" + checksum: 10/f05d86a099c941a2a309d60bf4839d16a00a93cb880cda4ab8faeb831647763fff6e03197ec15b80e1f195002afcca6afe2b95c3622b049b82d7ff8ef1c1c776 languageName: node linkType: hard "micromark-extension-gfm-tagfilter@npm:^1.0.0": - version: 1.0.0 - resolution: "micromark-extension-gfm-tagfilter@npm:1.0.0" + version: 1.0.2 + resolution: "micromark-extension-gfm-tagfilter@npm:1.0.2" dependencies: micromark-util-types: "npm:^1.0.0" - checksum: 10/2950168c4329486da0d411afebae47601dbbdb8ba51892d88ef451dd62e4d412afaba267f1e4a1d0c93b1b25723cfcdcbb013c458f652e8ab2a1046dd1b5c352 + checksum: 10/55c7d9019d6a39efaaed2c2e40b0aaa137d2c4f9c94cac82e93f509a806c3a775e4c815b5d8e986617450b68861a19776e4b886307e83db452b393f15a837b39 languageName: node linkType: hard "micromark-extension-gfm-task-list-item@npm:^1.0.0": - version: 1.0.0 - resolution: "micromark-extension-gfm-task-list-item@npm:1.0.0" + version: 1.0.5 + resolution: "micromark-extension-gfm-task-list-item@npm:1.0.5" dependencies: micromark-factory-space: "npm:^1.0.0" micromark-util-character: "npm:^1.0.0" micromark-util-symbol: "npm:^1.0.0" micromark-util-types: "npm:^1.0.0" - checksum: 10/a8bc41ce4c5599cde45804737381ca5136b43c64c05034e396e476958232916d3bc23e585d3f71c59f03666c568bced41f177a76497267259b813ab4987dd3a5 + uvu: "npm:^0.5.0" + checksum: 10/46bb1baa10bfb785a2e3e2f975e5509260b9995d5c3aeddf77051957d218ce1af4ea737bcb6a56a930e62d42b05307b20632a400eff25cdb290789ff3170cad5 languageName: node linkType: hard "micromark-extension-gfm@npm:^2.0.0": - version: 2.0.1 - resolution: "micromark-extension-gfm@npm:2.0.1" + version: 2.0.3 + resolution: "micromark-extension-gfm@npm:2.0.3" dependencies: micromark-extension-gfm-autolink-literal: "npm:^1.0.0" micromark-extension-gfm-footnote: "npm:^1.0.0" @@ -38225,200 +38431,204 @@ __metadata: micromark-extension-gfm-task-list-item: "npm:^1.0.0" micromark-util-combine-extensions: "npm:^1.0.0" micromark-util-types: "npm:^1.0.0" - checksum: 10/701d065102685a338c7eb87520587575dffbc240639a379c64f83971b3ffbeaf0165aa43ce72b0255856e991b395a5fc71dc436ec76d723f462a39ec16eade5e + checksum: 10/3ffd06ced4314abd0f0c72ec227f034f38dd47facbb62439ef3216d42f32433f3901d14675cf806e8d73689802a11849958b330bb5b55dd4fd5cdc64ebaf345c languageName: node linkType: hard "micromark-factory-destination@npm:^1.0.0": - version: 1.0.0 - resolution: "micromark-factory-destination@npm:1.0.0" + version: 1.1.0 + resolution: "micromark-factory-destination@npm:1.1.0" dependencies: micromark-util-character: "npm:^1.0.0" micromark-util-symbol: "npm:^1.0.0" micromark-util-types: "npm:^1.0.0" - checksum: 10/8e733ae9c1c2342f14ff290bf09946e20f6f540117d80342377a765cac48df2ea5e748f33c8b07501ad7a43414b1a6597c8510ede2052b6bf1251fab89748e20 + checksum: 10/9e2b5fb5fedbf622b687e20d51eb3d56ae90c0e7ecc19b37bd5285ec392c1e56f6e21aa7cfcb3c01eda88df88fe528f3acb91a5f57d7f4cba310bc3cd7f824fa languageName: node linkType: hard "micromark-factory-label@npm:^1.0.0": - version: 1.0.0 - resolution: "micromark-factory-label@npm:1.0.0" + version: 1.1.0 + resolution: "micromark-factory-label@npm:1.1.0" dependencies: micromark-util-character: "npm:^1.0.0" micromark-util-symbol: "npm:^1.0.0" micromark-util-types: "npm:^1.0.0" - checksum: 10/37f34d8e42e3a606a636419ffe0f99fd7f6054778365aac56d1cc11585d1cd46000dbf938319abb2ea5e245803679d3cfa46afb5aecf2702bfd963113481f14c + uvu: "npm:^0.5.0" + checksum: 10/fcda48f1287d9b148c562c627418a2ab759cdeae9c8e017910a0cba94bb759a96611e1fc6df33182e97d28fbf191475237298983bb89ef07d5b02464b1ad28d5 languageName: node linkType: hard "micromark-factory-space@npm:^1.0.0": - version: 1.0.0 - resolution: "micromark-factory-space@npm:1.0.0" + version: 1.1.0 + resolution: "micromark-factory-space@npm:1.1.0" dependencies: micromark-util-character: "npm:^1.0.0" micromark-util-types: "npm:^1.0.0" - checksum: 10/70d3aafde4e68ef4e509a3b644e9a29e4aada00801279e346577b008cbca06d78051bcd62aa7ea7425856ed73f09abd2b36607803055f726f52607ee7cb706b0 + checksum: 10/b58435076b998a7e244259a4694eb83c78915581206b6e7fc07b34c6abd36a1726ade63df8972fbf6c8fa38eecb9074f4e17be8d53f942e3b3d23d1a0ecaa941 languageName: node linkType: hard "micromark-factory-title@npm:^1.0.0": - version: 1.0.0 - resolution: "micromark-factory-title@npm:1.0.0" + version: 1.1.0 + resolution: "micromark-factory-title@npm:1.1.0" dependencies: micromark-factory-space: "npm:^1.0.0" micromark-util-character: "npm:^1.0.0" micromark-util-symbol: "npm:^1.0.0" micromark-util-types: "npm:^1.0.0" - checksum: 10/d9bf0779c49f013fea5fc5daadcee91e1703c81c1b5091337e806c24f1ea224d69f534d174aba2eccff7826620af71bb3db83b1caf14cbb89bea53f4e8e38bc3 + checksum: 10/4432d3dbc828c81f483c5901b0c6591a85d65a9e33f7d96ba7c3ae821617a0b3237ff5faf53a9152d00aaf9afb3a9f185b205590f40ed754f1d9232e0e9157b1 languageName: node linkType: hard "micromark-factory-whitespace@npm:^1.0.0": - version: 1.0.0 - resolution: "micromark-factory-whitespace@npm:1.0.0" + version: 1.1.0 + resolution: "micromark-factory-whitespace@npm:1.1.0" dependencies: micromark-factory-space: "npm:^1.0.0" micromark-util-character: "npm:^1.0.0" micromark-util-symbol: "npm:^1.0.0" micromark-util-types: "npm:^1.0.0" - checksum: 10/0888386e6ea2dd665a5182c570d9b3d0a172d3f11694ca5a2a84e552149c9f1429f5b975ec26e1f0fa4388c55a656c9f359ce5e0603aff6175ba3e255076f20b + checksum: 10/ef0fa682c7d593d85a514ee329809dee27d10bc2a2b65217d8ef81173e33b8e83c549049764b1ad851adfe0a204dec5450d9d20a4ca8598f6c94533a73f73fcd languageName: node linkType: hard "micromark-util-character@npm:^1.0.0": - version: 1.1.0 - resolution: "micromark-util-character@npm:1.1.0" + version: 1.2.0 + resolution: "micromark-util-character@npm:1.2.0" dependencies: micromark-util-symbol: "npm:^1.0.0" micromark-util-types: "npm:^1.0.0" - checksum: 10/81a1e4ee996e89966f58620088ca1ad49a6b1474fa488992be9b6f62d783d621c33f74c01f8560a2960412a43e83c7d991c711620ff3ee49169eb77de0bb2e3a + checksum: 10/88cf80f9b4c95266f24814ef587fb4180454668dcc3be4ac829e1227188cf349c8981bfca29e3eab1682f324c2c47544c0b0b799a26fbf9df5f156c6a84c970c languageName: node linkType: hard "micromark-util-chunked@npm:^1.0.0": - version: 1.0.0 - resolution: "micromark-util-chunked@npm:1.0.0" + version: 1.1.0 + resolution: "micromark-util-chunked@npm:1.1.0" dependencies: micromark-util-symbol: "npm:^1.0.0" - checksum: 10/c1efd56e8c4217bcf1c6f1a9fb9912b4a2a5503b00d031da902be922fb3fee60409ac53f11739991291357b2784fb0647ddfc74c94753a068646c0cb0fd71421 + checksum: 10/c435bde9110cb595e3c61b7f54c2dc28ee03e6a57fa0fc1e67e498ad8bac61ee5a7457a2b6a73022ddc585676ede4b912d28dcf57eb3bd6951e54015e14dc20b languageName: node linkType: hard "micromark-util-classify-character@npm:^1.0.0": - version: 1.0.0 - resolution: "micromark-util-classify-character@npm:1.0.0" + version: 1.1.0 + resolution: "micromark-util-classify-character@npm:1.1.0" dependencies: micromark-util-character: "npm:^1.0.0" micromark-util-symbol: "npm:^1.0.0" micromark-util-types: "npm:^1.0.0" - checksum: 10/180446e6a1dec653f625ded028f244784e1db8d10ad05c5d70f08af9de393b4a03dc6cf6fa5ed8ccc9c24bbece7837abf3bf66681c0b4adf159364b7d5236dfd + checksum: 10/8499cb0bb1f7fb946f5896285fcca65cd742f66cd3e79ba7744792bd413ec46834f932a286de650349914d02e822946df3b55d03e6a8e1d245d1ddbd5102e5b0 languageName: node linkType: hard "micromark-util-combine-extensions@npm:^1.0.0": - version: 1.0.0 - resolution: "micromark-util-combine-extensions@npm:1.0.0" + version: 1.1.0 + resolution: "micromark-util-combine-extensions@npm:1.1.0" dependencies: micromark-util-chunked: "npm:^1.0.0" micromark-util-types: "npm:^1.0.0" - checksum: 10/5304a820ef75340e1be69d6ad167055b6ba9a3bafe8171e5945a935752f462415a9dd61eb3490220c055a8a11167209a45bfa73f278338b7d3d61fa1464d3f35 + checksum: 10/ee78464f5d4b61ccb437850cd2d7da4d690b260bca4ca7a79c4bb70291b84f83988159e373b167181b6716cb197e309bc6e6c96a68cc3ba9d50c13652774aba9 languageName: node linkType: hard "micromark-util-decode-numeric-character-reference@npm:^1.0.0": - version: 1.0.0 - resolution: "micromark-util-decode-numeric-character-reference@npm:1.0.0" + version: 1.1.0 + resolution: "micromark-util-decode-numeric-character-reference@npm:1.1.0" dependencies: micromark-util-symbol: "npm:^1.0.0" - checksum: 10/f3ae2bb582a80f1e9d3face026f585c0c472335c064bd850bde152376f0394cb2831746749b6be6e0160f7d73626f67d10716026c04c87f402c0dd45a1a28633 + checksum: 10/4733fe75146e37611243f055fc6847137b66f0cde74d080e33bd26d0408c1d6f44cabc984063eee5968b133cb46855e729d555b9ff8d744652262b7b51feec73 languageName: node linkType: hard "micromark-util-decode-string@npm:^1.0.0": - version: 1.0.0 - resolution: "micromark-util-decode-string@npm:1.0.0" + version: 1.1.0 + resolution: "micromark-util-decode-string@npm:1.1.0" dependencies: + decode-named-character-reference: "npm:^1.0.0" micromark-util-character: "npm:^1.0.0" micromark-util-decode-numeric-character-reference: "npm:^1.0.0" - parse-entities: "npm:^3.0.0" - checksum: 10/9c7e6e3950e675f39058935e065e8774a1ef26a0d386eb45abd96fb8c0312c8a72464c672f41a3c7668974ac2a7cb2ad23b84eee3775b0bd4c47947d9fc64888 + micromark-util-symbol: "npm:^1.0.0" + checksum: 10/f1625155db452f15aa472918499689ba086b9c49d1322a08b22bfbcabe918c61b230a3002c8bc3ea9b1f52ca7a9bb1c3dd43ccb548c7f5f8b16c24a1ae77a813 languageName: node linkType: hard "micromark-util-encode@npm:^1.0.0": - version: 1.0.0 - resolution: "micromark-util-encode@npm:1.0.0" - checksum: 10/16985a6b355721307553d1893da364e83144ef068f84978071a9b4b3d884b65c3138f8330fb039aac10f75766b4906e03c5e62baafb1bf5e731f959878277712 + version: 1.1.0 + resolution: "micromark-util-encode@npm:1.1.0" + checksum: 10/4ef29d02b12336918cea6782fa87c8c578c67463925221d4e42183a706bde07f4b8b5f9a5e1c7ce8c73bb5a98b261acd3238fecd152e6dd1cdfa2d1ae11b60a0 languageName: node linkType: hard "micromark-util-html-tag-name@npm:^1.0.0": - version: 1.0.0 - resolution: "micromark-util-html-tag-name@npm:1.0.0" - checksum: 10/ed07ce9b9bb30cc4ea57f733089b3a253a6132c0608ccfc105eadb32f1f80bbd2347bf8a74f897fe039d7805a59f602fd4dd15f6adc7926d40b3646da2888d0f + version: 1.2.0 + resolution: "micromark-util-html-tag-name@npm:1.2.0" + checksum: 10/ccf0fa99b5c58676dc5192c74665a3bfd1b536fafaf94723bd7f31f96979d589992df6fcf2862eba290ef18e6a8efb30ec8e1e910d9f3fc74f208871e9f84750 languageName: node linkType: hard "micromark-util-normalize-identifier@npm:^1.0.0": - version: 1.0.0 - resolution: "micromark-util-normalize-identifier@npm:1.0.0" + version: 1.1.0 + resolution: "micromark-util-normalize-identifier@npm:1.1.0" dependencies: micromark-util-symbol: "npm:^1.0.0" - checksum: 10/d7c09d5e8318fb72f194af72664bd84a48a2928e3550b2b21c8fbc0ec22524f2a72e0f6663d2b95dc189a6957d3d7759b60716e888909710767cd557be821f8b + checksum: 10/8655bea41ffa4333e03fc22462cb42d631bbef9c3c07b625fd852b7eb442a110f9d2e5902a42e65188d85498279569502bf92f3434a1180fc06f7c37edfbaee2 languageName: node linkType: hard "micromark-util-resolve-all@npm:^1.0.0": - version: 1.0.0 - resolution: "micromark-util-resolve-all@npm:1.0.0" + version: 1.1.0 + resolution: "micromark-util-resolve-all@npm:1.1.0" dependencies: micromark-util-types: "npm:^1.0.0" - checksum: 10/409667f2bd126ef8acce009270d2aecaaa5584c5807672bc657b09e50aa91bd2e552cf41e5be1e6469244a83349cbb71daf6059b746b1c44e3f35446fef63e50 + checksum: 10/1ce6c0237cd3ca061e76fae6602cf95014e764a91be1b9f10d36cb0f21ca88f9a07de8d49ab8101efd0b140a4fbfda6a1efb72027ab3f4d5b54c9543271dc52c languageName: node linkType: hard "micromark-util-sanitize-uri@npm:^1.0.0": - version: 1.0.0 - resolution: "micromark-util-sanitize-uri@npm:1.0.0" + version: 1.2.0 + resolution: "micromark-util-sanitize-uri@npm:1.2.0" dependencies: micromark-util-character: "npm:^1.0.0" micromark-util-encode: "npm:^1.0.0" micromark-util-symbol: "npm:^1.0.0" - checksum: 10/198e91b9f86d429ebc74737c0378764c8dc2e988f46a6846f59223938bc9f3a5d4ae97ce9ce801ac6f3a76cce3da1196cbb3d5ba13bb4cce53026b06891a61da + checksum: 10/0d024100d95ffb88bf75f3360e305b545c1eb745430959b8633f7aa93f37ec401fc7094c90c97298409a9e30d94d53b895bae224e1bb966bea114976cfa0fd48 languageName: node linkType: hard "micromark-util-subtokenize@npm:^1.0.0": - version: 1.0.0 - resolution: "micromark-util-subtokenize@npm:1.0.0" + version: 1.1.0 + resolution: "micromark-util-subtokenize@npm:1.1.0" dependencies: micromark-util-chunked: "npm:^1.0.0" micromark-util-symbol: "npm:^1.0.0" micromark-util-types: "npm:^1.0.0" - checksum: 10/0b19352a05c958c38782be7be6ca1c5ce004f24b4d5fdb70666d2dfa4c75d859a0fc44ef3e899ad085fe3022b0cd1201748f96b5617d09e43ea455ba2e2d0f9a + uvu: "npm:^0.5.0" + checksum: 10/075a1db6ea586d65827d3eead33dbfc520c4e43659c93fcd8fd82f44a7b75cfe61dcde967a3dfcc2ffd999347440ba5aa6698e65a04f3fc627e13e9f12a1a910 languageName: node linkType: hard "micromark-util-symbol@npm:^1.0.0": - version: 1.0.0 - resolution: "micromark-util-symbol@npm:1.0.0" - checksum: 10/93945fd4863bcf9e4186ee6f234a1ef790f884e927287aed6741d41d37dae4c0783d36f3f811e94e1634ea86c6bb484b6d2691d5e87a471aee32500cb1a4c136 + version: 1.1.0 + resolution: "micromark-util-symbol@npm:1.1.0" + checksum: 10/a26b6b1efd77a715a4d9bbe0a5338eaf3d04ea5e85733e34fee56dfeabf64495c0afc5438fe5220316884cd3a5eae1f17768e0ff4e117827ea4a653897466f86 languageName: node linkType: hard "micromark-util-types@npm:^1.0.0, micromark-util-types@npm:^1.0.1": - version: 1.0.1 - resolution: "micromark-util-types@npm:1.0.1" - checksum: 10/cc270381bb1035e610592d76a9889ec7d2d8f613bd6c2cbbfc09cae8232602af132ca4d2a5d498b0f9e30db6bc33e0320bb7386ee2abc7267d6a1c25dadcbd85 + version: 1.1.0 + resolution: "micromark-util-types@npm:1.1.0" + checksum: 10/287ac5de4a3802bb6f6c3842197c294997a488db1c0486e03c7a8e674d9eb7720c17dda1bcb814814b8343b338c4826fcbc0555f3e75463712a60dcdb53a028e languageName: node linkType: hard "micromark@npm:^3.0.0": - version: 3.0.5 - resolution: "micromark@npm:3.0.5" + version: 3.2.0 + resolution: "micromark@npm:3.2.0" dependencies: "@types/debug": "npm:^4.0.0" debug: "npm:^4.0.0" + decode-named-character-reference: "npm:^1.0.0" micromark-core-commonmark: "npm:^1.0.1" micromark-factory-space: "npm:^1.0.0" micromark-util-character: "npm:^1.0.0" @@ -38432,12 +38642,12 @@ __metadata: micromark-util-subtokenize: "npm:^1.0.0" micromark-util-symbol: "npm:^1.0.0" micromark-util-types: "npm:^1.0.1" - parse-entities: "npm:^3.0.0" - checksum: 10/cb6c259849562f69f901150f37343ed7f952b75d01a3f0c312b5a0fe58c5f3304067c66be5dcf4a781a4da51073a631c2db095d3647f5d6d7895b44f181197b5 + uvu: "npm:^0.5.0" + checksum: 10/560a4a501efc3859d622461aaa9345fb95b99a2f34d3d3f2a775ab04de1dd857cb0f642083a6b28ab01bd817f5f0741a1be9857fd702f45e04a3752927a66719 languageName: node linkType: hard -"micromatch@npm:^4.0.2, micromatch@npm:^4.0.4, micromatch@npm:^4.0.5, micromatch@npm:^4.0.7, micromatch@npm:^4.0.8": +"micromatch@npm:^4.0.2, micromatch@npm:^4.0.5, micromatch@npm:^4.0.7, micromatch@npm:^4.0.8": version: 4.0.8 resolution: "micromatch@npm:4.0.8" dependencies: @@ -38600,14 +38810,14 @@ __metadata: linkType: hard "mini-css-extract-plugin@npm:^2.4.2, mini-css-extract-plugin@npm:^2.9.2": - version: 2.9.3 - resolution: "mini-css-extract-plugin@npm:2.9.3" + version: 2.9.4 + resolution: "mini-css-extract-plugin@npm:2.9.4" dependencies: schema-utils: "npm:^4.0.0" tapable: "npm:^2.2.1" peerDependencies: webpack: ^5.0.0 - checksum: 10/55bcc341af9e472c3b8010aa1a8a0212aef78eb8a76d07e3f9d5646b357af03ab4cae0dabfb03be8e0476064f36ab415be2fa65682b6acdb420805c67cdee4c6 + checksum: 10/24a0418dc49baed58a10a8b81e4d2fe474e89ccdc9370a7c69bd0aeeb5a70d2b4ee12f33b98c95a68423c79c1de7cc2a25aaa2105600b712e7d594cb0d56c9d4 languageName: node linkType: hard @@ -38661,7 +38871,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^10.0.3, minimatch@npm:^10.1.1": +"minimatch@npm:^10.1.1": version: 10.1.1 resolution: "minimatch@npm:10.1.1" dependencies: @@ -38982,8 +39192,8 @@ __metadata: linkType: hard "mockttp@npm:^3.13.0": - version: 3.15.5 - resolution: "mockttp@npm:3.15.5" + version: 3.17.1 + resolution: "mockttp@npm:3.17.1" dependencies: "@graphql-tools/schema": "npm:^8.5.0" "@graphql-tools/utils": "npm:^8.8.0" @@ -39001,7 +39211,7 @@ __metadata: cors: "npm:^2.8.4" cors-gate: "npm:^1.1.3" cross-fetch: "npm:^3.1.5" - destroyable-server: "npm:^1.0.2" + destroyable-server: "npm:^1.1.1" express: "npm:^4.14.0" fast-json-patch: "npm:^3.1.1" graphql: "npm:^14.0.2 || ^15.5" @@ -39020,7 +39230,7 @@ __metadata: parse-multipart-data: "npm:^1.4.0" performance-now: "npm:^2.1.0" portfinder: "npm:^1.0.32" - read-tls-client-hello: "npm:^1.0.0" + read-tls-client-hello: "npm:^1.1.0" semver: "npm:^7.5.3" socks-proxy-agent: "npm:^7.0.0" typed-error: "npm:^3.0.2" @@ -39029,7 +39239,7 @@ __metadata: ws: "npm:^8.8.0" bin: mockttp: dist/admin/admin-bin.js - checksum: 10/93eca69baa35db11ae7f541d712bfd208edf0017db3091e874f59fc64a7c036179906b4e9b66936f054ad1c258645d085452dafab58a1c2df9fd6d67330f8328 + checksum: 10/09278221361b9896636bbf9e6a6d6427afe2375c035dcc6ddd56d308a7b197ae3a5196fba7b00b9fb1bfb0b4c22daacc046bdc207e0ab9ef15bb2a79637cdfbf languageName: node linkType: hard @@ -39231,19 +39441,19 @@ __metadata: linkType: hard "mysql2@npm:^3.0.0": - version: 3.11.5 - resolution: "mysql2@npm:3.11.5" + version: 3.15.3 + resolution: "mysql2@npm:3.15.3" dependencies: aws-ssl-profiles: "npm:^1.1.1" denque: "npm:^2.1.0" generate-function: "npm:^2.3.1" - iconv-lite: "npm:^0.6.3" + iconv-lite: "npm:^0.7.0" long: "npm:^5.2.1" lru.min: "npm:^1.0.0" named-placeholders: "npm:^1.1.3" seq-queue: "npm:^0.0.5" sqlstring: "npm:^2.3.2" - checksum: 10/912dc364f6f9684721add5474c732f5d7c2403ec17cb05b06f95adafab3cb32daa2798b283d48d0951d11af94a58558581ed22635803fc6baab651d3651c1cc9 + checksum: 10/96fbab423afb05a9ac397c272aa1097872797e224b7d1785ac05b7e46d0884c1e613ad9e2c3082ad7973f229357f9ab5824a7f90e8c582b2094ce52027fff8e3 languageName: node linkType: hard @@ -39311,6 +39521,15 @@ __metadata: languageName: node linkType: hard +"napi-postinstall@npm:^0.3.0": + version: 0.3.4 + resolution: "napi-postinstall@npm:0.3.4" + bin: + napi-postinstall: lib/cli.js + checksum: 10/5541381508f9e1051ff3518701c7130ebac779abb3a1ffe9391fcc3cab4cc0569b0ba0952357db3f6b12909c3bb508359a7a60261ffd795feebbdab967175832 + languageName: node + linkType: hard + "native-duplexpair@npm:^1.0.0": version: 1.0.0 resolution: "native-duplexpair@npm:1.0.0" @@ -39529,7 +39748,7 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:^2.6.0, node-fetch@npm:^2.6.1, node-fetch@npm:^2.6.12, node-fetch@npm:^2.6.7, node-fetch@npm:^2.6.9, node-fetch@npm:^2.7.0": +"node-fetch@npm:^2.6.0, node-fetch@npm:^2.6.1, 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" dependencies: @@ -39788,15 +40007,15 @@ __metadata: linkType: hard "nodemailer@npm:^7.0.7": - version: 7.0.9 - resolution: "nodemailer@npm:7.0.9" - checksum: 10/88883c58afe356d2b4c24b1e976c04857e8a7a7145e1752dab69072900b0cc2e3daa0964a08c653e692fb64382453e1cfcee3d863828844c8d6f6239727b9023 + version: 7.0.11 + resolution: "nodemailer@npm:7.0.11" + checksum: 10/2ad4dd56a4caf84a83aa6f4378ded26d5ef8a644ca3be09c3b4fb2255d861369e620f29be6c3c97148ac4a50aa5fdff6240b9d60805362bd99ca15f2ea62e8a2 languageName: node linkType: hard "nodemon@npm:^3.0.1": - version: 3.1.10 - resolution: "nodemon@npm:3.1.10" + version: 3.1.11 + resolution: "nodemon@npm:3.1.11" dependencies: chokidar: "npm:^3.5.2" debug: "npm:^4" @@ -39810,7 +40029,7 @@ __metadata: undefsafe: "npm:^2.0.5" bin: nodemon: bin/nodemon.js - checksum: 10/af5f63d0b4af3ee54f60c136996692232f836815ddd37c0368fd8e50c31dd0180a4db5cdb7f4c2c5a96b31c77f30a77c2253ac34438913839846098af813fd20 + checksum: 10/0f43d2c70abe0764e26e438dbe0c78bc429746a558dabf5dd94b13f6f3a79b4bd7d5793347acafddaee5eab594a806c2ad43efc999d342e28d185661718da8dc languageName: node linkType: hard @@ -40099,10 +40318,10 @@ __metadata: languageName: node linkType: hard -"nwsapi@npm:^2.2.0, nwsapi@npm:^2.2.12": - version: 2.2.13 - resolution: "nwsapi@npm:2.2.13" - checksum: 10/f7f30a236f2ee513ea8042f1a987481dc2b900167c47f7163882f0fcfe7ccb57b5c8daaf2c91008dc20a204fcd79e050aee25001433ad99990bbed5a8c74121c +"nwsapi@npm:^2.2.12": + version: 2.2.23 + resolution: "nwsapi@npm:2.2.23" + checksum: 10/aa4a570039c33d70b51436d1bb533f3e2c33c488ccbe9b09285c46a6cee5ef266fd60103461085c6954ba52460786a8138f042958328c7c1b4763898eb3dadfa languageName: node linkType: hard @@ -40221,7 +40440,7 @@ __metadata: languageName: node linkType: hard -"object.values@npm:^1.1.6, object.values@npm:^1.2.0, object.values@npm:^1.2.1": +"object.values@npm:^1.1.6, object.values@npm:^1.2.1": version: 1.2.1 resolution: "object.values@npm:1.2.1" dependencies: @@ -40293,13 +40512,6 @@ __metadata: languageName: node linkType: hard -"on-headers@npm:~1.0.2": - version: 1.0.2 - resolution: "on-headers@npm:1.0.2" - checksum: 10/870766c16345855e2012e9422ba1ab110c7e44ad5891a67790f84610bd70a72b67fdd71baf497295f1d1bf38dd4c92248f825d48729c53c0eae5262fb69fa171 - languageName: node - linkType: hard - "on-headers@npm:~1.1.0": version: 1.1.0 resolution: "on-headers@npm:1.1.0" @@ -40377,19 +40589,19 @@ __metadata: languageName: node linkType: hard -"open@npm:^10.0.3": - version: 10.0.3 - resolution: "open@npm:10.0.3" +"open@npm:^10.0.3, open@npm:^10.2.0": + version: 10.2.0 + resolution: "open@npm:10.2.0" dependencies: default-browser: "npm:^5.2.1" define-lazy-prop: "npm:^3.0.0" is-inside-container: "npm:^1.0.0" - is-wsl: "npm:^3.1.0" - checksum: 10/4dc757ad1d3d63490822f991e9cbe3a7c05b7249fca2eaa571cb7d191e5cec88bc37e15d8ef4fd740d8989a288b661d8da253caa8d98e8c97430ddbbb0ae4ed1 + wsl-utils: "npm:^0.1.0" + checksum: 10/e6ad9474734eac3549dcc7d85e952394856ccaee48107c453bd6a725b82e3b8ed5f427658935df27efa76b411aeef62888edea8a9e347e8e7c82632ec966b30e languageName: node linkType: hard -"open@npm:^8.0.0, open@npm:^8.0.4, open@npm:^8.4.0": +"open@npm:^8.0.0, open@npm:^8.4.0": version: 8.4.2 resolution: "open@npm:8.4.2" dependencies: @@ -40572,13 +40784,6 @@ __metadata: languageName: node linkType: hard -"os-tmpdir@npm:~1.0.2": - version: 1.0.2 - resolution: "os-tmpdir@npm:1.0.2" - checksum: 10/5666560f7b9f10182548bf7013883265be33620b1c1b4a4d405c25be2636f970c5488ff3e6c48de75b55d02bde037249fe5dbfbb4c0fb7714953d56aed062e6d - languageName: node - linkType: hard - "osx-release@npm:^1.0.0": version: 1.1.0 resolution: "osx-release@npm:1.1.0" @@ -40615,6 +40820,75 @@ __metadata: languageName: node linkType: hard +"oxc-resolver@npm:^11.13.2": + version: 11.14.2 + resolution: "oxc-resolver@npm:11.14.2" + dependencies: + "@oxc-resolver/binding-android-arm-eabi": "npm:11.14.2" + "@oxc-resolver/binding-android-arm64": "npm:11.14.2" + "@oxc-resolver/binding-darwin-arm64": "npm:11.14.2" + "@oxc-resolver/binding-darwin-x64": "npm:11.14.2" + "@oxc-resolver/binding-freebsd-x64": "npm:11.14.2" + "@oxc-resolver/binding-linux-arm-gnueabihf": "npm:11.14.2" + "@oxc-resolver/binding-linux-arm-musleabihf": "npm:11.14.2" + "@oxc-resolver/binding-linux-arm64-gnu": "npm:11.14.2" + "@oxc-resolver/binding-linux-arm64-musl": "npm:11.14.2" + "@oxc-resolver/binding-linux-ppc64-gnu": "npm:11.14.2" + "@oxc-resolver/binding-linux-riscv64-gnu": "npm:11.14.2" + "@oxc-resolver/binding-linux-riscv64-musl": "npm:11.14.2" + "@oxc-resolver/binding-linux-s390x-gnu": "npm:11.14.2" + "@oxc-resolver/binding-linux-x64-gnu": "npm:11.14.2" + "@oxc-resolver/binding-linux-x64-musl": "npm:11.14.2" + "@oxc-resolver/binding-openharmony-arm64": "npm:11.14.2" + "@oxc-resolver/binding-wasm32-wasi": "npm:11.14.2" + "@oxc-resolver/binding-win32-arm64-msvc": "npm:11.14.2" + "@oxc-resolver/binding-win32-ia32-msvc": "npm:11.14.2" + "@oxc-resolver/binding-win32-x64-msvc": "npm:11.14.2" + dependenciesMeta: + "@oxc-resolver/binding-android-arm-eabi": + optional: true + "@oxc-resolver/binding-android-arm64": + optional: true + "@oxc-resolver/binding-darwin-arm64": + optional: true + "@oxc-resolver/binding-darwin-x64": + optional: true + "@oxc-resolver/binding-freebsd-x64": + optional: true + "@oxc-resolver/binding-linux-arm-gnueabihf": + optional: true + "@oxc-resolver/binding-linux-arm-musleabihf": + optional: true + "@oxc-resolver/binding-linux-arm64-gnu": + optional: true + "@oxc-resolver/binding-linux-arm64-musl": + optional: true + "@oxc-resolver/binding-linux-ppc64-gnu": + optional: true + "@oxc-resolver/binding-linux-riscv64-gnu": + optional: true + "@oxc-resolver/binding-linux-riscv64-musl": + optional: true + "@oxc-resolver/binding-linux-s390x-gnu": + optional: true + "@oxc-resolver/binding-linux-x64-gnu": + optional: true + "@oxc-resolver/binding-linux-x64-musl": + optional: true + "@oxc-resolver/binding-openharmony-arm64": + optional: true + "@oxc-resolver/binding-wasm32-wasi": + optional: true + "@oxc-resolver/binding-win32-arm64-msvc": + optional: true + "@oxc-resolver/binding-win32-ia32-msvc": + optional: true + "@oxc-resolver/binding-win32-x64-msvc": + optional: true + checksum: 10/f64fa5cd61700b0ba370319f87b6c5ef45b9036f2c21719a563999285493f8152d9c7922d35d07208088d3893327de91c10e65cbc4131782aeeb9f9da365ae7c + languageName: node + linkType: hard + "p-cancelable@npm:^1.0.0": version: 1.1.0 resolution: "p-cancelable@npm:1.1.0" @@ -40684,15 +40958,6 @@ __metadata: languageName: node linkType: hard -"p-limit@npm:^4.0.0": - version: 4.0.0 - resolution: "p-limit@npm:4.0.0" - dependencies: - yocto-queue: "npm:^1.0.0" - checksum: 10/01d9d70695187788f984226e16c903475ec6a947ee7b21948d6f597bed788e3112cc7ec2e171c1d37125057a5f45f3da21d8653e04a3a793589e12e9e80e756b - languageName: node - linkType: hard - "p-locate@npm:^3.0.0": version: 3.0.0 resolution: "p-locate@npm:3.0.0" @@ -40720,15 +40985,6 @@ __metadata: languageName: node linkType: hard -"p-locate@npm:^6.0.0": - version: 6.0.0 - resolution: "p-locate@npm:6.0.0" - dependencies: - p-limit: "npm:^4.0.0" - checksum: 10/2bfe5234efa5e7a4e74b30a5479a193fdd9236f8f6b4d2f3f69e3d286d9a7d7ab0c118a2a50142efcf4e41625def635bd9332d6cbf9cc65d85eb0718c579ab38 - languageName: node - linkType: hard - "p-map@npm:^2.0.0": version: 2.1.0 resolution: "p-map@npm:2.1.0" @@ -40990,6 +41246,21 @@ __metadata: languageName: node linkType: hard +"parse-entities@npm:^4.0.0": + version: 4.0.2 + resolution: "parse-entities@npm:4.0.2" + dependencies: + "@types/unist": "npm:^2.0.0" + character-entities-legacy: "npm:^3.0.0" + character-reference-invalid: "npm:^2.0.0" + decode-named-character-reference: "npm:^1.0.0" + is-alphanumerical: "npm:^2.0.0" + is-decimal: "npm:^2.0.0" + is-hexadecimal: "npm:^2.0.0" + checksum: 10/b0ce693d0b3d7ed1cea6fe814e6e077c71532695f01178e846269e9a2bc2f7ff34ca4bb8db80b48af0451100f25bb010df6591c9bb6306e4680ccb423d1e4038 + languageName: node + linkType: hard + "parse-json@npm:^5.0.0, parse-json@npm:^5.2.0": version: 5.2.0 resolution: "parse-json@npm:5.2.0" @@ -41009,13 +41280,6 @@ __metadata: languageName: node linkType: hard -"parse-ms@npm:^4.0.0": - version: 4.0.0 - resolution: "parse-ms@npm:4.0.0" - checksum: 10/673c801d9f957ff79962d71ed5a24850163f4181a90dd30c4e3666b3a804f53b77f1f0556792e8b2adbb5d58757907d1aa51d7d7dc75997c2a56d72937cbc8b7 - languageName: node - linkType: hard - "parse-multipart-data@npm:^1.4.0": version: 1.5.0 resolution: "parse-multipart-data@npm:1.5.0" @@ -41049,11 +41313,20 @@ __metadata: linkType: hard "parse5@npm:^7.0.0, parse5@npm:^7.1.2": - version: 7.2.0 - resolution: "parse5@npm:7.2.0" + version: 7.3.0 + resolution: "parse5@npm:7.3.0" dependencies: - entities: "npm:^4.5.0" - checksum: 10/49dabfe848f00e8cad8d9198a094d667fbdecbfa5143ddf8fb708e499b5ba76426c16135c8993b1d8e01827b92e8cfab0a9a248afa6ad7cc6f38aecf5bd017e6 + entities: "npm:^6.0.0" + checksum: 10/b0e48be20b820c655b138b86fa6fb3a790de6c891aa2aba536524f8027b4dca4fe538f11a0e5cf2f6f847d120dbb9e4822dcaeb933ff1e10850a2ef0154d1d88 + languageName: node + linkType: hard + +"parse5@npm:^8.0.0": + version: 8.0.0 + resolution: "parse5@npm:8.0.0" + dependencies: + entities: "npm:^6.0.0" + checksum: 10/1973850932bb1cbd52ab64502761489fbe1bb43a52dee7ce41aac0b6c33a51a92aaee04661590b0912b739ae9ee316bce4c78c8ea34af42a7e522c983c3c6cf5 languageName: node linkType: hard @@ -41084,13 +41357,13 @@ __metadata: linkType: hard "passport-auth0@npm:^1.4.3": - version: 1.4.4 - resolution: "passport-auth0@npm:1.4.4" + version: 1.4.5 + resolution: "passport-auth0@npm:1.4.5" dependencies: - axios: "npm:^1.6.0" + axios: "npm:^1.7.4" passport-oauth: "npm:^1.0.0" passport-oauth2: "npm:^1.6.0" - checksum: 10/307d2d8d687a29dbe2fc98fbee1cc948f76e936c6ae7ffeb28076c98b558a942be1cbc0eedb58d9003285bf4e816f6e971b0edb7a604d290272b1ba8e731006d + checksum: 10/e9e40e82862f75312ffd0dbed09cd62693008551b07e7ada75725597c3763361aa2f3070ea485e70219572a23d459ea03553dd8f2c5d683ece83577007bdf5b9 languageName: node linkType: hard @@ -41238,13 +41511,6 @@ __metadata: languageName: node linkType: hard -"path-exists@npm:^5.0.0": - version: 5.0.0 - resolution: "path-exists@npm:5.0.0" - checksum: 10/8ca842868cab09423994596eb2c5ec2a971c17d1a3cb36dbf060592c730c725cd524b9067d7d2a1e031fef9ba7bd2ac6dc5ec9fb92aa693265f7be3987045254 - languageName: node - linkType: hard - "path-is-absolute@npm:^1.0.0": version: 1.0.1 resolution: "path-is-absolute@npm:1.0.1" @@ -41314,10 +41580,10 @@ __metadata: languageName: node linkType: hard -"path-to-regexp@npm:8.2.0": - version: 8.2.0 - resolution: "path-to-regexp@npm:8.2.0" - checksum: 10/23378276a172b8ba5f5fb824475d1818ca5ccee7bbdb4674701616470f23a14e536c1db11da9c9e6d82b82c556a817bbf4eee6e41b9ed20090ef9427cbb38e13 +"path-to-regexp@npm:8.3.0, path-to-regexp@npm:^8.0.0, path-to-regexp@npm:^8.1.0, path-to-regexp@npm:^8.2.0": + version: 8.3.0 + resolution: "path-to-regexp@npm:8.3.0" + checksum: 10/568f148fc64f5fd1ecebf44d531383b28df924214eabf5f2570dce9587a228e36c37882805ff02d71c6209b080ea3ee6a4d2b712b5df09741b67f1f3cf91e55a languageName: node linkType: hard @@ -41328,13 +41594,6 @@ __metadata: languageName: node linkType: hard -"path-to-regexp@npm:^8.0.0, path-to-regexp@npm:^8.1.0, path-to-regexp@npm:^8.2.0": - version: 8.3.0 - resolution: "path-to-regexp@npm:8.3.0" - checksum: 10/568f148fc64f5fd1ecebf44d531383b28df924214eabf5f2570dce9587a228e36c37882805ff02d71c6209b080ea3ee6a4d2b712b5df09741b67f1f3cf91e55a - languageName: node - linkType: hard - "path-to-regexp@npm:~0.1.12": version: 0.1.12 resolution: "path-to-regexp@npm:0.1.12" @@ -41356,6 +41615,13 @@ __metadata: languageName: node linkType: hard +"pathe@npm:^2.0.3": + version: 2.0.3 + resolution: "pathe@npm:2.0.3" + checksum: 10/01e9a69928f39087d96e1751ce7d6d50da8c39abf9a12e0ac2389c42c83bc76f78c45a475bd9026a02e6a6f79be63acc75667df855862fe567d99a00a540d23d + languageName: node + linkType: hard + "pathval@npm:^2.0.0": version: 2.0.0 resolution: "pathval@npm:2.0.0" @@ -41421,10 +41687,10 @@ __metadata: languageName: node linkType: hard -"pg-cloudflare@npm:^1.1.1": - version: 1.1.1 - resolution: "pg-cloudflare@npm:1.1.1" - checksum: 10/45ca0c7926967ec9e66a9efc73ca57e3e933671b541bc774631a02ce683e7f658d0a4e881119b3f61486f38e344ae1b008d3a20eb5e21701c5fa8ff8382c5538 +"pg-cloudflare@npm:^1.2.7": + version: 1.2.7 + resolution: "pg-cloudflare@npm:1.2.7" + checksum: 10/3d171407cbce36436c461200666ba6bd884bfe98016972760a797cec850199b8024a40055d80322c5fc02909e1533a144e9b108a99f7d7e21d0c42612f9821fb languageName: node linkType: hard @@ -41435,7 +41701,7 @@ __metadata: languageName: node linkType: hard -"pg-connection-string@npm:^2.3.0, pg-connection-string@npm:^2.5.0, pg-connection-string@npm:^2.7.0": +"pg-connection-string@npm:^2.3.0, pg-connection-string@npm:^2.5.0, pg-connection-string@npm:^2.9.1": version: 2.9.1 resolution: "pg-connection-string@npm:2.9.1" checksum: 10/40e9e9cd752121e72bff18d83e6c7ecda9056426815a84294de018569a319293c924704c8b7f0604fdc588835c7927647dea4f3c87a014e715bcbb17d794e9f0 @@ -41456,23 +41722,23 @@ __metadata: languageName: node linkType: hard -"pg-pool@npm:^3.8.0": - version: 3.8.0 - resolution: "pg-pool@npm:3.8.0" +"pg-pool@npm:^3.10.1": + version: 3.10.1 + resolution: "pg-pool@npm:3.10.1" peerDependencies: pg: ">=8.0" - checksum: 10/be6b7c6932fa177dc69ca8980d959f24b4979911465ac11656b8ff86707cba035e776416d8aac1029e8cc4d8eb8989ed2cc85a33ac6b76e266b20a81284436d8 + checksum: 10/b389a714be59ebe53ec412cbff513191cc0b7a203faa5d26416b6a038cafdfe30fbf1a5936b77bb76109c49bd7c4a116870a5a46a45796b1b34c96f016d7fbe2 languageName: node linkType: hard -"pg-protocol@npm:*, pg-protocol@npm:^1.8.0": - version: 1.8.0 - resolution: "pg-protocol@npm:1.8.0" - checksum: 10/52f67d8161ae4afb1dbf96f6ad12a2ecf478dbb0b80baa239047cd562dee378961fd446f0a1cfc1fd323e052fbb3df47e886c5d9d86a2803a000d36682b29094 +"pg-protocol@npm:*, pg-protocol@npm:^1.10.3": + version: 1.10.3 + resolution: "pg-protocol@npm:1.10.3" + checksum: 10/31da85319084c03f403efee7accce9786964df82a7feb60e6bd77b71f1e622c74a2a644a2bc434389d0ab92e5abdeedea69ebdb53b1897d9f01d2a1f51a8a2fe languageName: node linkType: hard -"pg-types@npm:^2.1.0, pg-types@npm:^2.2.0": +"pg-types@npm:2.2.0, pg-types@npm:^2.2.0": version: 2.2.0 resolution: "pg-types@npm:2.2.0" dependencies: @@ -41486,15 +41752,15 @@ __metadata: linkType: hard "pg@npm:^8.11.3, pg@npm:^8.9.0": - version: 8.14.1 - resolution: "pg@npm:8.14.1" + version: 8.16.3 + resolution: "pg@npm:8.16.3" dependencies: - pg-cloudflare: "npm:^1.1.1" - pg-connection-string: "npm:^2.7.0" - pg-pool: "npm:^3.8.0" - pg-protocol: "npm:^1.8.0" - pg-types: "npm:^2.1.0" - pgpass: "npm:1.x" + pg-cloudflare: "npm:^1.2.7" + pg-connection-string: "npm:^2.9.1" + pg-pool: "npm:^3.10.1" + pg-protocol: "npm:^1.10.3" + pg-types: "npm:2.2.0" + pgpass: "npm:1.0.5" peerDependencies: pg-native: ">=3.0.1" dependenciesMeta: @@ -41503,16 +41769,16 @@ __metadata: peerDependenciesMeta: pg-native: optional: true - checksum: 10/45f2d5719fd74a6a4784c5115c0ff482af92d1e5b101bf423160b6a983e37cc2fad4a7eea2a06f27e6f8bdb8abce23486d2d522c8c52c90f68a2bc897f0553c4 + checksum: 10/6a2885a3f581d6c6dddddf5a4bb2790ee84f402ed7d73ece8b6bc102c58c17e4c5f17894c241633aa2f1d4fedd8f2401a80a9a02ef18bb57d05cbbfd8a53ca4d languageName: node linkType: hard -"pgpass@npm:1.x": - version: 1.0.2 - resolution: "pgpass@npm:1.0.2" +"pgpass@npm:1.0.5": + version: 1.0.5 + resolution: "pgpass@npm:1.0.5" dependencies: - split: "npm:^1.0.0" - checksum: 10/4f09d81d5aa9e3e409e2a58dc71f889ca92233d66772adcb810e53e637b49013ae84b8dd831aa5e6f1413bffb4b9b1eafd1a05227c8cf05c39f5cd276d4e9492 + split2: "npm:^4.1.0" + checksum: 10/0a6f3bf76e36bdb3c20a7e8033140c732767bba7e81f845f7489fc3123a2bd6e3b8e704f08cba86b117435414b5d2422e20ba9d5f2efb6f0c75c9efca73e8e87 languageName: node linkType: hard @@ -41644,7 +41910,7 @@ __metadata: languageName: node linkType: hard -"pirates@npm:^4.0.1, pirates@npm:^4.0.4, pirates@npm:^4.0.6": +"pirates@npm:^4.0.1, pirates@npm:^4.0.6, pirates@npm:^4.0.7": version: 4.0.7 resolution: "pirates@npm:4.0.7" checksum: 10/2427f371366081ae42feb58214f04805d6b41d6b84d74480ebcc9e0ddbd7105a139f7c653daeaf83ad8a1a77214cf07f64178e76de048128fec501eab3305a96 @@ -41708,27 +41974,27 @@ __metadata: languageName: node linkType: hard -"playwright-core@npm:1.54.2": - version: 1.54.2 - resolution: "playwright-core@npm:1.54.2" +"playwright-core@npm:1.57.0": + version: 1.57.0 + resolution: "playwright-core@npm:1.57.0" bin: playwright-core: cli.js - checksum: 10/8eb8b37d7b02c2394f85567c5703464ee7c85929e1de7118946548a0277cacd41a6f247b8f7eb50c921433346f785356eff8132a9d3c6c2dcf3402c6a83e4f18 + checksum: 10/ec066602f0196f036006caee14a30d0a57533a76673bb9a0c609ef56e21decf018f0e8d402ba2fb18251393be6a1c9e193c83266f1670fe50838c5340e220de0 languageName: node linkType: hard -"playwright@npm:1.54.2": - version: 1.54.2 - resolution: "playwright@npm:1.54.2" +"playwright@npm:1.57.0": + version: 1.57.0 + resolution: "playwright@npm:1.57.0" dependencies: fsevents: "npm:2.3.2" - playwright-core: "npm:1.54.2" + playwright-core: "npm:1.57.0" dependenciesMeta: fsevents: optional: true bin: playwright: cli.js - checksum: 10/3f4fedc1e2290b6da6960eedf0d78b9097251848b499b0627186ca85e94178fe6be1590c4926246ff4dad5729fc80ab63fee6554fe736d29c0a1808ec483467f + checksum: 10/241559210f98ef11b6bd6413f2d29da7ef67c7865b72053192f0d164fab9e0d3bd47913b3351d5de6433a8aff2d8424d4b8bd668df420bf4dda7ae9fcd37b942 languageName: node linkType: hard @@ -41784,12 +42050,12 @@ __metadata: linkType: hard "portfinder@npm:^1.0.28, portfinder@npm:^1.0.32": - version: 1.0.37 - resolution: "portfinder@npm:1.0.37" + version: 1.0.38 + resolution: "portfinder@npm:1.0.38" dependencies: async: "npm:^3.2.6" debug: "npm:^4.3.6" - checksum: 10/0d9addb4b28451319bc95feb7af6c060188e176199eebd1b66ef7ea460102e546aedcd6dc7039c5942812c9696218403106e2a45b66a8c551888fc18830b0014 + checksum: 10/369155c3e7efa10ad348cd6686eb9efe57f334a4638f9107fd6ad6705dc532841f9bd8346182591280b2c7837600d8fb0cf0d1ced69a78caa8544fc3bb43653a languageName: node linkType: hard @@ -42363,6 +42629,13 @@ __metadata: languageName: node linkType: hard +"presentable-error@npm:^0.0.1": + version: 0.0.1 + resolution: "presentable-error@npm:0.0.1" + checksum: 10/013809ee7a47ced847a8d860e9b89a56cdd8c4f1ad04ad8da1e58fd60843f77f497d204146bb15aaa9793d3b94ad8626eed01256fc9eb5839a545af2000a5fa4 + languageName: node + linkType: hard + "prettier@npm:^2.2.1, prettier@npm:^2.7.1": version: 2.8.8 resolution: "prettier@npm:2.8.8" @@ -42389,6 +42662,17 @@ __metadata: languageName: node linkType: hard +"pretty-format@npm:30.2.0, pretty-format@npm:^30.0.0": + version: 30.2.0 + resolution: "pretty-format@npm:30.2.0" + dependencies: + "@jest/schemas": "npm:30.0.5" + ansi-styles: "npm:^5.2.0" + react-is: "npm:^18.3.1" + checksum: 10/725890d648e3400575eebc99a334a4cd1498e0d36746313913706bbeea20ada27e17c184a3cd45c50f705c16111afa829f3450233fc0fda5eed293c69757e926 + languageName: node + linkType: hard + "pretty-format@npm:^27.0.2": version: 27.5.1 resolution: "pretty-format@npm:27.5.1" @@ -42400,7 +42684,7 @@ __metadata: languageName: node linkType: hard -"pretty-format@npm:^29.0.0, pretty-format@npm:^29.7.0": +"pretty-format@npm:^29.7.0": version: 29.7.0 resolution: "pretty-format@npm:29.7.0" dependencies: @@ -42420,15 +42704,6 @@ __metadata: languageName: node linkType: hard -"pretty-ms@npm:^9.0.0": - version: 9.2.0 - resolution: "pretty-ms@npm:9.2.0" - dependencies: - parse-ms: "npm:^4.0.0" - checksum: 10/a65a1d81560867f4f7128862fdbf0e1c2d3c5607bf75cae7758bf8111e2c4b744be46e084704125a38ba918bb43defa7a53aaff0f48c5c2d95367d3148c980d9 - languageName: node - linkType: hard - "printj@npm:~1.1.0": version: 1.1.2 resolution: "printj@npm:1.1.2" @@ -42586,7 +42861,7 @@ __metadata: languageName: node linkType: hard -"prompts@npm:^2.0.1, prompts@npm:^2.4.2": +"prompts@npm:^2.4.2": version: 2.4.2 resolution: "prompts@npm:2.4.2" dependencies: @@ -42643,6 +42918,13 @@ __metadata: languageName: node linkType: hard +"property-information@npm:^7.0.0": + version: 7.1.0 + resolution: "property-information@npm:7.1.0" + checksum: 10/896d38a52ad7170de73f832d277c69e76a9605d941ebb3f0d6e56271414a7fdf95ff6d2819e68036b8a0c7d2d4d88bf1d4a5765c032cb19c2343567ee3a14b15 + languageName: node + linkType: hard + "proto3-json-serializer@npm:^2.0.2": version: 2.0.2 resolution: "proto3-json-serializer@npm:2.0.2" @@ -42712,13 +42994,6 @@ __metadata: languageName: node linkType: hard -"psl@npm:^1.1.33": - version: 1.8.0 - resolution: "psl@npm:1.8.0" - checksum: 10/5f62a8eca06cb4a017983d15b92b0d38dc8699d637eabc8cb482c59b4106c9760f59cc8afabcb8bb7b98f0322907680d8f0f59226386fffab5248d180bc04578 - languageName: node - linkType: hard - "pstree.remy@npm:^1.1.8": version: 1.1.8 resolution: "pstree.remy@npm:1.1.8" @@ -42787,14 +43062,14 @@ __metadata: languageName: node linkType: hard -"pure-rand@npm:^6.0.0": - version: 6.0.4 - resolution: "pure-rand@npm:6.0.4" - checksum: 10/34fed0abe99d3db7ddc459c12e1eda6bff05db6a17f2017a1ae12202271ccf276fb223b442653518c719671c1b339bbf97f27ba9276dba0997c89e45c4e6a3bf +"pure-rand@npm:^7.0.0": + version: 7.0.1 + resolution: "pure-rand@npm:7.0.1" + checksum: 10/c61a576fda5032ec9763ecb000da4a8f19263b9e2f9ae9aa2759c8fbd9dc6b192b2ce78391ebd41abb394a5fedb7bcc4b03c9e6141ac8ab20882dd5717698b80 languageName: node linkType: hard -"qs@npm:^6.10.1, qs@npm:^6.10.3, qs@npm:^6.11.0, qs@npm:^6.11.2, qs@npm:^6.12.2, qs@npm:^6.12.3, qs@npm:^6.14.0, qs@npm:^6.7.0, qs@npm:^6.9.4, qs@npm:~6.14.0": +"qs@npm:^6.10.1, qs@npm:^6.10.3, qs@npm:^6.11.2, qs@npm:^6.12.2, qs@npm:^6.12.3, qs@npm:^6.14.0, qs@npm:^6.7.0, qs@npm:^6.9.4, qs@npm:~6.14.0": version: 6.14.0 resolution: "qs@npm:6.14.0" dependencies: @@ -42956,11 +43231,11 @@ __metadata: linkType: hard "rate-limit-redis@npm:^4.2.0": - version: 4.2.1 - resolution: "rate-limit-redis@npm:4.2.1" + version: 4.3.1 + resolution: "rate-limit-redis@npm:4.3.1" peerDependencies: express-rate-limit: ">= 6" - checksum: 10/c36c50cfca992cbd14c97c08bb01c7d1d340d27b5fa1a2c1154275fec0b59c187eb6fb207da3d035c7c87e7629c92324cd53074f854dbb16548faf94f5a41351 + checksum: 10/6e02374832ced889a61829e327d03d021c50c0fc3ac86674d8c922cd3a50c0451091106811c308ed5553776a28b6acbc5313e2c9d37aecb198ab306f249de21b languageName: node linkType: hard @@ -43254,9 +43529,9 @@ __metadata: languageName: node linkType: hard -"react-docgen@npm:^8.0.0": - version: 8.0.1 - resolution: "react-docgen@npm:8.0.1" +"react-docgen@npm:^8.0.0, react-docgen@npm:^8.0.2": + version: 8.0.2 + resolution: "react-docgen@npm:8.0.2" dependencies: "@babel/core": "npm:^7.28.0" "@babel/traverse": "npm:^7.28.0" @@ -43268,7 +43543,7 @@ __metadata: doctrine: "npm:^3.0.0" resolve: "npm:^1.22.1" strip-indent: "npm:^4.0.0" - checksum: 10/6eb9ec3870c0f527fd05b048a842e2338825d99703312d6f4e84f3ae0e5eda427e6b4c7c07a93b21d8740e2be23e779e0237c4b2783160e285f0121711e2f47c + checksum: 10/b56f594237a0bdf1356dee6a416ab6f2f38f60a7330cbdaf1da93d366f29f6bfbbfedecd51d47f6ba2a898985c3205c369e7f6cad528478560d9363717243ff8 languageName: node linkType: hard @@ -43409,11 +43684,11 @@ __metadata: linkType: hard "react-hook-form@npm:^7.12.2": - version: 7.55.0 - resolution: "react-hook-form@npm:7.55.0" + version: 7.67.0 + resolution: "react-hook-form@npm:7.67.0" peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 - checksum: 10/900e06064c1b4977f2e3e249a0f91742ae6bd1f2109701b80a9280b1c2b4bee8aac26aed7104371101eadad724f0bbe0215499e84623e6375007489ae850fe8e + checksum: 10/0e74a48b2da0f79166d5c6701f78a08fd5165e901e46ce5a578f0a2f25005e861023ffb35c1a96373c23701a84c3fce2111c4aced824d2ca08c9b2420a645551 languageName: node linkType: hard @@ -43472,7 +43747,7 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^18.0.0, react-is@npm:^18.2.0": +"react-is@npm:^18.0.0, react-is@npm:^18.2.0, react-is@npm:^18.3.1": version: 18.3.1 resolution: "react-is@npm:18.3.1" checksum: 10/d5f60c87d285af24b1e1e7eaeb123ec256c3c8bdea7061ab3932e3e14685708221bf234ec50b21e10dd07f008f1b966a2730a0ce4ff67905b3872ff2042aec22 @@ -43639,12 +43914,12 @@ __metadata: linkType: hard "react-resizable-panels@npm:^3.0.4": - version: 3.0.4 - resolution: "react-resizable-panels@npm:3.0.4" + version: 3.0.6 + resolution: "react-resizable-panels@npm:3.0.6" peerDependencies: react: ^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc - checksum: 10/92b8ac224d3c60c7c8ea0d80f712d9cd719afad76d4f1a5b8c8cc7c886b77f1d5058fa622ea057f28f5f7fc1a2c86e38e14d7b0f33722c30bff02e37f9fba705 + checksum: 10/cacd2a0a63e4ecca193ceb2c8369d760946987c6386e38be39c7f98f909db923f161dbfd5187c289f5093c035c4a7757c4bd30b0d792bd8b45f2bc64183fe47f languageName: node linkType: hard @@ -43808,7 +44083,7 @@ __metadata: languageName: node linkType: hard -"react-syntax-highlighter@npm:^15.4.5, react-syntax-highlighter@npm:^15.6.1": +"react-syntax-highlighter@npm:^15.4.5": version: 15.6.6 resolution: "react-syntax-highlighter@npm:15.6.6" dependencies: @@ -43824,6 +44099,22 @@ __metadata: languageName: node linkType: hard +"react-syntax-highlighter@npm:^16.0.0": + version: 16.1.0 + resolution: "react-syntax-highlighter@npm:16.1.0" + dependencies: + "@babel/runtime": "npm:^7.28.4" + highlight.js: "npm:^10.4.1" + highlightjs-vue: "npm:^1.0.0" + lowlight: "npm:^1.17.0" + prismjs: "npm:^1.30.0" + refractor: "npm:^5.0.0" + peerDependencies: + react: ">= 0.14.0" + checksum: 10/d55bc96802357de2102703fb3ffe86a67d52099e93da9624a900609e4d8b6f5f95472d42423951631348fdee2679d661b17aaf41039035dc3f1bbabf0423d62e + languageName: node + linkType: hard + "react-test-renderer@npm:^16.13.1": version: 16.14.0 resolution: "react-test-renderer@npm:16.14.0" @@ -43877,8 +44168,8 @@ __metadata: linkType: hard "react-use@npm:^17.2.4, react-use@npm:^17.3.2, react-use@npm:^17.4.0": - version: 17.5.1 - resolution: "react-use@npm:17.5.1" + version: 17.6.0 + resolution: "react-use@npm:17.6.0" dependencies: "@types/js-cookie": "npm:^2.2.6" "@xobotyi/scrollbar-width": "npm:^1.9.5" @@ -43897,7 +44188,7 @@ __metadata: peerDependencies: react: "*" react-dom: "*" - checksum: 10/2da403a9949dbd964b9b8e20dcd354db66b7f7d5ca1f42572fbcdb06bd49ee828c295be4912cb87abc163d1b54820bb8c5fa85314a16c4579d9e30bf9cbd5759 + checksum: 10/a817b74e82b481a39d3539bfe8d3b535c08d59d44a75ea91f65e56a7ccaedb0de185159e50b44ea4a635dda0c1c7159f07530e81a1d64b57130e0a715a107795 languageName: node linkType: hard @@ -43967,7 +44258,7 @@ __metadata: languageName: node linkType: hard -"read-tls-client-hello@npm:^1.0.0": +"read-tls-client-hello@npm:^1.0.0, read-tls-client-hello@npm:^1.1.0": version: 1.1.0 resolution: "read-tls-client-hello@npm:1.1.0" dependencies: @@ -44066,6 +44357,13 @@ __metadata: languageName: node linkType: hard +"readdirp@npm:^4.0.1": + version: 4.1.2 + resolution: "readdirp@npm:4.1.2" + checksum: 10/7b817c265940dba90bb9c94d82920d76c3a35ea2d67f9f9d8bd936adcfe02d50c802b14be3dd2e725e002dddbe2cc1c7a0edfb1bc3a365c9dfd5a61e612eea1e + languageName: node + linkType: hard + "readline-sync@npm:1.4.9": version: 1.4.9 resolution: "readline-sync@npm:1.4.9" @@ -44210,6 +44508,18 @@ __metadata: languageName: node linkType: hard +"refractor@npm:^5.0.0": + version: 5.0.0 + resolution: "refractor@npm:5.0.0" + dependencies: + "@types/hast": "npm:^3.0.0" + "@types/prismjs": "npm:^1.0.0" + hastscript: "npm:^9.0.0" + parse-entities: "npm:^4.0.0" + checksum: 10/a14ceb938ed6f7f17dfa44660d3f3aff33e8896710bd76af0b411778791918bf20f923a191ff197fbc6a8e3f06c4371b83882f46ce76736f804dbe2b82b0be94 + languageName: node + linkType: hard + "regenerator-runtime@npm:^0.10.5": version: 0.10.5 resolution: "regenerator-runtime@npm:0.10.5" @@ -44476,13 +44786,6 @@ __metadata: languageName: node linkType: hard -"resolve.exports@npm:^2.0.0": - version: 2.0.0 - resolution: "resolve.exports@npm:2.0.0" - checksum: 10/a94fe2c064c57b4cc64de8c13eab28f744ee2327af4e458f2db00b5bbc3e7bf91b59fca043e35e2a3cf70bdae2263825c926b62200e2eb78d5c55a88d14932a8 - languageName: node - linkType: hard - "resolve@npm:1.22.8": version: 1.22.8 resolution: "resolve@npm:1.22.8" @@ -44762,33 +45065,33 @@ __metadata: linkType: hard "rollup-plugin-dts@npm:^6.1.0": - version: 6.1.1 - resolution: "rollup-plugin-dts@npm:6.1.1" + version: 6.3.0 + resolution: "rollup-plugin-dts@npm:6.3.0" dependencies: - "@babel/code-frame": "npm:^7.24.2" - magic-string: "npm:^0.30.10" + "@babel/code-frame": "npm:^7.27.1" + magic-string: "npm:^0.30.21" peerDependencies: rollup: ^3.29.4 || ^4 typescript: ^4.5 || ^5.0 dependenciesMeta: "@babel/code-frame": optional: true - checksum: 10/8a66833a5af32f77d9bbc746339097d4af2382e5160f7629d85dcecb4efad12cbfebd37c79147fa688f073c333d71f53135e08a225a3fc3e9a3b3f92c46b2381 + checksum: 10/1b2b25126eee0c4e7f59d82ee5850b0c5779a1a0bb77d677798e20a3d29dba76d1a19a73300ed5b20aab02f6888ecc4209a95b07f6cc9c1b80af14bdcbeda5b9 languageName: node linkType: hard "rollup-plugin-esbuild@npm:^6.1.1": - version: 6.1.1 - resolution: "rollup-plugin-esbuild@npm:6.1.1" + version: 6.2.1 + resolution: "rollup-plugin-esbuild@npm:6.2.1" dependencies: - "@rollup/pluginutils": "npm:^5.0.5" - debug: "npm:^4.3.4" - es-module-lexer: "npm:^1.3.1" - get-tsconfig: "npm:^4.7.2" + debug: "npm:^4.4.0" + es-module-lexer: "npm:^1.6.0" + get-tsconfig: "npm:^4.10.0" + unplugin-utils: "npm:^0.2.4" peerDependencies: esbuild: ">=0.18.0" rollup: ^1.20.0 || ^2.0.0 || ^3.0.0 || ^4.0.0 - checksum: 10/bba2d1dfb92a193823ac9dd1cdd44a8fd8cd9f25868e9a22ca077e1b7445feb4eaaf6df051148e367fc902d7d59c9f50efab49086c24c367972f05c86f3a656d + checksum: 10/e5731b86c4e01c6ccd3998a2f90794bd738fe83a3a809b9e82456e4b1d173c296ef302c2a6669b966b12c757c1787f0585ae88cd73b98f3c0ad6ad7f779940aa languageName: node linkType: hard @@ -44851,42 +45154,32 @@ __metadata: languageName: node linkType: hard -"rollup@npm:^0.63.4": - version: 0.63.5 - resolution: "rollup@npm:0.63.5" - dependencies: - "@types/estree": "npm:0.0.39" - "@types/node": "npm:*" - bin: - rollup: ./bin/rollup - checksum: 10/c52ad022bb732ea0e962b3ec45779d9d0523f75283bded8d0c97788f97946781d617b971e7e732ad7a63af60aad76ca534c415d8b101c7ff7d3f5cc879aba025 - languageName: node - linkType: hard - "rollup@npm:^4.27.3, rollup@npm:^4.43.0": - version: 4.46.2 - resolution: "rollup@npm:4.46.2" + version: 4.53.3 + resolution: "rollup@npm:4.53.3" dependencies: - "@rollup/rollup-android-arm-eabi": "npm:4.46.2" - "@rollup/rollup-android-arm64": "npm:4.46.2" - "@rollup/rollup-darwin-arm64": "npm:4.46.2" - "@rollup/rollup-darwin-x64": "npm:4.46.2" - "@rollup/rollup-freebsd-arm64": "npm:4.46.2" - "@rollup/rollup-freebsd-x64": "npm:4.46.2" - "@rollup/rollup-linux-arm-gnueabihf": "npm:4.46.2" - "@rollup/rollup-linux-arm-musleabihf": "npm:4.46.2" - "@rollup/rollup-linux-arm64-gnu": "npm:4.46.2" - "@rollup/rollup-linux-arm64-musl": "npm:4.46.2" - "@rollup/rollup-linux-loongarch64-gnu": "npm:4.46.2" - "@rollup/rollup-linux-ppc64-gnu": "npm:4.46.2" - "@rollup/rollup-linux-riscv64-gnu": "npm:4.46.2" - "@rollup/rollup-linux-riscv64-musl": "npm:4.46.2" - "@rollup/rollup-linux-s390x-gnu": "npm:4.46.2" - "@rollup/rollup-linux-x64-gnu": "npm:4.46.2" - "@rollup/rollup-linux-x64-musl": "npm:4.46.2" - "@rollup/rollup-win32-arm64-msvc": "npm:4.46.2" - "@rollup/rollup-win32-ia32-msvc": "npm:4.46.2" - "@rollup/rollup-win32-x64-msvc": "npm:4.46.2" + "@rollup/rollup-android-arm-eabi": "npm:4.53.3" + "@rollup/rollup-android-arm64": "npm:4.53.3" + "@rollup/rollup-darwin-arm64": "npm:4.53.3" + "@rollup/rollup-darwin-x64": "npm:4.53.3" + "@rollup/rollup-freebsd-arm64": "npm:4.53.3" + "@rollup/rollup-freebsd-x64": "npm:4.53.3" + "@rollup/rollup-linux-arm-gnueabihf": "npm:4.53.3" + "@rollup/rollup-linux-arm-musleabihf": "npm:4.53.3" + "@rollup/rollup-linux-arm64-gnu": "npm:4.53.3" + "@rollup/rollup-linux-arm64-musl": "npm:4.53.3" + "@rollup/rollup-linux-loong64-gnu": "npm:4.53.3" + "@rollup/rollup-linux-ppc64-gnu": "npm:4.53.3" + "@rollup/rollup-linux-riscv64-gnu": "npm:4.53.3" + "@rollup/rollup-linux-riscv64-musl": "npm:4.53.3" + "@rollup/rollup-linux-s390x-gnu": "npm:4.53.3" + "@rollup/rollup-linux-x64-gnu": "npm:4.53.3" + "@rollup/rollup-linux-x64-musl": "npm:4.53.3" + "@rollup/rollup-openharmony-arm64": "npm:4.53.3" + "@rollup/rollup-win32-arm64-msvc": "npm:4.53.3" + "@rollup/rollup-win32-ia32-msvc": "npm:4.53.3" + "@rollup/rollup-win32-x64-gnu": "npm:4.53.3" + "@rollup/rollup-win32-x64-msvc": "npm:4.53.3" "@types/estree": "npm:1.0.8" fsevents: "npm:~2.3.2" dependenciesMeta: @@ -44910,7 +45203,7 @@ __metadata: optional: true "@rollup/rollup-linux-arm64-musl": optional: true - "@rollup/rollup-linux-loongarch64-gnu": + "@rollup/rollup-linux-loong64-gnu": optional: true "@rollup/rollup-linux-ppc64-gnu": optional: true @@ -44924,17 +45217,21 @@ __metadata: optional: true "@rollup/rollup-linux-x64-musl": optional: true + "@rollup/rollup-openharmony-arm64": + optional: true "@rollup/rollup-win32-arm64-msvc": optional: true "@rollup/rollup-win32-ia32-msvc": optional: true + "@rollup/rollup-win32-x64-gnu": + optional: true "@rollup/rollup-win32-x64-msvc": optional: true fsevents: optional: true bin: rollup: dist/bin/rollup - checksum: 10/3acc425a9828e8ba75eaec9cb506a680d3deaa09a753635140cc4a3c98445ba6e3f631b32ca1c98965b3f60672d2815cd560ea844bba497d69e65c58c02327cf + checksum: 10/e2eff82405061fa907f15dfbf742b1f5fb4b214495c00989bcdbe21da5fcb3f6dec3deabacec491300a53c99da409586cfc77bdf29b411fccb9089b72cd3728d languageName: node linkType: hard @@ -44954,11 +45251,12 @@ __metadata: "@octokit/rest": "npm:^19.0.3" "@playwright/test": "npm:^1.32.3" "@spotify/eslint-plugin": "npm:^15.0.0" - "@storybook/addon-a11y": "npm:^9.1.7" - "@storybook/addon-docs": "npm:^9.1.7" - "@storybook/addon-links": "npm:^9.1.7" - "@storybook/addon-themes": "npm:^9.1.7" - "@storybook/react-vite": "npm:^9.1.7" + "@storybook/addon-a11y": "npm:^10.1.9" + "@storybook/addon-docs": "npm:^10.1.9" + "@storybook/addon-links": "npm:^10.1.9" + "@storybook/addon-themes": "npm:^10.1.9" + "@storybook/addon-vitest": "npm:^10.1.9" + "@storybook/react-vite": "npm:^10.1.9" "@techdocs/cli": "workspace:*" "@types/cacheable-request": "npm:^8.3.6" "@types/global-agent": "npm:^2.1.3" @@ -44986,7 +45284,7 @@ __metadata: shx: "npm:^0.4.0" sloc: "npm:^0.3.1" sort-package-json: "npm:^2.8.0" - storybook: "npm:^9.1.7" + storybook: "npm:^10.1.10" ts-morph: "npm:^24.0.0" typedoc: "npm:^0.28.0" typescript: "npm:~5.7.0" @@ -45015,6 +45313,13 @@ __metadata: languageName: node linkType: hard +"rrweb-cssom@npm:^0.8.0": + version: 0.8.0 + resolution: "rrweb-cssom@npm:0.8.0" + checksum: 10/07521ee36fb6569c17906afad1ac7ff8f099d49ade9249e190693ac36cdf27f88d9acf0cc66978935d5d0a23fca105643d7e9125b9a9d91ed9db9e02d31d7d80 + languageName: node + linkType: hard + "rtl-css-js@npm:^1.16.1": version: 1.16.1 resolution: "rtl-css-js@npm:1.16.1" @@ -45040,7 +45345,7 @@ __metadata: languageName: node linkType: hard -"run-parallel@npm:^1.1.9, run-parallel@npm:^1.2.0": +"run-parallel@npm:^1.1.9": version: 1.2.0 resolution: "run-parallel@npm:1.2.0" dependencies: @@ -45058,15 +45363,6 @@ __metadata: languageName: node linkType: hard -"rxjs@npm:^6.6.3": - version: 6.6.7 - resolution: "rxjs@npm:6.6.7" - dependencies: - tslib: "npm:^1.9.0" - checksum: 10/c8263ebb20da80dd7a91c452b9e96a178331f402344bbb40bc772b56340fcd48d13d1f545a1e3d8e464893008c5e306cc42a1552afe0d562b1a6d4e1e6262b03 - languageName: node - linkType: hard - "sade@npm:^1.7.3": version: 1.8.1 resolution: "sade@npm:1.8.1" @@ -45383,7 +45679,7 @@ __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.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0, semver@npm:^7.6.2": +"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.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0, semver@npm:^7.6.2, semver@npm:^7.7.2": version: 7.7.3 resolution: "semver@npm:7.7.3" bin: @@ -45630,7 +45926,7 @@ __metadata: languageName: node linkType: hard -"sha.js@npm:^2.4.0, sha.js@npm:^2.4.11, sha.js@npm:^2.4.12, sha.js@npm:^2.4.8, sha.js@npm:^2.4.9": +"sha.js@npm:^2.4.0, sha.js@npm:^2.4.11, sha.js@npm:^2.4.12, sha.js@npm:^2.4.8": version: 2.4.12 resolution: "sha.js@npm:2.4.12" dependencies: @@ -45700,10 +45996,10 @@ __metadata: languageName: node linkType: hard -"shell-quote@npm:^1.6.1, shell-quote@npm:^1.7.3, shell-quote@npm:^1.8.1": - version: 1.8.1 - resolution: "shell-quote@npm:1.8.1" - checksum: 10/af19ab5a1ec30cb4b2f91fd6df49a7442d5c4825a2e269b3712eded10eedd7f9efeaab96d57829880733fc55bcdd8e9b1d8589b4befb06667c731d08145e274d +"shell-quote@npm:1.8.3, shell-quote@npm:^1.6.1, shell-quote@npm:^1.7.3, shell-quote@npm:^1.8.1": + version: 1.8.3 + resolution: "shell-quote@npm:1.8.3" + checksum: 10/5473e354637c2bd698911224129c9a8961697486cff1fb221f234d71c153fc377674029b0223d1d3c953a68d451d79366abfe53d1a0b46ee1f28eb9ade928f4c languageName: node linkType: hard @@ -45846,15 +46142,6 @@ __metadata: languageName: node linkType: hard -"simple-swizzle@npm:^0.2.2": - version: 0.2.2 - resolution: "simple-swizzle@npm:0.2.2" - dependencies: - is-arrayish: "npm:^0.3.1" - checksum: 10/c6dffff17aaa383dae7e5c056fbf10cf9855a9f79949f20ee225c04f06ddde56323600e0f3d6797e82d08d006e93761122527438ee9531620031c08c9e0d73cc - languageName: node - linkType: hard - "simple-update-notifier@npm:^2.0.0": version: 2.0.0 resolution: "simple-update-notifier@npm:2.0.0" @@ -45962,10 +46249,10 @@ __metadata: languageName: node linkType: hard -"smol-toml@npm:^1.3.1": - version: 1.3.1 - resolution: "smol-toml@npm:1.3.1" - checksum: 10/b999828ea46cf44ae90b6293884d6a139dfb4545ac6f86cbd1002568a943a43d8895ad82413855d095eec0c0bc21d23413c0a25a26c7fad6395c2ce42c2fdbd0 +"smol-toml@npm:^1.5.2": + version: 1.5.2 + resolution: "smol-toml@npm:1.5.2" + checksum: 10/0a7e9192d1cbd04c3122224306de33962f4f5ac7e78a48b7c3795a675683b6efeb8f73ad3fabda7635926a510948cb4654a729d17b35ec43d56d35a71cf906f4 languageName: node linkType: hard @@ -46121,7 +46408,7 @@ __metadata: languageName: node linkType: hard -"source-map-js@npm:^1.2.1": +"source-map-js@npm:^1.0.1, source-map-js@npm:^1.2.1": version: 1.2.1 resolution: "source-map-js@npm:1.2.1" checksum: 10/ff9d8c8bf096d534a5b7707e0382ef827b4dd360a577d3f34d2b9f48e12c9d230b5747974ee7c607f0df65113732711bb701fe9ece3c7edbd43cb2294d707df3 @@ -46197,13 +46484,6 @@ __metadata: languageName: node linkType: hard -"spawn-command@npm:^0.0.2-1": - version: 0.0.2 - resolution: "spawn-command@npm:0.0.2" - checksum: 10/f13e8c3c63abd4a0b52fb567eba5f7940d480c5ed3ec61781d38a1850f179b1196c39e6efa2bbd301f82c1bf1cd7807abc8fbd8fc8e44bcaa3975a124c0d1657 - languageName: node - linkType: hard - "spawndamnit@npm:^3.0.1": version: 3.0.1 resolution: "spawndamnit@npm:3.0.1" @@ -46257,12 +46537,10 @@ __metadata: languageName: node linkType: hard -"split@npm:^1.0.0": - version: 1.0.1 - resolution: "split@npm:1.0.1" - dependencies: - through: "npm:2" - checksum: 10/12f4554a5792c7e98bb3e22b53c63bfa5ef89aa704353e1db608a55b51f5b12afaad6e4a8ecf7843c15f273f43cdadd67b3705cc43d48a75c2cf4641d51f7e7a +"split2@npm:^4.1.0": + version: 4.2.0 + resolution: "split2@npm:4.2.0" + checksum: 10/09bbefc11bcf03f044584c9764cd31a252d8e52cea29130950b26161287c11f519807c5e54bd9e5804c713b79c02cefe6a98f4688630993386be353e03f534ab languageName: node linkType: hard @@ -46382,7 +46660,7 @@ __metadata: languageName: node linkType: hard -"stack-utils@npm:^2.0.2, stack-utils@npm:^2.0.3": +"stack-utils@npm:^2.0.2, stack-utils@npm:^2.0.6": version: 2.0.6 resolution: "stack-utils@npm:2.0.6" dependencies: @@ -46473,21 +46751,21 @@ __metadata: languageName: node linkType: hard -"storybook@npm:^9.1.7": - version: 9.1.7 - resolution: "storybook@npm:9.1.7" +"storybook@npm:^10.1.10": + version: 10.1.10 + resolution: "storybook@npm:10.1.10" dependencies: "@storybook/global": "npm:^5.0.0" + "@storybook/icons": "npm:^2.0.0" "@testing-library/jest-dom": "npm:^6.6.3" "@testing-library/user-event": "npm:^14.6.1" "@vitest/expect": "npm:3.2.4" - "@vitest/mocker": "npm:3.2.4" "@vitest/spy": "npm:3.2.4" - better-opn: "npm:^3.0.2" - esbuild: "npm:^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0" - esbuild-register: "npm:^3.5.0" + esbuild: "npm:^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0 || ^0.26.0 || ^0.27.0" + open: "npm:^10.2.0" recast: "npm:^0.23.5" semver: "npm:^7.6.2" + use-sync-external-store: "npm:^1.5.0" ws: "npm:^8.18.0" peerDependencies: prettier: ^2 || ^3 @@ -46495,8 +46773,8 @@ __metadata: prettier: optional: true bin: - storybook: ./bin/index.cjs - checksum: 10/3ad9a953d1c54249153c7928e970d41f9b7ce376649f5a07f71c622b0b524784955c8d11afca8903e712c28655cce7c94d9e2b5f094ceb883d284ffdcd5f0d01 + storybook: ./dist/bin/dispatcher.js + checksum: 10/c1f01c7ab57e80d2f2ef3a5c49baad5904e77c8e079199ad134e98a7ae455d52422390cd704e64142b36668874c055670dbffe0e334e1f4d541ebd4384052dd7 languageName: node linkType: hard @@ -46627,9 +46905,9 @@ __metadata: linkType: hard "strict-event-emitter@npm:^0.4.3": - version: 0.4.3 - resolution: "strict-event-emitter@npm:0.4.3" - checksum: 10/ee335aba8a43bc6749d3337d78b9f6dbe8358d34b6eb38e7075dadf7f1cae621d96588663dda22dce17e6e7c7e281ddac79ca47421da8250bb4bf53b979508a5 + version: 0.4.6 + resolution: "strict-event-emitter@npm:0.4.6" + checksum: 10/abdbf59b6c45b599cc2f227fa473765d1510d155ebd22533e8ecb06110dfacb2ff07aece7fd528dde2b4f9e379d60f2687eee8af3fa2877c3ed88ee5b7ed2707 languageName: node linkType: hard @@ -46661,13 +46939,13 @@ __metadata: languageName: node linkType: hard -"string-length@npm:^4.0.1": - version: 4.0.1 - resolution: "string-length@npm:4.0.1" +"string-length@npm:^4.0.2": + version: 4.0.2 + resolution: "string-length@npm:4.0.2" dependencies: char-regex: "npm:^1.0.2" strip-ansi: "npm:^6.0.0" - checksum: 10/7bd3191668ddafa6f574a8b17a1bd1b085737d64ceefa51f72cdd19c45a730422cd70d984eee7584d6e5b5c84b6318633c6d6a720a4bfd7c58769985fa77573e + checksum: 10/ce85533ef5113fcb7e522bcf9e62cb33871aa99b3729cec5595f4447f660b0cefd542ca6df4150c97a677d58b0cb727a3fe09ac1de94071d05526c73579bf505 languageName: node linkType: hard @@ -46761,7 +47039,7 @@ __metadata: languageName: node linkType: hard -"string.prototype.trimend@npm:^1.0.8, string.prototype.trimend@npm:^1.0.9": +"string.prototype.trimend@npm:^1.0.9": version: 1.0.9 resolution: "string.prototype.trimend@npm:1.0.9" dependencies: @@ -46832,11 +47110,11 @@ __metadata: linkType: hard "strip-ansi@npm:^7.0.1, strip-ansi@npm:^7.1.0": - version: 7.1.0 - resolution: "strip-ansi@npm:7.1.0" + version: 7.1.2 + resolution: "strip-ansi@npm:7.1.2" dependencies: ansi-regex: "npm:^6.0.1" - checksum: 10/475f53e9c44375d6e72807284024ac5d668ee1d06010740dec0b9744f2ddf47de8d7151f80e5f6190fc8f384e802fdf9504b76a7e9020c9faee7103623338be2 + checksum: 10/db0e3f9654e519c8a33c50fc9304d07df5649388e7da06d3aabf66d29e5ad65d5e6315d8519d409c15b32fa82c1df7e11ed6f8cd50b0e4404463f0c9d77c8d0b languageName: node linkType: hard @@ -46921,10 +47199,10 @@ __metadata: languageName: node linkType: hard -"strip-json-comments@npm:5.0.1": - version: 5.0.1 - resolution: "strip-json-comments@npm:5.0.1" - checksum: 10/b314af70c6666a71133e309a571bdb87687fc878d9fd8b38ebed393a77b89835b92f191aa6b0bc10dfd028ba99eed6b6365985001d64c5aef32a4a82456a156b +"strip-json-comments@npm:5.0.3": + version: 5.0.3 + resolution: "strip-json-comments@npm:5.0.3" + checksum: 10/3ccbf26f278220f785e4b71f8a719a6a063d72558cc63cb450924254af258a4f4c008b8c9b055373a680dc7bd525be9e543ad742c177f8a7667e0b726258e0e4 languageName: node linkType: hard @@ -46956,12 +47234,12 @@ __metadata: languageName: node linkType: hard -"strtok3@npm:^10.2.2": - version: 10.3.1 - resolution: "strtok3@npm:10.3.1" +"strtok3@npm:^10.3.1": + version: 10.3.4 + resolution: "strtok3@npm:10.3.4" dependencies: "@tokenizer/token": "npm:^0.3.0" - checksum: 10/bb7950cc9ce98ec742a5db360630f0b004f16197959ae28d8c8dad4f8f0e405d71cfdc992483038ba29a0b4cbd7227618ad2492005b510d84a3fc5903df0c13f + checksum: 10/53be14a567dca149be56cb072eaa3c0fffd70d066acf800cf588b91558c6d475364ff8d550524ce0499fc4873a4b0d42ad8c542bfdb9fb39cba520ef2e2e9818 languageName: node linkType: hard @@ -47084,54 +47362,56 @@ __metadata: linkType: hard "sucrase@npm:^3.20.2": - version: 3.35.0 - resolution: "sucrase@npm:3.35.0" + version: 3.35.1 + resolution: "sucrase@npm:3.35.1" dependencies: "@jridgewell/gen-mapping": "npm:^0.3.2" commander: "npm:^4.0.0" - glob: "npm:^10.3.10" lines-and-columns: "npm:^1.1.6" mz: "npm:^2.7.0" pirates: "npm:^4.0.1" + tinyglobby: "npm:^0.2.11" ts-interface-checker: "npm:^0.1.9" bin: sucrase: bin/sucrase sucrase-node: bin/sucrase-node - checksum: 10/bc601558a62826f1c32287d4fdfa4f2c09fe0fec4c4d39d0e257fd9116d7d6227a18309721d4185ec84c9dc1af0d5ec0e05a42a337fbb74fc293e068549aacbe + checksum: 10/539f5c6ebc1ff8d449a89eb52b8c8944a730b9840ddadbd299a7d89ebcf16c3f4bc9aa59e1f2e112a502e5cf1508f7e02065f0e97c0435eb9a7058e997dfff5a languageName: node linkType: hard -"summary@npm:2.1.0": - version: 2.1.0 - resolution: "summary@npm:2.1.0" - checksum: 10/10ac12ce12c013b56ad44c37cfac206961f0993d98867b33b1b03a27b38a1cf8dd2db0b788883356c5335bbbb37d953772ef4a381d6fc8f408faf99f2bc54af5 - languageName: node - linkType: hard - -"superagent@npm:^9.0.1": - version: 9.0.2 - resolution: "superagent@npm:9.0.2" +"superagent@npm:^10.2.3": + version: 10.2.3 + resolution: "superagent@npm:10.2.3" dependencies: - component-emitter: "npm:^1.3.0" + component-emitter: "npm:^1.3.1" cookiejar: "npm:^2.1.4" - debug: "npm:^4.3.4" + debug: "npm:^4.3.7" fast-safe-stringify: "npm:^2.1.1" - form-data: "npm:^4.0.0" - formidable: "npm:^3.5.1" + form-data: "npm:^4.0.4" + formidable: "npm:^3.5.4" methods: "npm:^1.1.2" mime: "npm:2.6.0" - qs: "npm:^6.11.0" - checksum: 10/d3c0c9051ceec84d5b431eaa410ad81bcd53255cea57af1fc66d683a24c34f3ba4761b411072a9bf489a70e3d5b586a78a0e6f2eac6a561067e7d196ddab0907 + qs: "npm:^6.11.2" + checksum: 10/377bf938e68927dd772169c5285be27872bf6e84fac01c52bcd9396bc5b348c9ded8f8be54649510ec09a67bc5096055847b37cb01b3bca0eb06ff1856170e35 languageName: node linkType: hard "supertest@npm:^7.0.0, supertest@npm:^7.1.0": - version: 7.1.0 - resolution: "supertest@npm:7.1.0" + version: 7.1.4 + resolution: "supertest@npm:7.1.4" dependencies: methods: "npm:^1.1.2" - superagent: "npm:^9.0.1" - checksum: 10/20069f739a44821dfa4f7f397b9086ef31a358366331138f97945eedb2e231796e7c55b032125d3bd12f9839f089fbb809893dbc0f98edc57e12333b9f42b726 + superagent: "npm:^10.2.3" + checksum: 10/ecb5d41f2b62b257dbdcabac245c32b8e8fb264fe2636dd85c2c883569d23dc14adc0a471abb84187cbdb49bc36ad870ad355b4a0b85973f510fd57fc229e6cc + languageName: node + linkType: hard + +"supports-color@npm:8.1.1, supports-color@npm:^8.0.0, supports-color@npm:^8.1.1, supports-color@npm:~8.1.1": + version: 8.1.1 + resolution: "supports-color@npm:8.1.1" + dependencies: + has-flag: "npm:^4.0.0" + checksum: 10/157b534df88e39c5518c5e78c35580c1eca848d7dbaf31bbe06cdfc048e22c7ff1a9d046ae17b25691128f631a51d9ec373c1b740c12ae4f0de6e292037e4282 languageName: node linkType: hard @@ -47162,15 +47442,6 @@ __metadata: languageName: node linkType: hard -"supports-color@npm:^8.0.0, supports-color@npm:^8.1.0, supports-color@npm:^8.1.1, supports-color@npm:~8.1.1": - version: 8.1.1 - resolution: "supports-color@npm:8.1.1" - dependencies: - has-flag: "npm:^4.0.0" - checksum: 10/157b534df88e39c5518c5e78c35580c1eca848d7dbaf31bbe06cdfc048e22c7ff1a9d046ae17b25691128f631a51d9ec373c1b740c12ae4f0de6e292037e4282 - languageName: node - linkType: hard - "supports-preserve-symlinks-flag@npm:^1.0.0": version: 1.0.0 resolution: "supports-preserve-symlinks-flag@npm:1.0.0" @@ -47195,17 +47466,17 @@ __metadata: languageName: node linkType: hard -"swagger-client@npm:^3.35.5": - version: 3.35.6 - resolution: "swagger-client@npm:3.35.6" +"swagger-client@npm:^3.36.0": + version: 3.36.0 + resolution: "swagger-client@npm:3.36.0" dependencies: "@babel/runtime-corejs3": "npm:^7.22.15" "@scarf/scarf": "npm:=1.4.0" - "@swagger-api/apidom-core": "npm:>=1.0.0-beta.41 <1.0.0-rc.0" - "@swagger-api/apidom-error": "npm:>=1.0.0-beta.41 <1.0.0-rc.0" - "@swagger-api/apidom-json-pointer": "npm:>=1.0.0-beta.41 <1.0.0-rc.0" - "@swagger-api/apidom-ns-openapi-3-1": "npm:>=1.0.0-beta.41 <1.0.0-rc.0" - "@swagger-api/apidom-reference": "npm:>=1.0.0-beta.41 <1.0.0-rc.0" + "@swagger-api/apidom-core": "npm:^1.0.0-rc.1" + "@swagger-api/apidom-error": "npm:^1.0.0-rc.1" + "@swagger-api/apidom-json-pointer": "npm:^1.0.0-rc.1" + "@swagger-api/apidom-ns-openapi-3-1": "npm:^1.0.0-rc.1" + "@swagger-api/apidom-reference": "npm:^1.0.0-rc.1" "@swaggerexpert/cookie": "npm:^2.0.2" deepmerge: "npm:~4.3.0" fast-json-patch: "npm:^3.0.0-1" @@ -47217,13 +47488,13 @@ __metadata: openapi-server-url-templating: "npm:^1.3.0" ramda: "npm:^0.30.1" ramda-adjunct: "npm:^5.1.0" - checksum: 10/fb6582dc45c2ae6a26ae4cc80f0a3d97e31f3b058676951f93670828f2f30f5d44ecd7c029465f5452b251a533be329a955c92cec11be7128baa5e2e963e6f9d + checksum: 10/ea69e017cf266b44e2ef8e01a862975789bc62a537ab28baffb80b51d99640e35fac44eea5b744e98d0f6151fa290a09f840a5ad3f0103ead508e628b10dbc7b languageName: node linkType: hard "swagger-ui-react@npm:^5.27.1": - version: 5.29.0 - resolution: "swagger-ui-react@npm:5.29.0" + version: 5.30.3 + resolution: "swagger-ui-react@npm:5.30.3" dependencies: "@babel/runtime-corejs3": "npm:^7.27.1" "@scarf/scarf": "npm:=1.4.0" @@ -47232,11 +47503,11 @@ __metadata: classnames: "npm:^2.5.1" css.escape: "npm:1.5.1" deep-extend: "npm:0.6.0" - dompurify: "npm:=3.2.4" + dompurify: "npm:=3.2.6" ieee754: "npm:^1.2.1" immutable: "npm:^3.x.x" js-file-download: "npm:^0.4.12" - js-yaml: "npm:=4.1.0" + js-yaml: "npm:=4.1.1" lodash: "npm:^4.17.21" prop-types: "npm:^15.8.1" randexp: "npm:^0.5.3" @@ -47247,14 +47518,14 @@ __metadata: react-immutable-pure-component: "npm:^2.2.0" react-inspector: "npm:^6.0.1" react-redux: "npm:^9.2.0" - react-syntax-highlighter: "npm:^15.6.1" + react-syntax-highlighter: "npm:^16.0.0" redux: "npm:^5.0.1" redux-immutable: "npm:^4.0.0" remarkable: "npm:^2.0.1" reselect: "npm:^5.1.1" serialize-error: "npm:^8.1.0" sha.js: "npm:^2.4.12" - swagger-client: "npm:^3.35.5" + swagger-client: "npm:^3.36.0" url-parse: "npm:^1.5.10" xml: "npm:=1.0.1" xml-but-prettier: "npm:^1.0.1" @@ -47262,7 +47533,7 @@ __metadata: peerDependencies: react: ">=16.8.0 <20" react-dom: ">=16.8.0 <20" - checksum: 10/994a7b06b17fe12693a7a09057161723f5e2ab2c80c747879951a54f0d7a0cd4c65c139bdaf229f13d61f5dd61c2b63218881fc23081ced0cc91745b48d806d5 + checksum: 10/6f466414072806e60a3e36d58029b0679cd80cd9488e79a2142bebcd0829efa587f1b3249c2feab3ab692b3a70f5b90038f3fd14430f8ae41c6ec904f8041f79 languageName: node linkType: hard @@ -47279,14 +47550,14 @@ __metadata: linkType: hard "swr@npm:^2.0.0, swr@npm:^2.2.5": - version: 2.2.5 - resolution: "swr@npm:2.2.5" + version: 2.3.7 + resolution: "swr@npm:2.3.7" dependencies: - client-only: "npm:^0.0.1" - use-sync-external-store: "npm:^1.2.0" + dequal: "npm:^2.0.3" + use-sync-external-store: "npm:^1.4.0" peerDependencies: - react: ^16.11.0 || ^17.0.0 || ^18.0.0 - checksum: 10/f02b3bd5a198a0f62f9a53d7c0528c4a58aa61a43310bea169614b6e873dadb52599e856ef0775405b6aa7409835343da0cf328948aa892aa309bf4b7e7d6902 + react: ^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + checksum: 10/a7a9f141ea31146f2787c36854ca0998f65d38503fe73fc3c0695ebba37821487eb43e62cece15d1739bc531e8430c15ac5f6ea695293e861fdbc2de92514d96 languageName: node linkType: hard @@ -47304,6 +47575,15 @@ __metadata: languageName: node linkType: hard +"synckit@npm:^0.11.8": + version: 0.11.11 + resolution: "synckit@npm:0.11.11" + dependencies: + "@pkgr/core": "npm:^0.2.9" + checksum: 10/6ecd88212b5be80004376b6ea74babcba284566ff59a50d8803afcaa78c165b5d268635c1dd84532ee3f690a979409e1eda225a8a35bed2d135ffdcea06ce7b0 + languageName: node + linkType: hard + "tapable@npm:^1.0.0": version: 1.1.3 resolution: "tapable@npm:1.1.3" @@ -47497,8 +47777,8 @@ __metadata: linkType: hard "terser-webpack-plugin@npm:*, terser-webpack-plugin@npm:^5.1.3, terser-webpack-plugin@npm:^5.3.11": - version: 5.3.15 - resolution: "terser-webpack-plugin@npm:5.3.15" + version: 5.3.16 + resolution: "terser-webpack-plugin@npm:5.3.16" dependencies: "@jridgewell/trace-mapping": "npm:^0.3.25" jest-worker: "npm:^27.4.5" @@ -47514,7 +47794,7 @@ __metadata: optional: true uglify-js: optional: true - checksum: 10/54059f0fe56c16a1e30032b33b1321051d562b5292adcf88d160c7d8e74779867014e98548ae59ba5283fe60f8725bea37c16b42f2c89ee430382cff74198b7a + checksum: 10/09dfbff602acfa114cdd174254b69a04adbc47856021ab351e37982202fd1ec85e0b62ffd5864c98beb8e96aef2f43da490b3448b4541db539c2cff6607394a6 languageName: node linkType: hard @@ -47646,7 +47926,7 @@ __metadata: languageName: node linkType: hard -"through@npm:2, through@npm:^2.3.6, through@npm:~2.3": +"through@npm:^2.3.6, through@npm:~2.3": version: 2.3.8 resolution: "through@npm:2.3.8" checksum: 10/5da78346f70139a7d213b65a0106f3c398d6bc5301f9248b5275f420abc2c4b1e77c2abc72d218dedc28c41efb2e7c312cb76a7730d04f9c2d37d247da3f4198 @@ -47717,7 +47997,7 @@ __metadata: languageName: node linkType: hard -"tinyglobby@npm:^0.2.15, tinyglobby@npm:^0.2.9": +"tinyglobby@npm:^0.2.11, tinyglobby@npm:^0.2.15, tinyglobby@npm:^0.2.9": version: 0.2.15 resolution: "tinyglobby@npm:0.2.15" dependencies: @@ -47748,10 +48028,10 @@ __metadata: languageName: node linkType: hard -"tldts-core@npm:^6.1.51": - version: 6.1.51 - resolution: "tldts-core@npm:6.1.51" - checksum: 10/861d5736d714abfd649c0545b9aae27058cd76f28f83077328fde6ba5ba9f7f107227d09406cfd38baf6215fc7840545ed0b17352f2f364182265887774394dc +"tldts-core@npm:^6.1.86": + version: 6.1.86 + resolution: "tldts-core@npm:6.1.86" + checksum: 10/cb5dff9cc15661ac773a2099e98c99a5cb3cebc35909c23cc4261ff7992032c7501995ae995de3574dbbf3431e59c47496534d52f5e96abcb231f0e72144c020 languageName: node linkType: hard @@ -47763,13 +48043,13 @@ __metadata: linkType: hard "tldts@npm:^6.1.32": - version: 6.1.51 - resolution: "tldts@npm:6.1.51" + version: 6.1.86 + resolution: "tldts@npm:6.1.86" dependencies: - tldts-core: "npm:^6.1.51" + tldts-core: "npm:^6.1.86" bin: tldts: bin/cli.js - checksum: 10/42e664469b1497af2fc6ac4cbf94f8a6507fcd23bf59521ace34223e36cb74ec7a003cf42834fcc4ba159c7448aa7e6f0f79f1f2fb8145b2e72ef44e87f035ec + checksum: 10/f7e66824e44479ccdda55ea556af14ce61c4d27708be403e3f90631defde49f82a580e1ca07187cc7e3b349e257a30c2808a22903f3a0548e136ebb609ccc109 languageName: node linkType: hard @@ -47784,15 +48064,6 @@ __metadata: languageName: node linkType: hard -"tmp@npm:^0.0.33": - version: 0.0.33 - resolution: "tmp@npm:0.0.33" - dependencies: - os-tmpdir: "npm:~1.0.2" - checksum: 10/09c0abfd165cff29b32be42bc35e80b8c64727d97dedde6550022e88fa9fd39a084660415ed8e3ebaa2aca1ee142f86df8b31d4196d4f81c774a3a20fd4b6abf - languageName: node - linkType: hard - "tmp@npm:^0.2.5": version: 0.2.5 resolution: "tmp@npm:0.2.5" @@ -47886,24 +48157,12 @@ __metadata: languageName: node linkType: hard -"tough-cookie@npm:^4.0.0": - version: 4.1.4 - resolution: "tough-cookie@npm:4.1.4" - dependencies: - psl: "npm:^1.1.33" - punycode: "npm:^2.1.1" - universalify: "npm:^0.2.0" - url-parse: "npm:^1.5.3" - checksum: 10/75663f4e2cd085f16af0b217e4218772adf0617fb3227171102618a54ce0187a164e505d61f773ed7d65988f8ff8a8f935d381f87da981752c1171b076b4afac - languageName: node - linkType: hard - "tough-cookie@npm:^5.0.0": - version: 5.0.0 - resolution: "tough-cookie@npm:5.0.0" + version: 5.1.2 + resolution: "tough-cookie@npm:5.1.2" dependencies: tldts: "npm:^6.1.32" - checksum: 10/a98d3846ed386e399e8b470c1eb08a6a296944246eabc55c9fe79d629bd2cdaa62f5a6572f271fe0060987906bd20468d72a219a3b4cbe51086bea48d2d677b6 + checksum: 10/de430e6e6d34b794137e05b8ac2aa6b74ebbe6cdceb4126f168cf1e76101162a4b2e0e7587c3b70e728bd8654fc39958b2035be7619ee6f08e7257610ba4cd04 languageName: node linkType: hard @@ -47916,21 +48175,12 @@ __metadata: languageName: node linkType: hard -"tr46@npm:^3.0.0": - version: 3.0.0 - resolution: "tr46@npm:3.0.0" - dependencies: - punycode: "npm:^2.1.1" - checksum: 10/b09a15886cbfaee419a3469081223489051ce9dca3374dd9500d2378adedbee84a3c73f83bfdd6bb13d53657753fc0d4e20a46bfcd3f1b9057ef528426ad7ce4 - languageName: node - linkType: hard - -"tr46@npm:^5.0.0": - version: 5.0.0 - resolution: "tr46@npm:5.0.0" +"tr46@npm:^5.1.0": + version: 5.1.1 + resolution: "tr46@npm:5.1.1" dependencies: punycode: "npm:^2.3.1" - checksum: 10/29155adb167d048d3c95d181f7cb5ac71948b4e8f3070ec455986e1f34634acae50ae02a3c8d448121c3afe35b76951cd46ed4c128fd80264280ca9502237a3e + checksum: 10/833a0e1044574da5790148fd17866d4ddaea89e022de50279967bcd6b28b4ce0d30d59eb3acf9702b60918975b3bad481400337e3a2e6326cffa5c77b874753d languageName: node linkType: hard @@ -47959,7 +48209,7 @@ __metadata: languageName: node linkType: hard -"tree-kill@npm:^1.2.2": +"tree-kill@npm:1.2.2, tree-kill@npm:^1.2.2": version: 1.2.2 resolution: "tree-kill@npm:1.2.2" bin: @@ -48057,7 +48307,7 @@ __metadata: languageName: node linkType: hard -"ts-api-utils@npm:^2.0.1, ts-api-utils@npm:^2.1.0": +"ts-api-utils@npm:^2.1.0": version: 2.1.0 resolution: "ts-api-utils@npm:2.1.0" peerDependencies: @@ -48067,14 +48317,14 @@ __metadata: linkType: hard "ts-checker-rspack-plugin@npm:^1.1.5": - version: 1.1.5 - resolution: "ts-checker-rspack-plugin@npm:1.1.5" + version: 1.2.1 + resolution: "ts-checker-rspack-plugin@npm:1.2.1" dependencies: "@babel/code-frame": "npm:^7.27.1" - "@rspack/lite-tapable": "npm:^1.0.1" + "@rspack/lite-tapable": "npm:^1.1.0" chokidar: "npm:^3.6.0" is-glob: "npm:^4.0.3" - memfs: "npm:^4.28.0" + memfs: "npm:^4.51.1" minimatch: "npm:^9.0.5" picocolors: "npm:^1.1.1" peerDependencies: @@ -48083,7 +48333,7 @@ __metadata: peerDependenciesMeta: "@rspack/core": optional: true - checksum: 10/d43f87a5860f3b8f528bf8f43c78c2d958a18fa484d791a204047fc5672134fd689665021ee25b07f9f9d8c807cd291978f58b789bf531b4704a9a4e3ad84735 + checksum: 10/c2e4a4e0cfda6a358e2b3c134446359f74ed57787c23cb270ae6d72bfa1fae91e42968d04c9c5921a39c2995869a56fb8f3c8f906f24d7a94a33dca31ece2f22 languageName: node linkType: hard @@ -48507,19 +48757,19 @@ __metadata: linkType: hard "typedoc@npm:^0.28.0": - version: 0.28.9 - resolution: "typedoc@npm:0.28.9" + version: 0.28.15 + resolution: "typedoc@npm:0.28.15" dependencies: - "@gerrit0/mini-shiki": "npm:^3.9.0" + "@gerrit0/mini-shiki": "npm:^3.17.0" lunr: "npm:^2.3.9" markdown-it: "npm:^14.1.0" minimatch: "npm:^9.0.5" - yaml: "npm:^2.8.0" + yaml: "npm:^2.8.1" peerDependencies: typescript: 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.9.x bin: typedoc: bin/typedoc - checksum: 10/b803651a2c1295c293c68b97bc8aa722ba89fe253b23104aab0f751f30921b69a813352173bf09fa65efc0c6dfbce11305f365218ee7298f955a0993907da36d + checksum: 10/c4bfed5435c5fbd8a63f0e058b7d845c83872c2648c5db49c2ace613013dbce55ca04b30630db2c72abbbd0850d8c110781cd5da6c508e781f7a7845a0e9c0d7 languageName: node linkType: hard @@ -48968,13 +49218,6 @@ __metadata: languageName: node linkType: hard -"universalify@npm:^0.2.0": - version: 0.2.0 - resolution: "universalify@npm:0.2.0" - checksum: 10/e86134cb12919d177c2353196a4cc09981524ee87abf621f7bc8d249dbbbebaec5e7d1314b96061497981350df786e4c5128dbf442eba104d6e765bc260678b5 - languageName: node - linkType: hard - "universalify@npm:^2.0.0": version: 2.0.0 resolution: "universalify@npm:2.0.0" @@ -48998,13 +49241,25 @@ __metadata: languageName: node linkType: hard -"unplugin@npm:^1.3.1": - version: 1.16.1 - resolution: "unplugin@npm:1.16.1" +"unplugin-utils@npm:^0.2.4": + version: 0.2.5 + resolution: "unplugin-utils@npm:0.2.5" dependencies: - acorn: "npm:^8.14.0" + pathe: "npm:^2.0.3" + picomatch: "npm:^4.0.3" + checksum: 10/f9ff443089de3159ccab001d075fa4245a741696182dbe6b9708aa01945ded163bd846a3f4099132a2195de3fcbefe404a05380e4697faa4c5917c89f97a2361 + languageName: node + linkType: hard + +"unplugin@npm:^2.3.5": + version: 2.3.11 + resolution: "unplugin@npm:2.3.11" + dependencies: + "@jridgewell/remapping": "npm:^2.3.5" + acorn: "npm:^8.15.0" + picomatch: "npm:^4.0.3" webpack-virtual-modules: "npm:^0.6.2" - checksum: 10/4b46d7d2a63d334a45111ba57a266b3f8993ef12a72b77d7b31ffc455e8a9bef9c0e37ea463eb409dbf7ccec0b9868aeb845dd42c690d9288e4b8ac2d90fbefd + checksum: 10/7b4adbfaac8894e8491c452c0b67c612b57e103761e842d9013ebea89a4ae92a78df4ec0aa30e5e3eaaefd47dd287973d5a662271624b7346a15d9236d257f9d languageName: node linkType: hard @@ -49015,6 +49270,73 @@ __metadata: languageName: node linkType: hard +"unrs-resolver@npm:^1.7.11": + version: 1.11.1 + resolution: "unrs-resolver@npm:1.11.1" + dependencies: + "@unrs/resolver-binding-android-arm-eabi": "npm:1.11.1" + "@unrs/resolver-binding-android-arm64": "npm:1.11.1" + "@unrs/resolver-binding-darwin-arm64": "npm:1.11.1" + "@unrs/resolver-binding-darwin-x64": "npm:1.11.1" + "@unrs/resolver-binding-freebsd-x64": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm-gnueabihf": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm-musleabihf": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm64-musl": "npm:1.11.1" + "@unrs/resolver-binding-linux-ppc64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-riscv64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-riscv64-musl": "npm:1.11.1" + "@unrs/resolver-binding-linux-s390x-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-x64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-x64-musl": "npm:1.11.1" + "@unrs/resolver-binding-wasm32-wasi": "npm:1.11.1" + "@unrs/resolver-binding-win32-arm64-msvc": "npm:1.11.1" + "@unrs/resolver-binding-win32-ia32-msvc": "npm:1.11.1" + "@unrs/resolver-binding-win32-x64-msvc": "npm:1.11.1" + napi-postinstall: "npm:^0.3.0" + dependenciesMeta: + "@unrs/resolver-binding-android-arm-eabi": + optional: true + "@unrs/resolver-binding-android-arm64": + optional: true + "@unrs/resolver-binding-darwin-arm64": + optional: true + "@unrs/resolver-binding-darwin-x64": + optional: true + "@unrs/resolver-binding-freebsd-x64": + optional: true + "@unrs/resolver-binding-linux-arm-gnueabihf": + optional: true + "@unrs/resolver-binding-linux-arm-musleabihf": + optional: true + "@unrs/resolver-binding-linux-arm64-gnu": + optional: true + "@unrs/resolver-binding-linux-arm64-musl": + optional: true + "@unrs/resolver-binding-linux-ppc64-gnu": + optional: true + "@unrs/resolver-binding-linux-riscv64-gnu": + optional: true + "@unrs/resolver-binding-linux-riscv64-musl": + optional: true + "@unrs/resolver-binding-linux-s390x-gnu": + optional: true + "@unrs/resolver-binding-linux-x64-gnu": + optional: true + "@unrs/resolver-binding-linux-x64-musl": + optional: true + "@unrs/resolver-binding-wasm32-wasi": + optional: true + "@unrs/resolver-binding-win32-arm64-msvc": + optional: true + "@unrs/resolver-binding-win32-ia32-msvc": + optional: true + "@unrs/resolver-binding-win32-x64-msvc": + optional: true + checksum: 10/4de653508cbaae47883a896bd5cdfef0e5e87b428d62620d16fd35cd534beaebf08ebf0cf2f8b4922aa947b2fe745180facf6cc3f39ba364f7ce0f974cb06a70 + languageName: node + linkType: hard + "untildify@npm:^4.0.0": version: 4.0.0 resolution: "untildify@npm:4.0.0" @@ -49106,7 +49428,7 @@ __metadata: languageName: node linkType: hard -"url-parse@npm:^1.5.10, url-parse@npm:^1.5.3": +"url-parse@npm:^1.5.10": version: 1.5.10 resolution: "url-parse@npm:1.5.10" dependencies: @@ -49263,12 +49585,12 @@ __metadata: languageName: node linkType: hard -"use-sync-external-store@npm:^1.2.0, use-sync-external-store@npm:^1.4.0": - version: 1.4.0 - resolution: "use-sync-external-store@npm:1.4.0" +"use-sync-external-store@npm:^1.4.0, use-sync-external-store@npm:^1.5.0": + version: 1.6.0 + resolution: "use-sync-external-store@npm:1.6.0" peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - checksum: 10/08bf581a8a2effaefc355e9d18ed025d436230f4cc973db2f593166df357cf63e47b9097b6e5089b594758bde322e1737754ad64905e030d70f8ff7ee671fd01 + checksum: 10/b40ad2847ba220695bff2d4ba4f4d60391c0fb4fb012faa7a4c18eb38b69181936f5edc55a522c4d20a788d1a879b73c3810952c9d0fd128d01cb3f22042c09e languageName: node linkType: hard @@ -49517,8 +49839,8 @@ __metadata: linkType: hard "vite@npm:^7.1.5": - version: 7.1.5 - resolution: "vite@npm:7.1.5" + version: 7.2.6 + resolution: "vite@npm:7.2.6" dependencies: esbuild: "npm:^0.25.0" fdir: "npm:^6.5.0" @@ -49567,7 +49889,7 @@ __metadata: optional: true bin: vite: bin/vite.js - checksum: 10/59edeef7e98757a668b2ad8a1731a5657fa83e22a165a36b7359225ea98a9be39b2f486710c0cf5085edb85daee7c8b6b6b0bd85d0ef32a1aa84aef71aabd0f0 + checksum: 10/c640ed9c91957749287af2f483f5b5024a56718ba7cf32b0e2c398772fdf7fdb9fd5f97665c41712d4e9422c14009e283d0b69ac1b64b4f91474625bebe324de languageName: node linkType: hard @@ -49585,15 +49907,6 @@ __metadata: languageName: node linkType: hard -"w3c-hr-time@npm:^1.0.2": - version: 1.0.2 - resolution: "w3c-hr-time@npm:1.0.2" - dependencies: - browser-process-hrtime: "npm:^1.0.0" - checksum: 10/03851d90c236837c24c2983f5a8806a837c6515b21d52e5f29776b07cc08695779303d481454d768308489f00dd9d3232d595acaa5b2686d199465a4d9f7b283 - languageName: node - linkType: hard - "w3c-keyname@npm:^2.2.4": version: 2.2.4 resolution: "w3c-keyname@npm:2.2.4" @@ -49601,15 +49914,6 @@ __metadata: languageName: node linkType: hard -"w3c-xmlserializer@npm:^3.0.0": - version: 3.0.0 - resolution: "w3c-xmlserializer@npm:3.0.0" - dependencies: - xml-name-validator: "npm:^4.0.0" - checksum: 10/b4d73e20be283cc9975573a88979d15c08daa9c00911f8c777ef2af74eea11ba635fec18647ff0374ce880ec32ae573d17bd0f787053fc3085a530345b2feab6 - languageName: node - linkType: hard - "w3c-xmlserializer@npm:^5.0.0": version: 5.0.0 resolution: "w3c-xmlserializer@npm:5.0.0" @@ -49633,6 +49937,13 @@ __metadata: languageName: node linkType: hard +"walk-up-path@npm:^4.0.0": + version: 4.0.0 + resolution: "walk-up-path@npm:4.0.0" + checksum: 10/6a230b20e5de296895116dc12b09dafaec1f72b8060c089533d296e241aff059dfaebe0d015c77467f857e4b40c78e08f7481add76f340233a1f34fa8af9ed63 + languageName: node + linkType: hard + "walkdir@npm:^0.4.1": version: 0.4.1 resolution: "walkdir@npm:0.4.1" @@ -49876,15 +50187,6 @@ __metadata: languageName: node linkType: hard -"whatwg-encoding@npm:^2.0.0": - version: 2.0.0 - resolution: "whatwg-encoding@npm:2.0.0" - dependencies: - iconv-lite: "npm:0.6.3" - checksum: 10/162d712d88fd134a4fe587e53302da812eb4215a1baa4c394dfd86eff31d0a079ff932c05233857997de07481093358d6e7587997358f49b8a580a777be22089 - languageName: node - linkType: hard - "whatwg-encoding@npm:^3.1.1": version: 3.1.1 resolution: "whatwg-encoding@npm:3.1.1" @@ -49908,7 +50210,7 @@ __metadata: languageName: node linkType: hard -"whatwg-url@npm:15.1.0": +"whatwg-url@npm:15.1.0, whatwg-url@npm:^15.0.0, whatwg-url@npm:^15.1.0": version: 15.1.0 resolution: "whatwg-url@npm:15.1.0" dependencies: @@ -49918,23 +50220,13 @@ __metadata: languageName: node linkType: hard -"whatwg-url@npm:^11.0.0": - version: 11.0.0 - resolution: "whatwg-url@npm:11.0.0" - dependencies: - tr46: "npm:^3.0.0" - webidl-conversions: "npm:^7.0.0" - checksum: 10/dfcd51c6f4bfb54685528fb10927f3fd3d7c809b5671beef4a8cdd7b1408a7abf3343a35bc71dab83a1424f1c1e92cc2700d7930d95d231df0fac361de0c7648 - languageName: node - linkType: hard - "whatwg-url@npm:^14.0.0": - version: 14.0.0 - resolution: "whatwg-url@npm:14.0.0" + version: 14.2.0 + resolution: "whatwg-url@npm:14.2.0" dependencies: - tr46: "npm:^5.0.0" + tr46: "npm:^5.1.0" webidl-conversions: "npm:^7.0.0" - checksum: 10/67ea7a359a90663b28c816d76379b4be62d13446e9a4c0ae0b5ae0294b1c22577750fcdceb40827bb35a61777b7093056953c856604a28b37d6a209ba59ad062 + checksum: 10/f0a95b0601c64f417c471536a2d828b4c16fe37c13662483a32f02f183ed0f441616609b0663fb791e524e8cd56d9a86dd7366b1fc5356048ccb09b576495e7c languageName: node linkType: hard @@ -50090,7 +50382,7 @@ __metadata: languageName: node linkType: hard -"winston-transport@npm:^4.5.0, winston-transport@npm:^4.7.0": +"winston-transport@npm:^4.5.0, winston-transport@npm:^4.7.0, winston-transport@npm:^4.9.0": version: 4.9.0 resolution: "winston-transport@npm:4.9.0" dependencies: @@ -50102,21 +50394,21 @@ __metadata: linkType: hard "winston@npm:^3.13.0, winston@npm:^3.2.1": - version: 3.16.0 - resolution: "winston@npm:3.16.0" + version: 3.18.3 + resolution: "winston@npm:3.18.3" dependencies: "@colors/colors": "npm:^1.6.0" - "@dabh/diagnostics": "npm:^2.0.2" + "@dabh/diagnostics": "npm:^2.0.8" async: "npm:^3.2.3" is-stream: "npm:^2.0.0" - logform: "npm:^2.6.0" + logform: "npm:^2.7.0" one-time: "npm:^1.0.0" readable-stream: "npm:^3.4.0" safe-stable-stringify: "npm:^2.3.1" stack-trace: "npm:0.0.x" triple-beam: "npm:^1.3.0" - winston-transport: "npm:^4.7.0" - checksum: 10/cacec5268a965dcd3752bfe223d36eb003ac86b0cabc3d794521dfa6f937f78c86c8da84a53956c0f32169a55b438f6db0ee2aa028d57a2bcd69e1895a2e9d97 + winston-transport: "npm:^4.9.0" + checksum: 10/0d94690e051c625ff5a2731b3057ddaa709445cc791c707c56f99ad7b5bf3eebe634656f707c01c9409dc21dbc118903464f80e29c0cb438b1cc2739c0135e51 languageName: node linkType: hard @@ -50197,7 +50489,7 @@ __metadata: languageName: node linkType: hard -"write-file-atomic@npm:^4.0.0, write-file-atomic@npm:^4.0.2": +"write-file-atomic@npm:^4.0.0": version: 4.0.2 resolution: "write-file-atomic@npm:4.0.2" dependencies: @@ -50217,7 +50509,7 @@ __metadata: languageName: node linkType: hard -"ws@npm:*, ws@npm:^8.12.0, ws@npm:^8.13.0, ws@npm:^8.17.1, ws@npm:^8.18.0, ws@npm:^8.18.2, ws@npm:^8.8.0": +"ws@npm:*, ws@npm:^8.12.0, ws@npm:^8.13.0, ws@npm:^8.17.1, ws@npm:^8.18.0, ws@npm:^8.18.2, ws@npm:^8.18.3, ws@npm:^8.8.0": version: 8.18.3 resolution: "ws@npm:8.18.3" peerDependencies: @@ -50262,6 +50554,15 @@ __metadata: languageName: node linkType: hard +"wsl-utils@npm:^0.1.0": + version: 0.1.0 + resolution: "wsl-utils@npm:0.1.0" + dependencies: + is-wsl: "npm:^3.1.0" + checksum: 10/de4c92187e04c3c27b4478f410a02e81c351dc85efa3447bf1666f34fc80baacd890a6698ec91995631714086992036013286aea3d77e6974020d40a08e00aec + languageName: node + linkType: hard + "xcase@npm:^2.0.1": version: 2.0.1 resolution: "xcase@npm:2.0.1" @@ -50285,13 +50586,6 @@ __metadata: languageName: node linkType: hard -"xml-name-validator@npm:^4.0.0": - version: 4.0.0 - resolution: "xml-name-validator@npm:4.0.0" - checksum: 10/f9582a3f281f790344a471c207516e29e293c6041b2c20d84dd6e58832cd7c19796c47e108fd4fd4b164a5e72ad94f2268f8ace8231cde4a2c6428d6aa220f92 - languageName: node - linkType: hard - "xml-name-validator@npm:^5.0.0": version: 5.0.0 resolution: "xml-name-validator@npm:5.0.0" @@ -50377,7 +50671,7 @@ __metadata: languageName: node 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.3.4, yaml@npm:^2.7.0, yaml@npm:^2.8.0": +"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.3.4, yaml@npm:^2.7.0, yaml@npm:^2.8.1": version: 2.8.2 resolution: "yaml@npm:2.8.2" bin: @@ -50400,6 +50694,21 @@ __metadata: languageName: node linkType: hard +"yargs@npm:17.7.2, yargs@npm:^17.1.1, yargs@npm:^17.3.1, yargs@npm:^17.7.1, yargs@npm:^17.7.2": + version: 17.7.2 + resolution: "yargs@npm:17.7.2" + dependencies: + cliui: "npm:^8.0.1" + escalade: "npm:^3.1.1" + get-caller-file: "npm:^2.0.5" + require-directory: "npm:^2.1.1" + string-width: "npm:^4.2.3" + y18n: "npm:^5.0.5" + yargs-parser: "npm:^21.1.1" + checksum: 10/abb3e37678d6e38ea85485ed86ebe0d1e3464c640d7d9069805ea0da12f69d5a32df8e5625e370f9c96dd1c2dc088ab2d0a4dd32af18222ef3c4224a19471576 + languageName: node + linkType: hard + "yargs@npm:^16.2.0": version: 16.2.0 resolution: "yargs@npm:16.2.0" @@ -50415,21 +50724,6 @@ __metadata: languageName: node linkType: hard -"yargs@npm:^17.1.1, yargs@npm:^17.3.1, yargs@npm:^17.7.1, yargs@npm:^17.7.2": - version: 17.7.2 - resolution: "yargs@npm:17.7.2" - dependencies: - cliui: "npm:^8.0.1" - escalade: "npm:^3.1.1" - get-caller-file: "npm:^2.0.5" - require-directory: "npm:^2.1.1" - string-width: "npm:^4.2.3" - y18n: "npm:^5.0.5" - yargs-parser: "npm:^21.1.1" - checksum: 10/abb3e37678d6e38ea85485ed86ebe0d1e3464c640d7d9069805ea0da12f69d5a32df8e5625e370f9c96dd1c2dc088ab2d0a4dd32af18222ef3c4224a19471576 - languageName: node - linkType: hard - "yarn-plugin-backstage@workspace:packages/yarn-plugin": version: 0.0.0-use.local resolution: "yarn-plugin-backstage@workspace:packages/yarn-plugin" @@ -50548,13 +50842,6 @@ __metadata: languageName: node linkType: hard -"yocto-queue@npm:^1.0.0": - version: 1.2.1 - resolution: "yocto-queue@npm:1.2.1" - checksum: 10/0843d6c2c0558e5c06e98edf9c17942f25c769e21b519303a5c2adefd5b738c9b2054204dc856ac0cd9d134b1bc27d928ce84fd23c9e2423b7e013d5a6f50577 - languageName: node - linkType: hard - "yoctocolors-cjs@npm:^2.1.2": version: 2.1.2 resolution: "yoctocolors-cjs@npm:2.1.2" @@ -50596,16 +50883,16 @@ __metadata: languageName: node linkType: hard -"zod-to-json-schema@npm:^3.20.4, zod-to-json-schema@npm:^3.21.4, zod-to-json-schema@npm:^3.24.1": - version: 3.24.6 - resolution: "zod-to-json-schema@npm:3.24.6" +"zod-to-json-schema@npm:^3.20.4, zod-to-json-schema@npm:^3.21.4, zod-to-json-schema@npm:^3.25.0": + version: 3.25.0 + resolution: "zod-to-json-schema@npm:3.25.0" peerDependencies: - zod: ^3.24.1 - checksum: 10/a2c30cf1f250aa79a7f975e65b4236d1abafafd63b43c43475057f28ce6e13f4c882391553c656fb426fd09665e6ae293c2439b4ed8600863beda43fb1a56922 + zod: ^3.25 || ^4 + checksum: 10/cb932e20b5b5e64c75b2c34a7e6dae74b727292eab9e014b93c2607378b8cb1b227f80b429053ceb77c8e0dddc338837f9e534b2a658540ff60c9e4ffdc7cc19 languageName: node linkType: hard -"zod-validation-error@npm:^3.0.3, zod-validation-error@npm:^3.4.0": +"zod-validation-error@npm:^3.4.0": version: 3.5.4 resolution: "zod-validation-error@npm:3.5.4" peerDependencies: @@ -50614,10 +50901,17 @@ __metadata: languageName: node linkType: hard -"zod@npm:^3.22.4, zod@npm:^3.23.8, zod@npm:^3.24.2": - version: 3.25.67 - resolution: "zod@npm:3.25.67" - checksum: 10/0e35432dcca7f053e63f5dd491a87c78abe0d981817547252c3b6d05f0f58788695d1a69724759c6501dff3fd62929be24c9f314a3625179bee889150f7a61fa +"zod@npm:^3.22.4, zod@npm:^3.24.2": + version: 3.25.76 + resolution: "zod@npm:3.25.76" + checksum: 10/f0c963ec40cd96858451d1690404d603d36507c1fc9682f2dae59ab38b578687d542708a7fdbf645f77926f78c9ed558f57c3d3aa226c285f798df0c4da16995 + languageName: node + linkType: hard + +"zod@npm:^3.25 || ^4.0, zod@npm:^4.1.11": + version: 4.1.13 + resolution: "zod@npm:4.1.13" + checksum: 10/0679190318928f69fcb07751063719de232c663b13955fcdb55db59839569d39f3f29b955cb0cba7af0b724233f88c06b3e84c550397ad4e68f8088fa6799d88 languageName: node linkType: hard