From b6fc7f861f232aeccacf820485a3786ce6b98551 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 14 Mar 2026 15:43:01 +0100 Subject: [PATCH] frontend-app-api: fix phased predicate type checks Use internal extension shapes when reading predicate metadata and type the finalized app test helper explicitly. This fixes the typecheck breakage introduced by the phased predicate and override changes. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .../src/tree/resolveAppNodeSpecs.ts | 40 ++++++++++--------- .../src/wiring/InternalFrontendPlugin.ts | 2 +- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts b/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts index 318479d6b5..0e56fa4a98 100644 --- a/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts +++ b/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts @@ -56,12 +56,8 @@ function combinePredicates( } function getExtensionPredicate(options: { - extension: Extension; internalExtension: ReturnType; }) { - if (options.extension.version === 'v2') { - return options.extension.if; - } if (options.internalExtension.version === 'v2') { return options.internalExtension.if; } @@ -109,20 +105,27 @@ export function resolveAppNodeSpecs(options: { const pluginExtensions = plugins.flatMap(plugin => { const internalPlugin = OpaqueFrontendPlugin.toInternal(plugin); return internalPlugin.extensions - .map(extension => ({ - ...extension, - plugin, - if: combinePredicates( - internalPlugin.if, - extension.version === 'v2' ? extension.if : undefined, - ), - })) + .map(extension => { + const internalExtension = toInternalExtension(extension); + return { + ...internalExtension, + plugin, + if: combinePredicates( + internalPlugin.if, + internalExtension.version === 'v2' + ? internalExtension.if + : undefined, + ), + }; + }) .filter(filterForbidden); }); const moduleExtensions = modules.flatMap(mod => { const internalModule = toInternalFrontendModule(mod); return internalModule.extensions .flatMap(extension => { + const internalExtension = toInternalExtension(extension); + // Modules for plugins that are not installed are ignored const plugin = plugins.find(p => p.pluginId === mod.pluginId); if (!plugin) { @@ -131,11 +134,13 @@ export function resolveAppNodeSpecs(options: { return [ { - ...extension, + ...internalExtension, plugin, if: combinePredicates( internalModule.if, - extension.version === 'v2' ? extension.if : undefined, + internalExtension.version === 'v2' + ? internalExtension.if + : undefined, ), }, ]; @@ -159,7 +164,7 @@ export function resolveAppNodeSpecs(options: { source: plugin, attachTo: internalExtension.attachTo, disabled: internalExtension.disabled, - if: getExtensionPredicate({ extension, internalExtension }), + if: getExtensionPredicate({ internalExtension }), config: undefined as unknown, }, }; @@ -173,7 +178,7 @@ export function resolveAppNodeSpecs(options: { plugin: appPlugin, attachTo: internalExtension.attachTo, disabled: internalExtension.disabled, - if: getExtensionPredicate({ extension, internalExtension }), + if: getExtensionPredicate({ internalExtension }), config: undefined as unknown, }, }; @@ -194,7 +199,6 @@ export function resolveAppNodeSpecs(options: { configuredExtensions[index].params.attachTo = internalExtension.attachTo; configuredExtensions[index].params.disabled = internalExtension.disabled; configuredExtensions[index].params.if = getExtensionPredicate({ - extension, internalExtension, }); } else { @@ -206,7 +210,7 @@ export function resolveAppNodeSpecs(options: { source: extension.plugin, attachTo: internalExtension.attachTo, disabled: internalExtension.disabled, - if: getExtensionPredicate({ extension, internalExtension }), + if: getExtensionPredicate({ internalExtension }), config: undefined, }, }); diff --git a/packages/frontend-internal/src/wiring/InternalFrontendPlugin.ts b/packages/frontend-internal/src/wiring/InternalFrontendPlugin.ts index 8d62e08627..31af631a59 100644 --- a/packages/frontend-internal/src/wiring/InternalFrontendPlugin.ts +++ b/packages/frontend-internal/src/wiring/InternalFrontendPlugin.ts @@ -17,10 +17,10 @@ import { Extension, FeatureFlagConfig, - FilterPredicate, IconElement, OverridableFrontendPlugin, } from '@backstage/frontend-plugin-api'; +import { FilterPredicate } from '@backstage/filter-predicates'; import { JsonObject } from '@backstage/types'; import { OpaqueType } from '@internal/opaque';