From 61905609ff224f9365f80ec5752e80bc10f65684 Mon Sep 17 00:00:00 2001 From: Stan Lewis Date: Fri, 5 Jun 2026 09:11:15 -0400 Subject: [PATCH 1/2] chore(app): remove some static plugins This change removes a number of plugins from the app-next and backend packages to allow them to be provided from dynamic plugins instead. --- packages/app-next/package.json | 14 - packages/app-next/src/App.tsx | 10 - packages/backend/package.json | 10 - packages/backend/src/index.ts | 29 -- packages/backend/src/modules/userSettings.ts | 3 + yarn.lock | 369 +------------------ 6 files changed, 12 insertions(+), 423 deletions(-) diff --git a/packages/app-next/package.json b/packages/app-next/package.json index 030a9b2842..d3c233ca11 100644 --- a/packages/app-next/package.json +++ b/packages/app-next/package.json @@ -50,21 +50,7 @@ "@backstage/frontend-plugin-api": "0.15.1", "@backstage/integration-react": "1.2.16", "@backstage/plugin-app": "0.4.2", - "@backstage/plugin-app-visualizer": "0.2.1", - "@backstage/plugin-auth-react": "0.1.25", - "@backstage/plugin-catalog": "2.0.1", - "@backstage/plugin-catalog-common": "1.1.8", - "@backstage/plugin-catalog-graph": "0.6.0", - "@backstage/plugin-catalog-import": "0.13.11", - "@backstage/plugin-catalog-react": "2.1.1", - "@backstage/plugin-catalog-unprocessed-entities": "0.2.30", "@backstage/plugin-permission-react": "0.4.41", - "@backstage/plugin-scaffolder": "1.36.1", - "@backstage/plugin-scaffolder-react": "1.20.0", - "@backstage/plugin-search": "1.7.0", - "@backstage/plugin-search-common": "1.2.22", - "@backstage/plugin-search-react": "1.11.0", - "@backstage/plugin-user-settings": "0.9.1", "@backstage/theme": "0.7.2", "@backstage/ui": "0.13.2", "@material-ui/core": "4.12.4", diff --git a/packages/app-next/src/App.tsx b/packages/app-next/src/App.tsx index fafcd6a17b..6ea78b644a 100644 --- a/packages/app-next/src/App.tsx +++ b/packages/app-next/src/App.tsx @@ -1,18 +1,8 @@ import { createApp } from '@backstage/frontend-defaults'; -import appVisualizerPlugin from '@backstage/plugin-app-visualizer'; -import catalogPlugin from '@backstage/plugin-catalog/alpha'; -import scaffolderPlugin from '@backstage/plugin-scaffolder/alpha'; -import searchPlugin from '@backstage/plugin-search/alpha'; -import userSettingsPlugin from '@backstage/plugin-user-settings/alpha'; import { dynamicFrontendFeaturesLoader } from '@backstage/frontend-dynamic-feature-loader'; const app = createApp({ features: [ - appVisualizerPlugin, - catalogPlugin, - scaffolderPlugin, - searchPlugin, - userSettingsPlugin, dynamicFrontendFeaturesLoader() ], }); diff --git a/packages/backend/package.json b/packages/backend/package.json index 49eded1253..6147c2b6bb 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -23,7 +23,6 @@ "dependencies": { "@backstage-community/plugin-rbac-backend": "7.12.5", "@backstage-community/plugin-rbac-node": "1.20.1", - "@backstage-community/plugin-scaffolder-backend-module-annotator": "2.16.1", "@backstage/backend-app-api": "1.6.0", "@backstage/backend-defaults": "0.16.0", "@backstage/backend-dynamic-feature-service": "0.8.0", @@ -51,19 +50,10 @@ "@backstage/plugin-auth-backend-module-okta-provider": "0.2.13", "@backstage/plugin-auth-backend-module-onelogin-provider": "0.3.13", "@backstage/plugin-auth-node": "0.6.14", - "@backstage/plugin-catalog-backend": "3.5.0", - "@backstage/plugin-catalog-backend-module-logs": "0.1.20", - "@backstage/plugin-catalog-backend-module-openapi": "0.2.20", - "@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "0.2.18", "@backstage/plugin-events-backend": "0.6.0", "@backstage/plugin-events-node": "0.4.20", "@backstage/plugin-permission-backend": "0.7.10", "@backstage/plugin-proxy-backend": "0.6.11", - "@backstage/plugin-scaffolder-backend": "3.3.0", - "@backstage/plugin-search-backend": "2.1.0", - "@backstage/plugin-search-backend-module-catalog": "0.3.13", - "@backstage/plugin-search-backend-module-pg": "0.5.53", - "@backstage/plugin-user-settings-backend": "0.4.1", "@internal/plugin-dynamic-plugins-info-backend": "*", "@internal/plugin-licensed-users-info-backend": "*", "@internal/plugin-scalprum-backend": "*", diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index 7f0acf4ca6..7100253682 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -17,7 +17,6 @@ import { pluginIDProviderService, rbacDynamicPluginsProvider, } from './modules'; -import { userSettingsBackend } from './modules/userSettings'; // Create a logger to cover logging static initialization tasks const staticLogger = WinstonLogger.create({ @@ -115,39 +114,13 @@ if ( backend.add(healthCheckPlugin); backend.add(import('@backstage/plugin-app-backend')); -backend.add( - import('@backstage/plugin-catalog-backend-module-scaffolder-entity-model'), -); - -// See https://backstage.io/docs/features/software-catalog/configuration#subscribing-to-catalog-errors -backend.add(import('@backstage/plugin-catalog-backend-module-logs')); - -backend.add(import('@backstage/plugin-catalog-backend')); - -// TODO: Probably we should now provide this as a dynamic plugin -backend.add(import('@backstage/plugin-catalog-backend-module-openapi')); - backend.add(import('@backstage/plugin-proxy-backend')); -// TODO: Check in the Scaffolder new backend plugin why the identity is not passed and the default is built instead. -backend.add(import('@backstage/plugin-scaffolder-backend')); - -// search engine -// See https://backstage.io/docs/features/search/search-engines -backend.add(import('@backstage/plugin-search-backend-module-pg')); - -// search collators -backend.add(import('@backstage/plugin-search-backend')); -backend.add(import('@backstage/plugin-search-backend-module-catalog')); - // TODO: We should test it more deeply. The structure is not exactly the same as the old backend implementation backend.add(import('@backstage/plugin-events-backend')); backend.add(import('@backstage/plugin-permission-backend')); backend.add(import('@backstage-community/plugin-rbac-backend')); -backend.add( - import('@backstage-community/plugin-scaffolder-backend-module-annotator'), -); backend.add(pluginIDProviderService); backend.add(rbacDynamicPluginsProvider); @@ -166,6 +139,4 @@ backend.add( ); backend.add(import('@internal/plugin-licensed-users-info-backend')); -backend.add(userSettingsBackend); - backend.start(); diff --git a/packages/backend/src/modules/userSettings.ts b/packages/backend/src/modules/userSettings.ts index b41c8fd157..1f644b01b3 100644 --- a/packages/backend/src/modules/userSettings.ts +++ b/packages/backend/src/modules/userSettings.ts @@ -16,9 +16,12 @@ export const userSettingsBackend = createBackendFeatureLoader({ `Invalid config value for 'userSettings.persistence': "${persistence}". Must be either "database" or "browser".`, ); } + /* + TODO - this whole file needs to be moved to the user-settings-backend dynamic plugin if (persistence === 'database') { return [import('@backstage/plugin-user-settings-backend')]; } + */ // Opt-out: browser -> no backend feature return []; }, diff --git a/yarn.lock b/yarn.lock index 17340da455..3274742b39 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2717,19 +2717,6 @@ __metadata: languageName: node linkType: hard -"@backstage-community/plugin-scaffolder-backend-module-annotator@npm:2.16.1": - version: 2.16.1 - resolution: "@backstage-community/plugin-scaffolder-backend-module-annotator@npm:2.16.1" - dependencies: - "@backstage/backend-plugin-api": "npm:^1.8.0" - "@backstage/plugin-scaffolder-node": "npm:^0.13.0" - fs-extra: "npm:^11.2.0" - lodash: "npm:^4.17.21" - yaml: "npm:^2.0.0" - checksum: 10c0/fdc715a1b3a5a04dfca37e54b44c4f15011a0a41715cf9246eaaf30db6050802124520252483443766615893977278d8f5b39353b4a79ed300ed798ec53e921a - languageName: node - linkType: hard - "@backstage/app-defaults@npm:1.7.6": version: 1.7.6 resolution: "@backstage/app-defaults@npm:1.7.6" @@ -4237,28 +4224,6 @@ __metadata: languageName: node linkType: hard -"@backstage/plugin-app-visualizer@npm:0.2.1": - version: 0.2.1 - resolution: "@backstage/plugin-app-visualizer@npm:0.2.1" - dependencies: - "@backstage/core-components": "npm:^0.18.8" - "@backstage/core-plugin-api": "npm:^1.12.4" - "@backstage/frontend-plugin-api": "npm:^0.15.0" - "@backstage/ui": "npm:^0.13.0" - "@remixicon/react": "npm:^4.6.0" - react-aria-components: "npm:^1.14.0" - peerDependencies: - "@types/react": ^17.0.0 || ^18.0.0 - react: ^17.0.0 || ^18.0.0 - react-dom: ^17.0.0 || ^18.0.0 - react-router-dom: ^6.30.2 - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/c382feb720aa6ac18a06b2fd351ce711c56c4dd721a93ea49c205c5349c43e7c6d3c3c0c9fe7c19b5497ca696a7ba262ffe52059d61ed5ed2bc594a9959daec9 - languageName: node - linkType: hard - "@backstage/plugin-app@npm:0.4.2, @backstage/plugin-app@npm:^0.4.1": version: 0.4.2 resolution: "@backstage/plugin-app@npm:0.4.2" @@ -4579,68 +4544,7 @@ __metadata: languageName: node linkType: hard -"@backstage/plugin-auth-react@npm:0.1.25": - version: 0.1.25 - resolution: "@backstage/plugin-auth-react@npm:0.1.25" - dependencies: - "@backstage/core-components": "npm:^0.18.8" - "@backstage/core-plugin-api": "npm:^1.12.4" - "@backstage/errors": "npm:^1.2.7" - "@material-ui/core": "npm:^4.9.13" - "@react-hookz/web": "npm:^24.0.0" - peerDependencies: - "@types/react": ^17.0.0 || ^18.0.0 - react: ^17.0.0 || ^18.0.0 - react-dom: ^17.0.0 || ^18.0.0 - react-router-dom: ^6.30.2 - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/401a35f629047a6205610380a329b96b66984ed8613fb557dac5f93e9637949150da69337597efa12d52ded1919b5c2c610660d77e3dcd7e075c53c661b9ddec - languageName: node - linkType: hard - -"@backstage/plugin-catalog-backend-module-logs@npm:0.1.20": - version: 0.1.20 - resolution: "@backstage/plugin-catalog-backend-module-logs@npm:0.1.20" - dependencies: - "@backstage/backend-plugin-api": "npm:^1.8.0" - "@backstage/plugin-catalog-backend": "npm:^3.5.0" - "@backstage/plugin-events-node": "npm:^0.4.20" - checksum: 10c0/d192204df463ec576c9da39812c54a15fdec5e49d08ea543ff23ad80c57c45d0c63a302eea3bc1eeaf3cae16897c3bb64f417209042a0b5c19163f389a89f1f4 - languageName: node - linkType: hard - -"@backstage/plugin-catalog-backend-module-openapi@npm:0.2.20": - version: 0.2.20 - resolution: "@backstage/plugin-catalog-backend-module-openapi@npm:0.2.20" - dependencies: - "@apidevtools/json-schema-ref-parser": "npm:^14.2.1" - "@backstage/backend-plugin-api": "npm:^1.8.0" - "@backstage/catalog-model": "npm:^1.7.7" - "@backstage/integration": "npm:^2.0.0" - "@backstage/plugin-catalog-common": "npm:^1.1.8" - "@backstage/plugin-catalog-node": "npm:^2.1.0" - "@backstage/types": "npm:^1.2.2" - yaml: "npm:^2.1.1" - checksum: 10c0/c291cd20edd01ef1f107099a0fde985bce8b81e120d6c421693c03cc831276a5756da875cc383ce57b84e3344b2d8f221dd2c502fbc57ab3f3c2c36894ec7d00 - languageName: node - linkType: hard - -"@backstage/plugin-catalog-backend-module-scaffolder-entity-model@npm:0.2.18": - version: 0.2.18 - resolution: "@backstage/plugin-catalog-backend-module-scaffolder-entity-model@npm:0.2.18" - dependencies: - "@backstage/backend-plugin-api": "npm:^1.8.0" - "@backstage/catalog-model": "npm:^1.7.7" - "@backstage/plugin-catalog-common": "npm:^1.1.8" - "@backstage/plugin-catalog-node": "npm:^2.1.0" - "@backstage/plugin-scaffolder-common": "npm:^2.0.0" - checksum: 10c0/837ed4778461634e8d3cc23b13f2a2613c248b6597caa9a4a9abfb218a6cb02f1cdfaed83ced80336655f6cae85448f784c0099e50c29863db0cd2a05e48fd45 - languageName: node - linkType: hard - -"@backstage/plugin-catalog-backend@npm:3.5.0, @backstage/plugin-catalog-backend@npm:^3.5.0": +"@backstage/plugin-catalog-backend@npm:^3.5.0": version: 3.5.0 resolution: "@backstage/plugin-catalog-backend@npm:3.5.0" dependencies: @@ -4890,45 +4794,6 @@ __metadata: languageName: node linkType: hard -"@backstage/plugin-catalog-unprocessed-entities-common@npm:^0.0.15": - version: 0.0.15 - resolution: "@backstage/plugin-catalog-unprocessed-entities-common@npm:0.0.15" - dependencies: - "@backstage/catalog-model": "npm:^1.8.0" - "@backstage/errors": "npm:^1.3.0" - "@backstage/plugin-permission-common": "npm:^0.9.8" - checksum: 10c0/b3ae7dccd1e1c6309bacaee804cc4b1d8d7dd5c7ba5f1ef0c9c4caaea185bd20babcb4e2aa2f55c86ffd4def3a6940af9f3fffc4782bb9b39aec01bf7faf3ad0 - languageName: node - linkType: hard - -"@backstage/plugin-catalog-unprocessed-entities@npm:0.2.30": - version: 0.2.30 - resolution: "@backstage/plugin-catalog-unprocessed-entities@npm:0.2.30" - dependencies: - "@backstage/core-compat-api": "npm:^0.5.10" - "@backstage/core-components": "npm:^0.18.9" - "@backstage/core-plugin-api": "npm:^1.12.5" - "@backstage/errors": "npm:^1.3.0" - "@backstage/frontend-plugin-api": "npm:^0.16.2" - "@backstage/plugin-catalog-unprocessed-entities-common": "npm:^0.0.15" - "@backstage/ui": "npm:^0.14.3" - "@material-ui/core": "npm:^4.9.13" - "@material-ui/icons": "npm:^4.9.1" - "@material-ui/lab": "npm:^4.0.0-alpha.60" - luxon: "npm:^3.5.0" - react-use: "npm:^17.2.4" - peerDependencies: - "@types/react": ^17.0.0 || ^18.0.0 - react: ^17.0.0 || ^18.0.0 - react-dom: ^17.0.0 || ^18.0.0 - react-router-dom: ^6.30.2 - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/9054d63fa14e5e9ddcb639bcbafa5264bc801097b2e55b00a45acb9139034e1cc9dfcde521f5f241a5b6e619c3f8e4c7d9de97c070913f2a4e758c09306d7573 - languageName: node - linkType: hard - "@backstage/plugin-catalog@npm:2.0.1, @backstage/plugin-catalog@npm:^2.0.0": version: 2.0.1 resolution: "@backstage/plugin-catalog@npm:2.0.1" @@ -5175,50 +5040,6 @@ __metadata: languageName: node linkType: hard -"@backstage/plugin-scaffolder-backend@npm:3.3.0": - version: 3.3.0 - resolution: "@backstage/plugin-scaffolder-backend@npm:3.3.0" - dependencies: - "@backstage/backend-openapi-utils": "npm:^0.6.7" - "@backstage/backend-plugin-api": "npm:^1.8.0" - "@backstage/catalog-model": "npm:^1.7.7" - "@backstage/config": "npm:^1.3.6" - "@backstage/errors": "npm:^1.2.7" - "@backstage/integration": "npm:^2.0.0" - "@backstage/plugin-catalog-node": "npm:^2.1.0" - "@backstage/plugin-events-node": "npm:^0.4.20" - "@backstage/plugin-permission-common": "npm:^0.9.7" - "@backstage/plugin-permission-node": "npm:^0.10.11" - "@backstage/plugin-scaffolder-common": "npm:^2.0.0" - "@backstage/plugin-scaffolder-node": "npm:^0.13.1" - "@backstage/types": "npm:^1.2.2" - "@opentelemetry/api": "npm:^1.9.0" - "@types/luxon": "npm:^3.0.0" - express: "npm:^4.22.0" - fs-extra: "npm:^11.2.0" - globby: "npm:^11.0.0" - isbinaryfile: "npm:^5.0.0" - isolated-vm: "npm:^6.0.1" - jsonschema: "npm:^1.5.0" - knex: "npm:^3.0.0" - lodash: "npm:^4.17.21" - logform: "npm:^2.3.2" - luxon: "npm:^3.0.0" - nunjucks: "npm:^3.2.3" - p-queue: "npm:^6.6.2" - prom-client: "npm:^15.0.0" - triple-beam: "npm:^1.4.1" - uuid: "npm:^11.0.0" - winston: "npm:^3.2.1" - winston-transport: "npm:^4.7.0" - yaml: "npm:^2.0.0" - zen-observable: "npm:^0.10.0" - zod: "npm:^3.25.76 || ^4.0.0" - zod-to-json-schema: "npm:^3.25.1" - checksum: 10c0/16d1e250a57ca79034edb6352e99c9300e1cf0f181c01b205724500f9488329a2b61a002ecb5a17c5f12fe6383b1f102b44f1c7142c383351d44ee570e6f34db - languageName: node - linkType: hard - "@backstage/plugin-scaffolder-common@npm:^2.0.0": version: 2.0.0 resolution: "@backstage/plugin-scaffolder-common@npm:2.0.0" @@ -5238,7 +5059,7 @@ __metadata: languageName: node linkType: hard -"@backstage/plugin-scaffolder-node@npm:^0.13.0, @backstage/plugin-scaffolder-node@npm:^0.13.1": +"@backstage/plugin-scaffolder-node@npm:^0.13.0": version: 0.13.1 resolution: "@backstage/plugin-scaffolder-node@npm:0.13.1" dependencies: @@ -5391,39 +5212,6 @@ __metadata: languageName: node linkType: hard -"@backstage/plugin-search-backend-module-catalog@npm:0.3.13": - version: 0.3.13 - resolution: "@backstage/plugin-search-backend-module-catalog@npm:0.3.13" - dependencies: - "@backstage/backend-plugin-api": "npm:^1.8.0" - "@backstage/catalog-client": "npm:^1.14.0" - "@backstage/catalog-model": "npm:^1.7.7" - "@backstage/config": "npm:^1.3.6" - "@backstage/errors": "npm:^1.2.7" - "@backstage/plugin-catalog-common": "npm:^1.1.8" - "@backstage/plugin-catalog-node": "npm:^2.1.0" - "@backstage/plugin-permission-common": "npm:^0.9.7" - "@backstage/plugin-search-backend-node": "npm:^1.4.2" - "@backstage/plugin-search-common": "npm:^1.2.22" - checksum: 10c0/0d06ef59603169272696d2028fcef5af7f9457c795477f1f5775c682a1970a8cbbfc3e26fe0309fb1903fd2fed46b34be45e5e0bbeac9f4038b8c1b902789214 - languageName: node - linkType: hard - -"@backstage/plugin-search-backend-module-pg@npm:0.5.53": - version: 0.5.53 - resolution: "@backstage/plugin-search-backend-module-pg@npm:0.5.53" - dependencies: - "@backstage/backend-plugin-api": "npm:^1.8.0" - "@backstage/config": "npm:^1.3.6" - "@backstage/plugin-search-backend-node": "npm:^1.4.2" - "@backstage/plugin-search-common": "npm:^1.2.22" - knex: "npm:^3.0.0" - lodash: "npm:^4.17.21" - uuid: "npm:^11.0.0" - checksum: 10c0/0c3edb70d97b8f63ffeed87575adfe7f0cd42bdb0d6d0003f25bf4b5620ea6881b2f38380303ba214a3b7d268701db51d77809547864a668a3d41f34abacd7be - languageName: node - linkType: hard - "@backstage/plugin-search-backend-node@npm:^1.4.2": version: 1.4.2 resolution: "@backstage/plugin-search-backend-node@npm:1.4.2" @@ -5442,30 +5230,7 @@ __metadata: languageName: node linkType: hard -"@backstage/plugin-search-backend@npm:2.1.0": - version: 2.1.0 - resolution: "@backstage/plugin-search-backend@npm:2.1.0" - dependencies: - "@backstage/backend-openapi-utils": "npm:^0.6.7" - "@backstage/backend-plugin-api": "npm:^1.8.0" - "@backstage/config": "npm:^1.3.6" - "@backstage/errors": "npm:^1.2.7" - "@backstage/plugin-permission-common": "npm:^0.9.7" - "@backstage/plugin-permission-node": "npm:^0.10.11" - "@backstage/plugin-search-backend-node": "npm:^1.4.2" - "@backstage/plugin-search-common": "npm:^1.2.22" - "@backstage/types": "npm:^1.2.2" - dataloader: "npm:^2.0.0" - express: "npm:^4.22.0" - lodash: "npm:^4.17.21" - qs: "npm:^6.10.1" - yn: "npm:^4.0.0" - zod: "npm:^3.25.76 || ^4.0.0" - checksum: 10c0/be0ecb3fbda7418e3403d42f4060ed18b4968bc3ea69ee79844ece97bcd741f51cfd5b18247a47c4dbf67ce0d00793c8df977387c03038b13adeeb49d000c1db - languageName: node - linkType: hard - -"@backstage/plugin-search-common@npm:1.2.22, @backstage/plugin-search-common@npm:^1.2.22": +"@backstage/plugin-search-common@npm:^1.2.22": version: 1.2.22 resolution: "@backstage/plugin-search-common@npm:1.2.22" dependencies: @@ -5545,22 +5310,6 @@ __metadata: languageName: node linkType: hard -"@backstage/plugin-signals-node@npm:^0.1.29": - version: 0.1.29 - resolution: "@backstage/plugin-signals-node@npm:0.1.29" - dependencies: - "@backstage/backend-plugin-api": "npm:^1.8.0" - "@backstage/config": "npm:^1.3.6" - "@backstage/plugin-auth-node": "npm:^0.6.14" - "@backstage/plugin-events-node": "npm:^0.4.20" - "@backstage/types": "npm:^1.2.2" - express: "npm:^4.22.0" - uuid: "npm:^11.0.0" - ws: "npm:^8.18.0" - checksum: 10c0/4d32e70698e85f2dd653f120c3486ed169d26ad36db417607ef9c5b0b2824c4cb75dd812709dfb442e60f332a78f6765cab99999cd1f1abd73303da257454d4e - languageName: node - linkType: hard - "@backstage/plugin-signals-react@npm:^0.0.20": version: 0.0.20 resolution: "@backstage/plugin-signals-react@npm:0.0.20" @@ -5635,26 +5384,6 @@ __metadata: languageName: node linkType: hard -"@backstage/plugin-user-settings-backend@npm:0.4.1": - version: 0.4.1 - resolution: "@backstage/plugin-user-settings-backend@npm:0.4.1" - dependencies: - "@backstage/backend-plugin-api": "npm:^1.8.0" - "@backstage/errors": "npm:^1.2.7" - "@backstage/plugin-auth-node": "npm:^0.6.14" - "@backstage/plugin-signals-node": "npm:^0.1.29" - "@backstage/plugin-user-settings-common": "npm:^0.1.0" - "@backstage/types": "npm:^1.2.2" - already: "npm:^2.2.1" - express: "npm:^4.22.0" - express-promise-router: "npm:^4.1.0" - knex: "npm:^3.0.0" - p-limit: "npm:^3.1.0" - zod: "npm:^3.25.76 || ^4.0.0" - checksum: 10c0/44cbe8d0233787976759bc9dbdc2fdf562958269d7336a06dbce3e9c1c886f2e8e9474d6ae9ef91374706337acd48a402aaead1f7381f37356e759786ca02747 - languageName: node - linkType: hard - "@backstage/plugin-user-settings-common@npm:^0.1.0": version: 0.1.0 resolution: "@backstage/plugin-user-settings-common@npm:0.1.0" @@ -5840,7 +5569,7 @@ __metadata: languageName: node linkType: hard -"@backstage/ui@npm:^0.14.0, @backstage/ui@npm:^0.14.2, @backstage/ui@npm:^0.14.3": +"@backstage/ui@npm:^0.14.0, @backstage/ui@npm:^0.14.2": version: 0.14.3 resolution: "@backstage/ui@npm:0.14.3" dependencies: @@ -8644,7 +8373,7 @@ __metadata: languageName: node linkType: hard -"@material-ui/lab@npm:4.0.0-alpha.61, @material-ui/lab@npm:^4.0.0-alpha.60, @material-ui/lab@npm:^4.0.0-alpha.61": +"@material-ui/lab@npm:4.0.0-alpha.61, @material-ui/lab@npm:^4.0.0-alpha.61": version: 4.0.0-alpha.61 resolution: "@material-ui/lab@npm:4.0.0-alpha.61" dependencies: @@ -18282,13 +18011,6 @@ __metadata: languageName: node linkType: hard -"a-sync-waterfall@npm:^1.0.0": - version: 1.0.1 - resolution: "a-sync-waterfall@npm:1.0.1" - checksum: 10c0/1c7b258da2c77eb1447dcc683afb10ca3dc8880de990562ccbb7b282538aba01e910345ce9e8500c1458272c7866b85fcfa5ca8159e33550b011ab5c586ec5a4 - languageName: node - linkType: hard - "abbrev@npm:^2.0.0": version: 2.0.0 resolution: "abbrev@npm:2.0.0" @@ -18510,13 +18232,6 @@ __metadata: languageName: node linkType: hard -"already@npm:^2.2.1": - version: 2.2.1 - resolution: "already@npm:2.2.1" - checksum: 10c0/f915c7949f7590566419c65025035141074bebb0a3ee0e2f3d49de87f64b744b852707fc44f5b2eeeeafed625c0274c7ab9c7632966d28e48e5a4e380a0803f9 - languageName: node - linkType: hard - "anser@npm:^2.1.1": version: 2.3.5 resolution: "anser@npm:2.3.5" @@ -18670,21 +18385,7 @@ __metadata: "@backstage/frontend-plugin-api": "npm:0.15.1" "@backstage/integration-react": "npm:1.2.16" "@backstage/plugin-app": "npm:0.4.2" - "@backstage/plugin-app-visualizer": "npm:0.2.1" - "@backstage/plugin-auth-react": "npm:0.1.25" - "@backstage/plugin-catalog": "npm:2.0.1" - "@backstage/plugin-catalog-common": "npm:1.1.8" - "@backstage/plugin-catalog-graph": "npm:0.6.0" - "@backstage/plugin-catalog-import": "npm:0.13.11" - "@backstage/plugin-catalog-react": "npm:2.1.1" - "@backstage/plugin-catalog-unprocessed-entities": "npm:0.2.30" "@backstage/plugin-permission-react": "npm:0.4.41" - "@backstage/plugin-scaffolder": "npm:1.36.1" - "@backstage/plugin-scaffolder-react": "npm:1.20.0" - "@backstage/plugin-search": "npm:1.7.0" - "@backstage/plugin-search-common": "npm:1.2.22" - "@backstage/plugin-search-react": "npm:1.11.0" - "@backstage/plugin-user-settings": "npm:0.9.1" "@backstage/test-utils": "npm:1.7.16" "@backstage/theme": "npm:0.7.2" "@backstage/ui": "npm:0.13.2" @@ -19001,7 +18702,7 @@ __metadata: languageName: node linkType: hard -"asap@npm:^2.0.0, asap@npm:^2.0.3": +"asap@npm:^2.0.0": version: 2.0.6 resolution: "asap@npm:2.0.6" checksum: 10c0/c6d5e39fe1f15e4b87677460bd66b66050cd14c772269cee6688824c1410a08ab20254bb6784f9afb75af9144a9f9a7692d49547f4d19d715aeb7c0318f3136d @@ -19363,7 +19064,6 @@ __metadata: dependencies: "@backstage-community/plugin-rbac-backend": "npm:7.12.5" "@backstage-community/plugin-rbac-node": "npm:1.20.1" - "@backstage-community/plugin-scaffolder-backend-module-annotator": "npm:2.16.1" "@backstage/backend-app-api": "npm:1.6.0" "@backstage/backend-defaults": "npm:0.16.0" "@backstage/backend-dynamic-feature-service": "npm:0.8.0" @@ -19394,20 +19094,11 @@ __metadata: "@backstage/plugin-auth-backend-module-okta-provider": "npm:0.2.13" "@backstage/plugin-auth-backend-module-onelogin-provider": "npm:0.3.13" "@backstage/plugin-auth-node": "npm:0.6.14" - "@backstage/plugin-catalog-backend": "npm:3.5.0" - "@backstage/plugin-catalog-backend-module-logs": "npm:0.1.20" - "@backstage/plugin-catalog-backend-module-openapi": "npm:0.2.20" - "@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "npm:0.2.18" "@backstage/plugin-catalog-node": "npm:2.1.0" "@backstage/plugin-events-backend": "npm:0.6.0" "@backstage/plugin-events-node": "npm:0.4.20" "@backstage/plugin-permission-backend": "npm:0.7.10" "@backstage/plugin-proxy-backend": "npm:0.6.11" - "@backstage/plugin-scaffolder-backend": "npm:3.3.0" - "@backstage/plugin-search-backend": "npm:2.1.0" - "@backstage/plugin-search-backend-module-catalog": "npm:0.3.13" - "@backstage/plugin-search-backend-module-pg": "npm:0.5.53" - "@backstage/plugin-user-settings-backend": "npm:0.4.1" "@internal/plugin-dynamic-plugins-info-backend": "npm:*" "@internal/plugin-licensed-users-info-backend": "npm:*" "@internal/plugin-scalprum-backend": "npm:*" @@ -20870,13 +20561,6 @@ __metadata: languageName: node linkType: hard -"commander@npm:^5.1.0": - version: 5.1.0 - resolution: "commander@npm:5.1.0" - checksum: 10c0/da9d71dbe4ce039faf1fe9eac3771dca8c11d66963341f62602f7b66e36d2a3f8883407af4f9a37b1db1a55c59c0c1325f186425764c2e963dc1d67aec2a4b6d - languageName: node - linkType: hard - "commander@npm:^6.2.1": version: 6.2.1 resolution: "commander@npm:6.2.1" @@ -27272,13 +26956,6 @@ __metadata: languageName: node linkType: hard -"isbinaryfile@npm:^5.0.0": - version: 5.0.7 - resolution: "isbinaryfile@npm:5.0.7" - checksum: 10c0/4cd98a91aaf969d7cae91f74d041dd1df35d9e140c522b7879180035f7eab9ba9c0c3d678e00e72a2777ee7245fd8f20b60c0787132c5fdbf6fc113492325e11 - languageName: node - linkType: hard - "isexe@npm:^2.0.0": version: 2.0.0 resolution: "isexe@npm:2.0.0" @@ -27307,16 +26984,6 @@ __metadata: languageName: node linkType: hard -"isolated-vm@npm:^6.0.1": - version: 6.0.2 - resolution: "isolated-vm@npm:6.0.2" - dependencies: - node-gyp: "npm:latest" - prebuild-install: "npm:^7.1.3" - checksum: 10c0/1c40cb52836a9bd9b6c2a410ee0156dc3bef528e04c8cfeec24a431625ed4d41c0f8e9930df893a577e10d6109f1f81070dc369e2b47a1d48f8695807a3adf0c - languageName: node - linkType: hard - "isomorphic-dompurify@npm:^2.14.0": version: 2.36.0 resolution: "isomorphic-dompurify@npm:2.36.0" @@ -29331,7 +28998,7 @@ __metadata: languageName: node linkType: hard -"luxon@npm:3.7.2, luxon@npm:^3.0.0, luxon@npm:^3.2.1, luxon@npm:^3.5.0": +"luxon@npm:3.7.2, luxon@npm:^3.0.0, luxon@npm:^3.2.1": version: 3.7.2 resolution: "luxon@npm:3.7.2" checksum: 10c0/ed8f0f637826c08c343a29dd478b00628be93bba6f068417b1d8896b61cb61c6deacbe1df1e057dbd9298334044afa150f9aaabbeb3181418ac8520acfdc2ae2 @@ -31300,24 +30967,6 @@ __metadata: languageName: node linkType: hard -"nunjucks@npm:^3.2.3": - version: 3.2.4 - resolution: "nunjucks@npm:3.2.4" - dependencies: - a-sync-waterfall: "npm:^1.0.0" - asap: "npm:^2.0.3" - commander: "npm:^5.1.0" - peerDependencies: - chokidar: ^3.3.0 - peerDependenciesMeta: - chokidar: - optional: true - bin: - nunjucks-precompile: bin/precompile - checksum: 10c0/7fe5197559b7c09972c79e2a86f9c093459b9075bc9b41134cd2bc599ae93567b53bd09d472a748edc736192d9ccd2998aa8c20cfcbe6a3fffd281f91897c888 - languageName: node - linkType: hard - "oauth@npm:0.10.x": version: 0.10.2 resolution: "oauth@npm:0.10.2" @@ -33096,7 +32745,7 @@ __metadata: languageName: node linkType: hard -"prebuild-install@npm:^7.0.1, prebuild-install@npm:^7.1.1, prebuild-install@npm:^7.1.3": +"prebuild-install@npm:^7.0.1, prebuild-install@npm:^7.1.1": version: 7.1.3 resolution: "prebuild-install@npm:7.1.3" dependencies: @@ -39830,7 +39479,7 @@ __metadata: languageName: node linkType: hard -"yaml@npm:^2.0.0, yaml@npm:^2.1.1, yaml@npm:^2.2.1, yaml@npm:^2.2.2, yaml@npm:^2.5.1, yaml@npm:^2.7.0": +"yaml@npm:^2.0.0, yaml@npm:^2.2.1, yaml@npm:^2.2.2, yaml@npm:^2.5.1, yaml@npm:^2.7.0": version: 2.8.2 resolution: "yaml@npm:2.8.2" bin: From a39cfb40212757cee974aaf29deef285d4799ab1 Mon Sep 17 00:00:00 2001 From: Stan Lewis Date: Thu, 11 Jun 2026 06:18:12 -0400 Subject: [PATCH 2/2] fix(backend): add temporary patch This change adds a temporary patch to update the backend dynamic feature service so that it will also load backend plugins that have an alpha export but do not export the plugin object in that alpha export. The patch is similar to the fix applied in this PR: https://github.com/backstage/backstage/pull/34535 Assisted-By: Cursor Desktop --- ...feature-service-npm-0.8.0-92b2319b05.patch | 162 ++++++++++++++++++ packages/backend/package.json | 2 +- .../dynamic-plugins-info-backend/package.json | 2 +- plugins/scalprum-backend/package.json | 2 +- yarn.lock | 41 ++++- 5 files changed, 203 insertions(+), 6 deletions(-) create mode 100644 .yarn/patches/@backstage-backend-dynamic-feature-service-npm-0.8.0-92b2319b05.patch diff --git a/.yarn/patches/@backstage-backend-dynamic-feature-service-npm-0.8.0-92b2319b05.patch b/.yarn/patches/@backstage-backend-dynamic-feature-service-npm-0.8.0-92b2319b05.patch new file mode 100644 index 0000000000..2c7c6c6ed6 --- /dev/null +++ b/.yarn/patches/@backstage-backend-dynamic-feature-service-npm-0.8.0-92b2319b05.patch @@ -0,0 +1,162 @@ +diff --git a/dist/manager/plugin-manager.cjs.js b/dist/manager/plugin-manager.cjs.js +index 30e7e7fd4533086cf726478386b9515fb01cd754..4b8b3e87f5be5768290499ef931b28d52d1a2a10 100644 +--- a/dist/manager/plugin-manager.cjs.js ++++ b/dist/manager/plugin-manager.cjs.js +@@ -1,14 +1,17 @@ + 'use strict'; + + var types = require('./types.cjs.js'); + var pluginScanner = require('../scanner/plugin-scanner.cjs.js'); + var CommonJSModuleLoader = require('../loader/CommonJSModuleLoader.cjs.js'); ++var path = require('node:path'); + var url = require('node:url'); + var backendPluginApi = require('@backstage/backend-plugin-api'); + var cliNode = require('@backstage/cli-node'); + var cliCommon = require('@backstage/cli-common'); + var fs = require('node:fs'); + ++function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; } ++ + function _interopNamespaceCompat(e) { + if (e && typeof e === 'object' && 'default' in e) return e; + var n = Object.create(null); +@@ -27,6 +31,7 @@ function _interopNamespaceCompat(e) { + return Object.freeze(n); + } + ++var path__default = /*#__PURE__*/_interopDefaultCompat(path); + var url__namespace = /*#__PURE__*/_interopNamespaceCompat(url); + var fs__namespace = /*#__PURE__*/_interopNamespaceCompat(fs); + +@@ -116,52 +121,57 @@ class DynamicPluginManager { + return loadedPlugins; + } + async loadBackendPlugin(plugin) { +- const usedPluginManifest = plugin.alphaManifest?.main ?? plugin.manifest.main; +- const usedPluginLocation = plugin.alphaManifest?.main ? `${plugin.location}/alpha` : plugin.location; +- const packagePath = url__namespace.fileURLToPath( +- `${usedPluginLocation}/${usedPluginManifest}` +- ); + const dynamicPlugin = { + name: plugin.manifest.name, + version: plugin.manifest.version, + platform: "node", + role: plugin.manifest.backstage.role + }; +- try { +- const pluginModule = await this.moduleLoader.load(packagePath); +- if (isBackendFeature(pluginModule.default)) { +- dynamicPlugin.installer = { +- kind: "new", +- install: () => pluginModule.default +- }; +- } else if (isBackendFeatureFactory(pluginModule.default)) { +- dynamicPlugin.installer = { +- kind: "new", +- install: pluginModule.default +- }; +- } else if (types.isBackendDynamicPluginInstaller(pluginModule.dynamicPluginInstaller)) { +- dynamicPlugin.installer = pluginModule.dynamicPluginInstaller; ++ const entryPoints = [ ++ ...plugin.alphaManifest?.main ? [ ++ { ++ location: new URL(`${plugin.location}/alpha`), ++ manifest: plugin.alphaManifest.main ++ } ++ ] : [], ++ { ++ location: plugin.location, ++ manifest: plugin.manifest.main + } +- if (dynamicPlugin.installer) { ++ ]; ++ for (const [index, { location, manifest }] of entryPoints.entries()) { ++ const loadResult = await tryLoadBackendPluginEntry( ++ this.moduleLoader, ++ location, ++ manifest ++ ); ++ if (loadResult.installer) { ++ dynamicPlugin.installer = loadResult.installer; + this.logger.info( +- `loaded dynamic backend plugin '${plugin.manifest.name}' from '${usedPluginLocation}'` ++ `loaded dynamic backend plugin '${plugin.manifest.name}' from '${location}'` + ); +- } else { +- dynamicPlugin.failure = `the module should either export a 'BackendFeature' or 'BackendFeatureFactory' as default export, or export a 'const dynamicPluginInstaller: BackendDynamicPluginInstaller' field as dynamic loading entrypoint.`; ++ return dynamicPlugin; ++ } ++ if (index < entryPoints.length - 1) { ++ continue; ++ } ++ if (loadResult.error) { ++ dynamicPlugin.failure = `${loadResult.error.name}: ${loadResult.error.message}`; + this.logger.error( +- `dynamic backend plugin '${plugin.manifest.name}' could not be loaded from '${usedPluginLocation}': ${dynamicPlugin.failure}` ++ `an error occurred while loading dynamic backend plugin '${plugin.manifest.name}' from '${location}'`, ++ loadResult.error + ); ++ return dynamicPlugin; + } +- return dynamicPlugin; +- } catch (error) { +- const typedError = typeof error === "object" && "message" in error && "name" in error ? error : new Error(error); +- dynamicPlugin.failure = `${typedError.name}: ${typedError.message}`; ++ dynamicPlugin.failure = `the module should either export a 'BackendFeature' or 'BackendFeatureFactory' as default export, or export a 'const dynamicPluginInstaller: BackendDynamicPluginInstaller' field as dynamic loading entrypoint.`; + this.logger.error( +- `an error occurred while loading dynamic backend plugin '${plugin.manifest.name}' from '${usedPluginLocation}'`, +- typedError ++ `dynamic backend plugin '${plugin.manifest.name}' could not be loaded from '${location}': ${dynamicPlugin.failure}` + ); + return dynamicPlugin; + } ++ throw new Error( ++ `Failed to load dynamic backend plugin '${plugin.manifest.name}': exhausted all entry points without producing a result` ++ ); + } + backendPlugins(options) { + return this.plugins(options).filter( +@@ -245,6 +255,34 @@ const dynamicPluginsFeatureDiscoveryLoader = backendPluginApi.createBackendFeatu + return features; + } + }); ++async function tryLoadBackendPluginEntry(moduleLoader, location, manifest) { ++ try { ++ const packagePath = path__default.default.resolve(url__namespace.fileURLToPath(location), manifest); ++ const pluginModule = await moduleLoader.load(packagePath); ++ return { installer: resolveInstallerFromModule(pluginModule) }; ++ } catch (error) { ++ const typedError = typeof error === "object" && error !== null && "message" in error && "name" in error ? error : new Error(error); ++ return { error: typedError }; ++ } ++} ++function resolveInstallerFromModule(pluginModule) { ++ if (isBackendFeature(pluginModule.default)) { ++ return { ++ kind: "new", ++ install: () => pluginModule.default ++ }; ++ } ++ if (isBackendFeatureFactory(pluginModule.default)) { ++ return { ++ kind: "new", ++ install: pluginModule.default ++ }; ++ } ++ if (types.isBackendDynamicPluginInstaller(pluginModule.dynamicPluginInstaller)) { ++ return pluginModule.dynamicPluginInstaller; ++ } ++ return void 0; ++} + function isBackendFeature(value) { + return !!value && (typeof value === "object" || typeof value === "function") && value.$$type === "@backstage/BackendFeature"; + } +diff --git a/dist/manager/plugin-manager.cjs.js.map b/dist/manager/plugin-manager.cjs.js.map +index b8cefc9e7d0162893103a05f23231acf32142210..14dd0fd2765c3bce8ada215b272afbf6b94405cb 100644 +--- a/dist/manager/plugin-manager.cjs.js.map ++++ b/dist/manager/plugin-manager.cjs.js.map +@@ -1 +1 @@ +-{"version":3,"file":"plugin-manager.cjs.js","sources":["../../src/manager/plugin-manager.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { Config } from '@backstage/config';\nimport {\n DynamicPluginProvider,\n BackendDynamicPlugin,\n isBackendDynamicPluginInstaller,\n DynamicPlugin,\n FrontendDynamicPlugin,\n} from './types';\nimport { ScannedPluginPackage } from '../scanner';\nimport { PluginScanner } from '../scanner/plugin-scanner';\nimport { ModuleLoader } from '../loader';\nimport { CommonJSModuleLoader } from '../loader/CommonJSModuleLoader';\nimport * as url from 'node:url';\nimport {\n BackendFeature,\n LoggerService,\n coreServices,\n createBackendFeatureLoader,\n createServiceFactory,\n createServiceRef,\n} from '@backstage/backend-plugin-api';\nimport { PackageRole, PackageRoles } from '@backstage/cli-node';\nimport { targetPaths } from '@backstage/cli-common';\nimport * as fs from 'node:fs';\n\n/**\n * @public\n */\nexport interface DynamicPluginManagerOptions {\n config: Config;\n logger: LoggerService;\n preferAlpha?: boolean;\n moduleLoader?: ModuleLoader;\n}\n\n/**\n * @public\n */\nexport class DynamicPluginManager implements DynamicPluginProvider {\n static async create(\n options: DynamicPluginManagerOptions,\n ): Promise {\n /* eslint-disable-next-line no-restricted-syntax */\n const backstageRoot = targetPaths.rootDir;\n const scanner = PluginScanner.create({\n config: options.config,\n logger: options.logger,\n backstageRoot,\n preferAlpha: options.preferAlpha,\n });\n const scannedPlugins = (await scanner.scanRoot()).packages;\n await scanner.trackChanges();\n const moduleLoader =\n options.moduleLoader ||\n new CommonJSModuleLoader({ logger: options.logger });\n const manager = new DynamicPluginManager(\n options.logger,\n scannedPlugins,\n moduleLoader,\n );\n\n const scannedPluginManifestsPerRealPath = new Map(\n scannedPlugins.map(p => [\n fs.realpathSync(url.fileURLToPath(p.location)),\n p.manifest,\n ]),\n );\n\n await moduleLoader.bootstrap(\n backstageRoot,\n [...scannedPluginManifestsPerRealPath.keys()],\n scannedPluginManifestsPerRealPath,\n );\n\n scanner.subscribeToRootDirectoryChange(async () => {\n manager._availablePackages = (await scanner.scanRoot()).packages;\n // TODO: do not store _scannedPlugins again, but instead store a diff of the changes\n });\n manager._plugins.push(...(await manager.loadPlugins()));\n\n return manager;\n }\n\n private readonly _plugins: DynamicPlugin[];\n private _availablePackages: ScannedPluginPackage[];\n\n private readonly logger: LoggerService;\n private readonly packages: ScannedPluginPackage[];\n private readonly moduleLoader: ModuleLoader;\n\n private constructor(\n logger: LoggerService,\n packages: ScannedPluginPackage[],\n moduleLoader: ModuleLoader,\n ) {\n this.logger = logger;\n this.packages = packages;\n this.moduleLoader = moduleLoader;\n this._plugins = [];\n this._availablePackages = packages;\n }\n\n get availablePackages(): ScannedPluginPackage[] {\n return this._availablePackages;\n }\n\n addBackendPlugin(plugin: BackendDynamicPlugin): void {\n this._plugins.push(plugin);\n }\n\n private async loadPlugins(): Promise {\n const loadedPlugins: DynamicPlugin[] = [];\n\n for (const scannedPlugin of this.packages) {\n const role = scannedPlugin.manifest.backstage.role;\n const platform = PackageRoles.getRoleInfo(role).platform;\n const isPlugin =\n role.endsWith('-plugin') ||\n role.endsWith('-plugin-module') ||\n role === ('frontend-dynamic-container' as PackageRole);\n\n if (!isPlugin) {\n this.logger.info(\n `skipping dynamic plugin package '${scannedPlugin.manifest.name}' from '${scannedPlugin.location}': incompatible role '${role}'`,\n );\n continue;\n }\n\n switch (platform) {\n case 'node':\n loadedPlugins.push(await this.loadBackendPlugin(scannedPlugin));\n break;\n\n case 'web':\n loadedPlugins.push({\n name: scannedPlugin.manifest.name,\n version: scannedPlugin.manifest.version,\n role: scannedPlugin.manifest.backstage.role,\n platform: 'web',\n // TODO(davidfestal): add required front-end plugin information here.\n });\n break;\n\n default:\n this.logger.info(\n `skipping dynamic plugin package '${scannedPlugin.manifest.name}' from '${scannedPlugin.location}': unrelated platform '${platform}'`,\n );\n }\n }\n return loadedPlugins;\n }\n\n private async loadBackendPlugin(\n plugin: ScannedPluginPackage,\n ): Promise {\n const usedPluginManifest =\n plugin.alphaManifest?.main ?? plugin.manifest.main;\n const usedPluginLocation = plugin.alphaManifest?.main\n ? `${plugin.location}/alpha`\n : plugin.location;\n const packagePath = url.fileURLToPath(\n `${usedPluginLocation}/${usedPluginManifest}`,\n );\n const dynamicPlugin: BackendDynamicPlugin = {\n name: plugin.manifest.name,\n version: plugin.manifest.version,\n platform: 'node',\n role: plugin.manifest.backstage.role,\n };\n\n try {\n const pluginModule = await this.moduleLoader.load(packagePath);\n\n if (isBackendFeature(pluginModule.default)) {\n dynamicPlugin.installer = {\n kind: 'new',\n install: () => pluginModule.default,\n };\n } else if (isBackendFeatureFactory(pluginModule.default)) {\n dynamicPlugin.installer = {\n kind: 'new',\n install: pluginModule.default,\n };\n } else if (\n isBackendDynamicPluginInstaller(pluginModule.dynamicPluginInstaller)\n ) {\n dynamicPlugin.installer = pluginModule.dynamicPluginInstaller;\n }\n if (dynamicPlugin.installer) {\n this.logger.info(\n `loaded dynamic backend plugin '${plugin.manifest.name}' from '${usedPluginLocation}'`,\n );\n } else {\n dynamicPlugin.failure = `the module should either export a 'BackendFeature' or 'BackendFeatureFactory' as default export, or export a 'const dynamicPluginInstaller: BackendDynamicPluginInstaller' field as dynamic loading entrypoint.`;\n this.logger.error(\n `dynamic backend plugin '${plugin.manifest.name}' could not be loaded from '${usedPluginLocation}': ${dynamicPlugin.failure}`,\n );\n }\n return dynamicPlugin;\n } catch (error) {\n const typedError =\n typeof error === 'object' && 'message' in error && 'name' in error\n ? error\n : new Error(error);\n dynamicPlugin.failure = `${typedError.name}: ${typedError.message}`;\n this.logger.error(\n `an error occurred while loading dynamic backend plugin '${plugin.manifest.name}' from '${usedPluginLocation}'`,\n typedError,\n );\n return dynamicPlugin;\n }\n }\n\n backendPlugins(options?: {\n includeFailed?: boolean;\n }): BackendDynamicPlugin[] {\n return this.plugins(options).filter(\n (p): p is BackendDynamicPlugin => p.platform === 'node',\n );\n }\n\n frontendPlugins(options?: {\n includeFailed?: boolean;\n }): FrontendDynamicPlugin[] {\n return this.plugins(options).filter(\n (p): p is FrontendDynamicPlugin => p.platform === 'web',\n );\n }\n\n plugins(options?: { includeFailed?: boolean }): DynamicPlugin[] {\n return this._plugins.filter(p => options?.includeFailed || !p.failure);\n }\n\n getScannedPackage(plugin: DynamicPlugin): ScannedPluginPackage {\n const pkg = this.packages.find(\n p =>\n p.manifest.name === plugin.name &&\n p.manifest.version === plugin.version,\n );\n if (pkg === undefined) {\n throw new Error(\n `The scanned package of a dynamic plugin should always be available: ${plugin.name}/${plugin.version}`,\n );\n }\n return pkg;\n }\n}\n\n/**\n * @public\n */\nexport const dynamicPluginsServiceRef = createServiceRef(\n {\n id: 'core.dynamicplugins',\n scope: 'root',\n },\n);\n\n/**\n * @public\n */\nexport interface DynamicPluginsFactoryOptions {\n moduleLoader?(logger: LoggerService): ModuleLoader | Promise;\n}\n\n/**\n * @public\n * @deprecated Use {@link dynamicPluginsFeatureLoader} instead, which gathers all services and features required for dynamic plugins.\n */\nexport const dynamicPluginsServiceFactoryWithOptions = (\n options?: DynamicPluginsFactoryOptions,\n) =>\n createServiceFactory({\n service: dynamicPluginsServiceRef,\n deps: {\n config: coreServices.rootConfig,\n logger: coreServices.rootLogger,\n },\n async factory({ config, logger }) {\n return await DynamicPluginManager.create({\n config,\n logger,\n preferAlpha: true,\n moduleLoader: await options?.moduleLoader?.(logger),\n });\n },\n });\n\n/**\n * @public\n * @deprecated Use {@link dynamicPluginsFeatureLoader} instead, which gathers all services and features required for dynamic plugins.\n */\nexport const dynamicPluginsServiceFactory = Object.assign(\n dynamicPluginsServiceFactoryWithOptions,\n dynamicPluginsServiceFactoryWithOptions(),\n);\n\nclass DynamicPluginsEnabledFeatureDiscoveryService {\n private readonly dynamicPlugins: DynamicPluginProvider;\n\n constructor(dynamicPlugins: DynamicPluginProvider) {\n this.dynamicPlugins = dynamicPlugins;\n }\n\n async getBackendFeatures(): Promise<{ features: Array }> {\n return {\n features: this.dynamicPlugins\n .backendPlugins()\n .flatMap((plugin): BackendFeature[] => {\n if (plugin.installer?.kind === 'new') {\n const installed = plugin.installer.install();\n if (Array.isArray(installed)) {\n return installed;\n }\n return [installed];\n }\n return [];\n }),\n };\n }\n}\n\n/**\n * @public\n * @deprecated Use {@link dynamicPluginsFeatureLoader} instead, which gathers all services and features required for dynamic plugins.\n */\nexport const dynamicPluginsFeatureDiscoveryLoader = createBackendFeatureLoader({\n deps: {\n dynamicPlugins: dynamicPluginsServiceRef,\n },\n async loader({ dynamicPlugins }) {\n const service = new DynamicPluginsEnabledFeatureDiscoveryService(\n dynamicPlugins,\n );\n const { features } = await service.getBackendFeatures();\n return features;\n },\n});\n\nfunction isBackendFeature(value: unknown): value is BackendFeature {\n return (\n !!value &&\n (typeof value === 'object' || typeof value === 'function') &&\n (value as BackendFeature).$$type === '@backstage/BackendFeature'\n );\n}\n\nfunction isBackendFeatureFactory(\n value: unknown,\n): value is () => BackendFeature {\n return (\n !!value &&\n typeof value === 'function' &&\n (value as any).$$type === '@backstage/BackendFeatureFactory'\n );\n}\n"],"names":["targetPaths","PluginScanner","CommonJSModuleLoader","fs","url","PackageRoles","isBackendDynamicPluginInstaller","createServiceRef","createServiceFactory","coreServices","createBackendFeatureLoader"],"mappings":"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"} +\ No newline at end of file ++{"version":3,"file":"plugin-manager.cjs.js","sources":["../../src/manager/plugin-manager.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { Config } from '@backstage/config';\nimport { toError } from '@backstage/errors';\nimport {\n DynamicPluginProvider,\n BackendDynamicPlugin,\n isBackendDynamicPluginInstaller,\n DynamicPlugin,\n FrontendDynamicPlugin,\n} from './types';\nimport { ScannedPluginPackage } from '../scanner';\nimport { PluginScanner } from '../scanner/plugin-scanner';\nimport { ModuleLoader } from '../loader';\nimport { CommonJSModuleLoader } from '../loader/CommonJSModuleLoader';\nimport path from 'node:path';\nimport * as url from 'node:url';\nimport {\n BackendFeature,\n LoggerService,\n coreServices,\n createBackendFeatureLoader,\n createServiceFactory,\n createServiceRef,\n} from '@backstage/backend-plugin-api';\nimport { PackageRole, PackageRoles } from '@backstage/cli-node';\nimport { targetPaths } from '@backstage/cli-common';\nimport * as fs from 'node:fs';\n\n/**\n * @public\n */\nexport interface DynamicPluginManagerOptions {\n config: Config;\n logger: LoggerService;\n preferAlpha?: boolean;\n moduleLoader?: ModuleLoader;\n}\n\n/**\n * @public\n */\nexport class DynamicPluginManager implements DynamicPluginProvider {\n static async create(\n options: DynamicPluginManagerOptions,\n ): Promise {\n /* eslint-disable-next-line no-restricted-syntax */\n const backstageRoot = targetPaths.rootDir;\n const scanner = PluginScanner.create({\n config: options.config,\n logger: options.logger,\n backstageRoot,\n preferAlpha: options.preferAlpha,\n });\n const scannedPlugins = (await scanner.scanRoot()).packages;\n await scanner.trackChanges();\n const moduleLoader =\n options.moduleLoader ||\n new CommonJSModuleLoader({ logger: options.logger });\n const manager = new DynamicPluginManager(\n options.logger,\n scannedPlugins,\n moduleLoader,\n );\n\n const scannedPluginManifestsPerRealPath = new Map(\n scannedPlugins.map(p => [\n fs.realpathSync(url.fileURLToPath(p.location)),\n p.manifest,\n ]),\n );\n\n await moduleLoader.bootstrap(\n backstageRoot,\n [...scannedPluginManifestsPerRealPath.keys()],\n scannedPluginManifestsPerRealPath,\n );\n\n scanner.subscribeToRootDirectoryChange(async () => {\n manager._availablePackages = (await scanner.scanRoot()).packages;\n // TODO: do not store _scannedPlugins again, but instead store a diff of the changes\n });\n manager._plugins.push(...(await manager.loadPlugins()));\n\n return manager;\n }\n\n private readonly _plugins: DynamicPlugin[];\n private _availablePackages: ScannedPluginPackage[];\n\n private readonly logger: LoggerService;\n private readonly packages: ScannedPluginPackage[];\n private readonly moduleLoader: ModuleLoader;\n\n private constructor(\n logger: LoggerService,\n packages: ScannedPluginPackage[],\n moduleLoader: ModuleLoader,\n ) {\n this.logger = logger;\n this.packages = packages;\n this.moduleLoader = moduleLoader;\n this._plugins = [];\n this._availablePackages = packages;\n }\n\n get availablePackages(): ScannedPluginPackage[] {\n return this._availablePackages;\n }\n\n addBackendPlugin(plugin: BackendDynamicPlugin): void {\n this._plugins.push(plugin);\n }\n\n private async loadPlugins(): Promise {\n const loadedPlugins: DynamicPlugin[] = [];\n\n for (const scannedPlugin of this.packages) {\n const role = scannedPlugin.manifest.backstage.role;\n const platform = PackageRoles.getRoleInfo(role).platform;\n const isPlugin =\n role.endsWith('-plugin') ||\n role.endsWith('-plugin-module') ||\n role === ('frontend-dynamic-container' as PackageRole);\n\n if (!isPlugin) {\n this.logger.info(\n `skipping dynamic plugin package '${scannedPlugin.manifest.name}' from '${scannedPlugin.location}': incompatible role '${role}'`,\n );\n continue;\n }\n\n switch (platform) {\n case 'node':\n loadedPlugins.push(await this.loadBackendPlugin(scannedPlugin));\n break;\n\n case 'web':\n loadedPlugins.push({\n name: scannedPlugin.manifest.name,\n version: scannedPlugin.manifest.version,\n role: scannedPlugin.manifest.backstage.role,\n platform: 'web',\n // TODO(davidfestal): add required front-end plugin information here.\n });\n break;\n\n default:\n this.logger.info(\n `skipping dynamic plugin package '${scannedPlugin.manifest.name}' from '${scannedPlugin.location}': unrelated platform '${platform}'`,\n );\n }\n }\n return loadedPlugins;\n }\n\n private async loadBackendPlugin(\n plugin: ScannedPluginPackage,\n ): Promise {\n const dynamicPlugin: BackendDynamicPlugin = {\n name: plugin.manifest.name,\n version: plugin.manifest.version,\n platform: 'node',\n role: plugin.manifest.backstage.role,\n };\n\n const entryPoints: Array<{ location: URL; manifest: string }> = [\n ...(plugin.alphaManifest?.main\n ? [\n {\n location: new URL(`${plugin.location}/alpha`),\n manifest: plugin.alphaManifest.main,\n },\n ]\n : []),\n {\n location: plugin.location,\n manifest: plugin.manifest.main,\n },\n ];\n\n for (const [index, { location, manifest }] of entryPoints.entries()) {\n const loadResult = await tryLoadBackendPluginEntry(\n this.moduleLoader,\n location,\n manifest,\n );\n\n if (loadResult.installer) {\n dynamicPlugin.installer = loadResult.installer;\n this.logger.info(\n `loaded dynamic backend plugin '${plugin.manifest.name}' from '${location}'`,\n );\n return dynamicPlugin;\n }\n\n if (index < entryPoints.length - 1) {\n continue;\n }\n\n if (loadResult.error) {\n dynamicPlugin.failure = `${loadResult.error.name}: ${loadResult.error.message}`;\n this.logger.error(\n `an error occurred while loading dynamic backend plugin '${plugin.manifest.name}' from '${location}'`,\n loadResult.error,\n );\n return dynamicPlugin;\n }\n\n dynamicPlugin.failure = `the module should either export a 'BackendFeature' or 'BackendFeatureFactory' as default export, or export a 'const dynamicPluginInstaller: BackendDynamicPluginInstaller' field as dynamic loading entrypoint.`;\n this.logger.error(\n `dynamic backend plugin '${plugin.manifest.name}' could not be loaded from '${location}': ${dynamicPlugin.failure}`,\n );\n return dynamicPlugin;\n }\n\n throw new Error(\n `Failed to load dynamic backend plugin '${plugin.manifest.name}': exhausted all entry points without producing a result`,\n );\n }\n\n backendPlugins(options?: {\n includeFailed?: boolean;\n }): BackendDynamicPlugin[] {\n return this.plugins(options).filter(\n (p): p is BackendDynamicPlugin => p.platform === 'node',\n );\n }\n\n frontendPlugins(options?: {\n includeFailed?: boolean;\n }): FrontendDynamicPlugin[] {\n return this.plugins(options).filter(\n (p): p is FrontendDynamicPlugin => p.platform === 'web',\n );\n }\n\n plugins(options?: { includeFailed?: boolean }): DynamicPlugin[] {\n return this._plugins.filter(p => options?.includeFailed || !p.failure);\n }\n\n getScannedPackage(plugin: DynamicPlugin): ScannedPluginPackage {\n const pkg = this.packages.find(\n p =>\n p.manifest.name === plugin.name &&\n p.manifest.version === plugin.version,\n );\n if (pkg === undefined) {\n throw new Error(\n `The scanned package of a dynamic plugin should always be available: ${plugin.name}/${plugin.version}`,\n );\n }\n return pkg;\n }\n}\n\n/**\n * @public\n */\nexport const dynamicPluginsServiceRef = createServiceRef(\n {\n id: 'core.dynamicplugins',\n scope: 'root',\n },\n);\n\n/**\n * @public\n */\nexport interface DynamicPluginsFactoryOptions {\n moduleLoader?(logger: LoggerService): ModuleLoader | Promise;\n}\n\n/**\n * @public\n * @deprecated Use {@link dynamicPluginsFeatureLoader} instead, which gathers all services and features required for dynamic plugins.\n */\nexport const dynamicPluginsServiceFactoryWithOptions = (\n options?: DynamicPluginsFactoryOptions,\n) =>\n createServiceFactory({\n service: dynamicPluginsServiceRef,\n deps: {\n config: coreServices.rootConfig,\n logger: coreServices.rootLogger,\n },\n async factory({ config, logger }) {\n return await DynamicPluginManager.create({\n config,\n logger,\n preferAlpha: true,\n moduleLoader: await options?.moduleLoader?.(logger),\n });\n },\n });\n\n/**\n * @public\n * @deprecated Use {@link dynamicPluginsFeatureLoader} instead, which gathers all services and features required for dynamic plugins.\n */\nexport const dynamicPluginsServiceFactory = Object.assign(\n dynamicPluginsServiceFactoryWithOptions,\n dynamicPluginsServiceFactoryWithOptions(),\n);\n\nclass DynamicPluginsEnabledFeatureDiscoveryService {\n private readonly dynamicPlugins: DynamicPluginProvider;\n\n constructor(dynamicPlugins: DynamicPluginProvider) {\n this.dynamicPlugins = dynamicPlugins;\n }\n\n async getBackendFeatures(): Promise<{ features: Array }> {\n return {\n features: this.dynamicPlugins\n .backendPlugins()\n .flatMap((plugin): BackendFeature[] => {\n if (plugin.installer?.kind === 'new') {\n const installed = plugin.installer.install();\n if (Array.isArray(installed)) {\n return installed;\n }\n return [installed];\n }\n return [];\n }),\n };\n }\n}\n\n/**\n * @public\n * @deprecated Use {@link dynamicPluginsFeatureLoader} instead, which gathers all services and features required for dynamic plugins.\n */\nexport const dynamicPluginsFeatureDiscoveryLoader = createBackendFeatureLoader({\n deps: {\n dynamicPlugins: dynamicPluginsServiceRef,\n },\n async loader({ dynamicPlugins }) {\n const service = new DynamicPluginsEnabledFeatureDiscoveryService(\n dynamicPlugins,\n );\n const { features } = await service.getBackendFeatures();\n return features;\n },\n});\n\nasync function tryLoadBackendPluginEntry(\n moduleLoader: ModuleLoader,\n location: URL,\n manifest: string,\n): Promise<{\n installer?: BackendDynamicPlugin['installer'];\n error?: Error;\n}> {\n try {\n const packagePath = path.resolve(url.fileURLToPath(location), manifest);\n const pluginModule = await moduleLoader.load(packagePath);\n return { installer: resolveInstallerFromModule(pluginModule) };\n } catch (error) {\n return { error: toError(error) };\n }\n}\n\nfunction resolveInstallerFromModule(\n pluginModule: Record,\n): BackendDynamicPlugin['installer'] | undefined {\n if (isBackendFeature(pluginModule.default)) {\n return {\n kind: 'new',\n install: () => pluginModule.default as BackendFeature,\n };\n }\n if (isBackendFeatureFactory(pluginModule.default)) {\n return {\n kind: 'new',\n install: pluginModule.default as () => BackendFeature,\n };\n }\n if (isBackendDynamicPluginInstaller(pluginModule.dynamicPluginInstaller)) {\n return pluginModule.dynamicPluginInstaller;\n }\n return undefined;\n}\n\nfunction isBackendFeature(value: unknown): value is BackendFeature {\n return (\n !!value &&\n (typeof value === 'object' || typeof value === 'function') &&\n (value as BackendFeature).$$type === '@backstage/BackendFeature'\n );\n}\n\nfunction isBackendFeatureFactory(\n value: unknown,\n): value is () => BackendFeature {\n return (\n !!value &&\n typeof value === 'function' &&\n (value as any).$$type === '@backstage/BackendFeatureFactory'\n );\n}\n"],"names":["targetPaths","PluginScanner","CommonJSModuleLoader","fs","url","PackageRoles","createServiceRef","createServiceFactory","coreServices","createBackendFeatureLoader","path","toError","isBackendDynamicPluginInstaller"],"mappings":"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"} +\ No newline at end of file diff --git a/packages/backend/package.json b/packages/backend/package.json index 6147c2b6bb..6f30fc58d4 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -25,7 +25,7 @@ "@backstage-community/plugin-rbac-node": "1.20.1", "@backstage/backend-app-api": "1.6.0", "@backstage/backend-defaults": "0.16.0", - "@backstage/backend-dynamic-feature-service": "0.8.0", + "@backstage/backend-dynamic-feature-service": "patch:@backstage/backend-dynamic-feature-service@npm%3A0.8.0#~/.yarn/patches/@backstage-backend-dynamic-feature-service-npm-0.8.0-92b2319b05.patch", "@backstage/backend-plugin-api": "1.8.0", "@backstage/catalog-client": "1.14.0", "@backstage/catalog-model": "1.7.7", diff --git a/plugins/dynamic-plugins-info-backend/package.json b/plugins/dynamic-plugins-info-backend/package.json index c54d3b9054..4a2e0fb088 100644 --- a/plugins/dynamic-plugins-info-backend/package.json +++ b/plugins/dynamic-plugins-info-backend/package.json @@ -33,7 +33,7 @@ }, "dependencies": { "@backstage/backend-defaults": "0.16.0", - "@backstage/backend-dynamic-feature-service": "0.8.0", + "@backstage/backend-dynamic-feature-service": "patch:@backstage/backend-dynamic-feature-service@npm%3A0.8.0#~/.yarn/patches/@backstage-backend-dynamic-feature-service-npm-0.8.0-92b2319b05.patch", "@backstage/backend-plugin-api": "1.8.0", "@backstage/config": "1.3.6", "express": "4.22.2", diff --git a/plugins/scalprum-backend/package.json b/plugins/scalprum-backend/package.json index a2613bcf0a..77075a106e 100644 --- a/plugins/scalprum-backend/package.json +++ b/plugins/scalprum-backend/package.json @@ -32,7 +32,7 @@ }, "dependencies": { "@backstage/backend-defaults": "0.16.0", - "@backstage/backend-dynamic-feature-service": "0.8.0", + "@backstage/backend-dynamic-feature-service": "patch:@backstage/backend-dynamic-feature-service@npm%3A0.8.0#~/.yarn/patches/@backstage-backend-dynamic-feature-service-npm-0.8.0-92b2319b05.patch", "@backstage/backend-plugin-api": "1.8.0", "@backstage/config": "1.3.6", "express": "4.22.2", diff --git a/yarn.lock b/yarn.lock index 3274742b39..8602c573a1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2881,6 +2881,41 @@ __metadata: languageName: node linkType: hard +"@backstage/backend-dynamic-feature-service@patch:@backstage/backend-dynamic-feature-service@npm%3A0.8.0#~/.yarn/patches/@backstage-backend-dynamic-feature-service-npm-0.8.0-92b2319b05.patch": + version: 0.8.0 + resolution: "@backstage/backend-dynamic-feature-service@patch:@backstage/backend-dynamic-feature-service@npm%3A0.8.0#~/.yarn/patches/@backstage-backend-dynamic-feature-service-npm-0.8.0-92b2319b05.patch::version=0.8.0&hash=7ee75f" + dependencies: + "@backstage/backend-defaults": "npm:^0.16.0" + "@backstage/backend-openapi-utils": "npm:^0.6.7" + "@backstage/backend-plugin-api": "npm:^1.8.0" + "@backstage/cli-common": "npm:^0.2.0" + "@backstage/cli-node": "npm:^0.3.0" + "@backstage/config": "npm:^1.3.6" + "@backstage/config-loader": "npm:^1.10.9" + "@backstage/errors": "npm:^1.2.7" + "@backstage/plugin-app-node": "npm:^0.1.43" + "@backstage/plugin-auth-node": "npm:^0.6.14" + "@backstage/plugin-catalog-backend": "npm:^3.5.0" + "@backstage/plugin-events-backend": "npm:^0.6.0" + "@backstage/plugin-events-node": "npm:^0.4.20" + "@backstage/plugin-permission-common": "npm:^0.9.7" + "@backstage/plugin-permission-node": "npm:^0.10.11" + "@backstage/plugin-scaffolder-node": "npm:^0.13.0" + "@backstage/plugin-search-backend-node": "npm:^1.4.2" + "@backstage/plugin-search-common": "npm:^1.2.22" + "@backstage/types": "npm:^1.2.2" + "@manypkg/get-packages": "npm:^1.1.3" + "@module-federation/sdk": "npm:^0.21.6" + chokidar: "npm:^3.5.3" + express: "npm:^4.22.0" + express-promise-router: "npm:^4.1.0" + fs-extra: "npm:^11.2.0" + lodash: "npm:^4.17.21" + winston: "npm:^3.2.1" + checksum: 10c0/e958d362569931aa6b88611492254061040e762035d3fb1e75b88a5aa2515be7c672c4cbca525f0ef45ec3d7684044a450f13b62f6e386317ad431a3144748b3 + languageName: node + linkType: hard + "@backstage/backend-openapi-utils@npm:^0.6.7": version: 0.6.7 resolution: "@backstage/backend-openapi-utils@npm:0.6.7" @@ -7070,7 +7105,7 @@ __metadata: resolution: "@internal/plugin-dynamic-plugins-info-backend@workspace:plugins/dynamic-plugins-info-backend" dependencies: "@backstage/backend-defaults": "npm:0.16.0" - "@backstage/backend-dynamic-feature-service": "npm:0.8.0" + "@backstage/backend-dynamic-feature-service": "patch:@backstage/backend-dynamic-feature-service@npm%3A0.8.0#~/.yarn/patches/@backstage-backend-dynamic-feature-service-npm-0.8.0-92b2319b05.patch" "@backstage/backend-plugin-api": "npm:1.8.0" "@backstage/backend-test-utils": "npm:1.11.1" "@backstage/cli": "npm:0.36.0" @@ -7126,7 +7161,7 @@ __metadata: resolution: "@internal/plugin-scalprum-backend@workspace:plugins/scalprum-backend" dependencies: "@backstage/backend-defaults": "npm:0.16.0" - "@backstage/backend-dynamic-feature-service": "npm:0.8.0" + "@backstage/backend-dynamic-feature-service": "patch:@backstage/backend-dynamic-feature-service@npm%3A0.8.0#~/.yarn/patches/@backstage-backend-dynamic-feature-service-npm-0.8.0-92b2319b05.patch" "@backstage/backend-plugin-api": "npm:1.8.0" "@backstage/backend-test-utils": "npm:1.11.1" "@backstage/cli": "npm:0.36.0" @@ -19066,7 +19101,7 @@ __metadata: "@backstage-community/plugin-rbac-node": "npm:1.20.1" "@backstage/backend-app-api": "npm:1.6.0" "@backstage/backend-defaults": "npm:0.16.0" - "@backstage/backend-dynamic-feature-service": "npm:0.8.0" + "@backstage/backend-dynamic-feature-service": "patch:@backstage/backend-dynamic-feature-service@npm%3A0.8.0#~/.yarn/patches/@backstage-backend-dynamic-feature-service-npm-0.8.0-92b2319b05.patch" "@backstage/backend-plugin-api": "npm:1.8.0" "@backstage/backend-test-utils": "npm:1.11.1" "@backstage/catalog-client": "npm:1.14.0"