fix: replace old config schemas for extensions and blueprints

to overcome a lot of warnings given during for example testing where
these extensions are used.

Signed-off-by: Hellgren Heikki <heikki.hellgren@op.fi>
This commit is contained in:
Hellgren Heikki
2026-04-15 10:54:23 +03:00
parent a321fc0c47
commit cad156e797
47 changed files with 332 additions and 285 deletions
+13
View File
@@ -0,0 +1,13 @@
---
'@backstage/frontend-plugin-api': patch
'@backstage/plugin-catalog-graph': patch
'@backstage/plugin-catalog-react': patch
'@backstage/plugin-search-react': patch
'@backstage/plugin-techdocs': patch
'@backstage/plugin-catalog': patch
'@backstage/plugin-search': patch
'@backstage/plugin-app': patch
'@backstage/plugin-org': patch
---
Replaced old config schema values from existing extensions and blueprints.
+1
View File
@@ -0,0 +1 @@
Replaced old config schema values from existing extensions and blueprints.
+1 -1
View File
@@ -27,8 +27,8 @@ const examplePlugin: OverridableFrontendPlugin<
title: string | undefined;
};
configInput: {
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
+8 -4
View File
@@ -1839,8 +1839,12 @@ export const NavItemBlueprint: ExtensionBlueprint_2<{
{}
>;
inputs: {};
config: {};
configInput: {};
config: {
title: string | undefined;
};
configInput: {
title?: string | undefined;
};
dataRefs: {
target: ConfigurableExtensionDataRef_2<
{
@@ -2258,8 +2262,8 @@ export const PageBlueprint: ExtensionBlueprint_2<{
title: string | undefined;
};
configInput: {
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
dataRefs: never;
}>;
@@ -2560,8 +2564,8 @@ export const SubPageBlueprint: ExtensionBlueprint_2<{
title: string | undefined;
};
configInput: {
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
dataRefs: never;
}>;
@@ -14,6 +14,7 @@
* limitations under the License.
*/
import { z } from 'zod/v4';
import { IconComponent } from '../icons/types';
import { RouteRef } from '../routing';
import { createExtensionBlueprint, createExtensionDataRef } from '../wiring';
@@ -59,9 +60,7 @@ export const NavItemBlueprint = createExtensionBlueprint({
routeRef,
}),
],
config: {
schema: {
title: z => z.string().optional(),
},
configSchema: {
title: z.string().optional(),
},
});
@@ -14,6 +14,7 @@
* limitations under the License.
*/
import { z } from 'zod/v4';
import { JSX } from 'react';
import { Routes, Route, Navigate } from 'react-router-dom';
import { IconElement } from '../icons/types';
@@ -68,11 +69,9 @@ export const PageBlueprint = createExtensionBlueprint({
coreExtensionData.title.optional(),
coreExtensionData.icon.optional(),
],
config: {
schema: {
path: z => z.string().optional(),
title: z => z.string().optional(),
},
configSchema: {
path: z.string().optional(),
title: z.string().optional(),
},
*factory(
params: {
@@ -14,6 +14,7 @@
* limitations under the License.
*/
import { z } from 'zod/v4';
import { IconElement } from '../icons/types';
import { RouteRef } from '../routing';
import { coreExtensionData, createExtensionBlueprint } from '../wiring';
@@ -50,11 +51,9 @@ export const SubPageBlueprint = createExtensionBlueprint({
coreExtensionData.routeRef.optional(),
coreExtensionData.icon.optional(),
],
config: {
schema: {
path: z => z.string().optional(),
title: z => z.string().optional(),
},
configSchema: {
path: z.string().optional(),
title: z.string().optional(),
},
*factory(
params: {
+7 -3
View File
@@ -475,8 +475,12 @@ const _default: OverridableFrontendPlugin<
'nav-item:api-docs': OverridableExtensionDefinition<{
kind: 'nav-item';
name: undefined;
config: {};
configInput: {};
config: {
title: string | undefined;
};
configInput: {
title?: string | undefined;
};
output: ExtensionDataRef<
{
title: string;
@@ -501,8 +505,8 @@ const _default: OverridableFrontendPlugin<
};
configInput: {
initiallySelectedFilter?: 'all' | 'owned' | 'starred' | undefined;
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
+10 -6
View File
@@ -22,8 +22,12 @@ const visualizerPlugin: OverridableFrontendPlugin<
'nav-item:app-visualizer': OverridableExtensionDefinition<{
kind: 'nav-item';
name: undefined;
config: {};
configInput: {};
config: {
title: string | undefined;
};
configInput: {
title?: string | undefined;
};
output: ExtensionDataRef<
{
title: string;
@@ -48,8 +52,8 @@ const visualizerPlugin: OverridableFrontendPlugin<
title: string | undefined;
};
configInput: {
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
@@ -135,8 +139,8 @@ const visualizerPlugin: OverridableFrontendPlugin<
title: string | undefined;
};
configInput: {
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
@@ -173,8 +177,8 @@ const visualizerPlugin: OverridableFrontendPlugin<
title: string | undefined;
};
configInput: {
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
@@ -211,8 +215,8 @@ const visualizerPlugin: OverridableFrontendPlugin<
title: string | undefined;
};
configInput: {
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
+3 -3
View File
@@ -818,18 +818,18 @@ const appPlugin: OverridableFrontendPlugin<
config: {
transientTimeoutMs: number;
anchorOrigin: {
horizontal: 'center' | 'left' | 'right';
vertical: 'top' | 'bottom';
horizontal: 'center' | 'left' | 'right';
};
};
configInput: {
transientTimeoutMs?: number | undefined;
anchorOrigin?:
| {
horizontal?: 'center' | 'left' | 'right' | undefined;
vertical?: 'top' | 'bottom' | undefined;
horizontal?: 'center' | 'left' | 'right' | undefined;
}
| undefined;
transientTimeoutMs?: number | undefined;
};
output: ExtensionDataRef<JSX_2.Element, 'core.reactElement', {}>;
inputs: {};
+1 -1
View File
@@ -18,7 +18,7 @@
import { AppLanguageSelector } from '../../../../packages/core-app-api/src/apis/implementations/AppLanguageApi';
import { appLanguageApiRef } from '@backstage/frontend-plugin-api';
import { ApiBlueprint } from '@backstage/frontend-plugin-api';
import { z } from 'zod';
import { z } from 'zod/v4';
export const AppLanguageApi = ApiBlueprint.makeWithOverrides({
name: 'app-language',
+10 -12
View File
@@ -14,6 +14,7 @@
* limitations under the License.
*/
import { z } from 'zod/v4';
import {
createExtension,
coreExtensionData,
@@ -32,18 +33,15 @@ export const AppRoutes = createExtension({
coreExtensionData.reactElement,
]),
},
config: {
schema: {
redirects: z =>
z
.array(
z.object({
from: z.string(),
to: z.string(),
}),
)
.optional(),
},
configSchema: {
redirects: z
.array(
z.object({
from: z.string(),
to: z.string(),
}),
)
.optional(),
},
output: [coreExtensionData.reactElement],
factory({ inputs, config }) {
+12 -11
View File
@@ -16,6 +16,7 @@
import { OAuthRequestDialog } from '@backstage/core-components';
import { AppRootElementBlueprint } from '@backstage/frontend-plugin-api';
import { z } from 'zod/v4';
import { ToastDisplay } from '../components/Toast';
export const oauthRequestDialogAppRootElement = AppRootElementBlueprint.make({
@@ -28,17 +29,17 @@ export const oauthRequestDialogAppRootElement = AppRootElementBlueprint.make({
export const alertDisplayAppRootElement =
AppRootElementBlueprint.makeWithOverrides({
name: 'alert-display',
config: {
schema: {
transientTimeoutMs: z => z.number().default(5000),
anchorOrigin: z =>
z
.object({
vertical: z.enum(['top', 'bottom']).default('top'),
horizontal: z.enum(['left', 'center', 'right']).default('center'),
})
.default({}),
},
configSchema: {
transientTimeoutMs: z.number().default(5000),
anchorOrigin: z
.object({
vertical: z.enum(['top', 'bottom']).default('top'),
horizontal: z.enum(['left', 'center', 'right']).default('center'),
})
.default({
vertical: 'top',
horizontal: 'center',
}),
},
factory: (originalFactory, { config }) => {
return originalFactory({
+1 -1
View File
@@ -28,8 +28,8 @@ const _default: OverridableFrontendPlugin<
title: string | undefined;
};
configInput: {
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
+2 -1
View File
@@ -65,7 +65,8 @@
"lodash": "^4.17.15",
"p-limit": "^3.1.0",
"qs": "^6.9.4",
"react-use": "^17.2.4"
"react-use": "^17.2.4",
"zod": "^3.25.76 || ^4.0.0"
},
"devDependencies": {
"@backstage/cli": "workspace:^",
+22 -22
View File
@@ -99,18 +99,18 @@ const _default: OverridableFrontendPlugin<
type: 'content' | 'info' | undefined;
};
configInput: {
height?: number | undefined;
curve?: 'curveStepBefore' | 'curveMonotoneX' | undefined;
direction?: 'TB' | 'BT' | 'LR' | 'RL' | undefined;
zoom?: 'disabled' | 'enabled' | 'enable-on-click' | undefined;
title?: string | undefined;
showArrowHeads?: boolean | undefined;
kinds?: string[] | undefined;
relations?: string[] | undefined;
maxDepth?: number | undefined;
kinds?: string[] | undefined;
mergeRelations?: boolean | undefined;
relationPairs?: [string, string][] | undefined;
unidirectional?: boolean | undefined;
mergeRelations?: boolean | undefined;
showArrowHeads?: boolean | undefined;
direction?: 'TB' | 'BT' | 'LR' | 'RL' | undefined;
relationPairs?: [string, string][] | undefined;
zoom?: 'disabled' | 'enabled' | 'enable-on-click' | undefined;
curve?: 'curveStepBefore' | 'curveMonotoneX' | undefined;
title?: string | undefined;
height?: number | undefined;
filter?: FilterPredicate | undefined;
type?: 'content' | 'info' | undefined;
};
@@ -166,22 +166,22 @@ const _default: OverridableFrontendPlugin<
title: string | undefined;
};
configInput: {
curve?: 'curveStepBefore' | 'curveMonotoneX' | undefined;
direction?: 'TB' | 'BT' | 'LR' | 'RL' | undefined;
zoom?: 'disabled' | 'enabled' | 'enable-on-click' | undefined;
showArrowHeads?: boolean | undefined;
relations?: string[] | undefined;
maxDepth?: number | undefined;
rootEntityRefs?: string[] | undefined;
kinds?: string[] | undefined;
mergeRelations?: boolean | undefined;
relationPairs?: [string, string][] | undefined;
unidirectional?: boolean | undefined;
selectedRelations?: string[] | undefined;
selectedKinds?: string[] | undefined;
selectedRelations?: string[] | undefined;
rootEntityRefs?: string[] | undefined;
maxDepth?: number | undefined;
unidirectional?: boolean | undefined;
mergeRelations?: boolean | undefined;
showArrowHeads?: boolean | undefined;
direction?: 'TB' | 'BT' | 'LR' | 'RL' | undefined;
showFilters?: boolean | undefined;
title?: string | undefined;
curve?: 'curveStepBefore' | 'curveMonotoneX' | undefined;
kinds?: string[] | undefined;
relations?: string[] | undefined;
relationPairs?: [string, string][] | undefined;
zoom?: 'disabled' | 'enabled' | 'enable-on-click' | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
+31 -34
View File
@@ -19,6 +19,7 @@ import {
createFrontendPlugin,
PageBlueprint,
} from '@backstage/frontend-plugin-api';
import { z } from 'zod/v4';
import { RiMindMap } from '@remixicon/react';
import { EntityCardBlueprint } from '@backstage/plugin-catalog-react/alpha';
import { catalogGraphRouteRef, catalogEntityRouteRef } from './routes';
@@ -30,23 +31,21 @@ import {
const CatalogGraphEntityCard = EntityCardBlueprint.makeWithOverrides({
name: 'relations',
config: {
schema: {
kinds: z => z.array(z.string()).optional(),
relations: z => z.array(z.string()).optional(),
maxDepth: z => z.number().optional(),
unidirectional: z => z.boolean().optional(),
mergeRelations: z => z.boolean().optional(),
showArrowHeads: z => z.boolean().optional(),
direction: z => z.nativeEnum(Direction).optional(),
relationPairs: z => z.array(z.tuple([z.string(), z.string()])).optional(),
zoom: z => z.enum(['enabled', 'disabled', 'enable-on-click']).optional(),
curve: z => z.enum(['curveStepBefore', 'curveMonotoneX']).optional(),
// Skipping a "variant" config for now, defaulting to "gridItem" in the component
// For more details, see this comment: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252
title: z => z.string().optional(),
height: z => z.number().optional(),
},
configSchema: {
kinds: z.array(z.string()).optional(),
relations: z.array(z.string()).optional(),
maxDepth: z.number().optional(),
unidirectional: z.boolean().optional(),
mergeRelations: z.boolean().optional(),
showArrowHeads: z.boolean().optional(),
direction: z.nativeEnum(Direction).optional(),
relationPairs: z.array(z.tuple([z.string(), z.string()])).optional(),
zoom: z.enum(['enabled', 'disabled', 'enable-on-click']).optional(),
curve: z.enum(['curveStepBefore', 'curveMonotoneX']).optional(),
// Skipping a "variant" config for now, defaulting to "gridItem" in the component
// For more details, see this comment: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252
title: z.string().optional(),
height: z.number().optional(),
},
factory(originalFactory, { config }) {
return originalFactory({
@@ -59,23 +58,21 @@ const CatalogGraphEntityCard = EntityCardBlueprint.makeWithOverrides({
});
const CatalogGraphPage = PageBlueprint.makeWithOverrides({
config: {
schema: {
selectedKinds: z => z.array(z.string()).optional(),
selectedRelations: z => z.array(z.string()).optional(),
rootEntityRefs: z => z.array(z.string()).optional(),
maxDepth: z => z.number().optional(),
unidirectional: z => z.boolean().optional(),
mergeRelations: z => z.boolean().optional(),
showArrowHeads: z => z.boolean().optional(),
direction: z => z.nativeEnum(Direction).optional(),
showFilters: z => z.boolean().optional(),
curve: z => z.enum(['curveStepBefore', 'curveMonotoneX']).optional(),
kinds: z => z.array(z.string()).optional(),
relations: z => z.array(z.string()).optional(),
relationPairs: z => z.array(z.tuple([z.string(), z.string()])).optional(),
zoom: z => z.enum(['enabled', 'disabled', 'enable-on-click']).optional(),
},
configSchema: {
selectedKinds: z.array(z.string()).optional(),
selectedRelations: z.array(z.string()).optional(),
rootEntityRefs: z.array(z.string()).optional(),
maxDepth: z.number().optional(),
unidirectional: z.boolean().optional(),
mergeRelations: z.boolean().optional(),
showArrowHeads: z.boolean().optional(),
direction: z.nativeEnum(Direction).optional(),
showFilters: z.boolean().optional(),
curve: z.enum(['curveStepBefore', 'curveMonotoneX']).optional(),
kinds: z.array(z.string()).optional(),
relations: z.array(z.string()).optional(),
relationPairs: z.array(z.tuple([z.string(), z.string()])).optional(),
zoom: z.enum(['enabled', 'disabled', 'enable-on-click']).optional(),
},
factory(originalFactory, { config }) {
return originalFactory({
+1 -1
View File
@@ -121,8 +121,8 @@ const _default: OverridableFrontendPlugin<
title: string | undefined;
};
configInput: {
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
+2 -2
View File
@@ -418,8 +418,8 @@ export const EntityContentLayoutBlueprint: ExtensionBlueprint<{
filter: FilterPredicate | undefined;
};
configInput: {
filter?: FilterPredicate | undefined;
type?: string | undefined;
filter?: FilterPredicate | undefined;
};
dataRefs: {
filterFunction: ConfigurableExtensionDataRef<
@@ -611,9 +611,9 @@ export const EntityIconLinkBlueprint: ExtensionBlueprint<{
filter: FilterPredicate | undefined;
};
configInput: {
filter?: FilterPredicate | undefined;
label?: string | undefined;
title?: string | undefined;
filter?: FilterPredicate | undefined;
};
dataRefs: {
useProps: ConfigurableExtensionDataRef<
@@ -27,8 +27,9 @@ import {
import { JSX } from 'react';
import {
FilterPredicate,
createZodV3FilterPredicateSchema,
createZodV4FilterPredicateSchema,
} from '@backstage/filter-predicates';
import { z } from 'zod/v4';
import { resolveEntityFilterData } from './resolveEntityFilterData';
import { Entity } from '@backstage/catalog-model';
@@ -60,12 +61,11 @@ export const EntityContentLayoutBlueprint = createExtensionBlueprint({
filterExpression: entityFilterExpressionDataRef,
component: entityCardLayoutComponentDataRef,
},
config: {
schema: {
type: z => z.string().optional(),
filter: z =>
z.union([z.string(), createZodV3FilterPredicateSchema(z)]).optional(),
},
configSchema: {
type: z.string().optional(),
filter: z
.union([z.string(), createZodV4FilterPredicateSchema()])
.optional(),
},
*factory(
{
@@ -27,7 +27,7 @@ import { useEntityContextMenu } from '../../hooks/useEntityContextMenu';
import {
FilterPredicate,
filterPredicateToFilterFunction,
createZodV3FilterPredicateSchema,
createZodV4FilterPredicateSchema,
} from '@backstage/filter-predicates';
import type { Entity } from '@backstage/catalog-model';
import { entityFilterFunctionDataRef } from './extensionData';
@@ -62,10 +62,8 @@ export const EntityContextMenuItemBlueprint = createExtensionBlueprint({
dataRefs: {
filterFunction: entityFilterFunctionDataRef,
},
config: {
schema: {
filter: z => createZodV3FilterPredicateSchema(z).optional(),
},
configSchema: {
filter: createZodV4FilterPredicateSchema().optional(),
},
*factory(params: EntityContextMenuItemParams, { node, config }) {
const loader = async () => {
@@ -21,7 +21,7 @@ import {
} from '@backstage/frontend-plugin-api';
import {
FilterPredicate,
createZodV3FilterPredicateSchema,
createZodV4FilterPredicateSchema,
} from '@backstage/filter-predicates';
import { Entity } from '@backstage/catalog-model';
import { resolveEntityFilterData } from './resolveEntityFilterData';
@@ -38,10 +38,8 @@ export const EntityHeaderBlueprint = createExtensionBlueprint({
filterFunction: entityFilterFunctionDataRef,
element: coreExtensionData.reactElement,
},
config: {
schema: {
filter: z => createZodV3FilterPredicateSchema(z).optional(),
},
configSchema: {
filter: createZodV4FilterPredicateSchema().optional(),
},
output: [
entityFilterFunctionDataRef.optional(),
@@ -22,9 +22,11 @@ import {
import {
FilterPredicate,
createZodV3FilterPredicateSchema,
createZodV4FilterPredicateSchema,
} from '@backstage/filter-predicates';
import { z } from 'zod/v4';
import {
entityFilterExpressionDataRef,
entityFilterFunctionDataRef,
@@ -52,12 +54,10 @@ export const EntityIconLinkBlueprint = createExtensionBlueprint({
filterFunction: entityFilterFunctionDataRef,
filterExpression: entityFilterExpressionDataRef,
},
config: {
schema: {
label: z => z.string().optional(),
title: z => z.string().optional(),
filter: z => createZodV3FilterPredicateSchema(z).optional(),
},
configSchema: {
label: z.string().optional(),
title: z.string().optional(),
filter: createZodV4FilterPredicateSchema().optional(),
},
*factory(
params: {
@@ -43,8 +43,12 @@ const _default: OverridableFrontendPlugin<
'nav-item:catalog-unprocessed-entities': OverridableExtensionDefinition<{
kind: 'nav-item';
name: undefined;
config: {};
configInput: {};
config: {
title: string | undefined;
};
configInput: {
title?: string | undefined;
};
output: ExtensionDataRef<
{
title: string;
@@ -69,8 +73,8 @@ const _default: OverridableFrontendPlugin<
title: string | undefined;
};
configInput: {
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
@@ -145,8 +149,8 @@ const _default: OverridableFrontendPlugin<
title: string | undefined;
};
configInput: {
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
+2 -1
View File
@@ -88,7 +88,8 @@
"pluralize": "^8.0.0",
"react-helmet": "6.1.0",
"react-use": "^17.2.4",
"zen-observable": "^0.10.0"
"zen-observable": "^0.10.0",
"zod": "^3.25.76 || ^4.0.0"
},
"devDependencies": {
"@backstage/cli": "workspace:^",
+11 -7
View File
@@ -997,9 +997,9 @@ const _default: OverridableFrontendPlugin<
filter: FilterPredicate | undefined;
};
configInput: {
filter?: FilterPredicate | undefined;
label?: string | undefined;
title?: string | undefined;
filter?: FilterPredicate | undefined;
};
output:
| ExtensionDataRef<
@@ -1030,8 +1030,12 @@ const _default: OverridableFrontendPlugin<
'nav-item:catalog': OverridableExtensionDefinition<{
kind: 'nav-item';
name: undefined;
config: {};
configInput: {};
config: {
title: string | undefined;
};
configInput: {
title?: string | undefined;
};
output: ExtensionDataRef<
{
title: string;
@@ -1054,8 +1058,8 @@ const _default: OverridableFrontendPlugin<
| boolean
| {
mode: 'offset' | 'cursor';
offset?: number | undefined;
limit?: number | undefined;
offset?: number | undefined;
};
path: string | undefined;
title: string | undefined;
@@ -1065,12 +1069,12 @@ const _default: OverridableFrontendPlugin<
| boolean
| {
mode: 'offset' | 'cursor';
offset?: number | undefined;
limit?: number | undefined;
offset?: number | undefined;
}
| undefined;
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
@@ -1179,8 +1183,8 @@ const _default: OverridableFrontendPlugin<
| undefined;
defaultContentOrder?: 'title' | 'natural' | undefined;
showNavItemIcons?: boolean | undefined;
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
+7 -12
View File
@@ -15,6 +15,7 @@
*/
import { CatalogFilterBlueprint } from '@backstage/plugin-catalog-react/alpha';
import { z } from 'zod/v4';
const catalogTagCatalogFilter = CatalogFilterBlueprint.make({
name: 'tag',
@@ -30,10 +31,8 @@ const catalogTagCatalogFilter = CatalogFilterBlueprint.make({
const catalogKindCatalogFilter = CatalogFilterBlueprint.makeWithOverrides({
name: 'kind',
config: {
schema: {
initialFilter: z => z.string().default('component'),
},
configSchema: {
initialFilter: z.string().default('component'),
},
factory(originalFactory, { config }) {
return originalFactory({
@@ -61,10 +60,8 @@ const catalogTypeCatalogFilter = CatalogFilterBlueprint.make({
const catalogModeCatalogFilter = CatalogFilterBlueprint.makeWithOverrides({
name: 'mode',
config: {
schema: {
mode: z => z.enum(['owners-only', 'all']).optional(),
},
configSchema: {
mode: z.enum(['owners-only', 'all']).optional(),
},
factory(originalFactory, { config }) {
return originalFactory({
@@ -116,10 +113,8 @@ const catalogProcessingStatusCatalogFilter = CatalogFilterBlueprint.make({
const catalogListCatalogFilter = CatalogFilterBlueprint.makeWithOverrides({
name: 'list',
config: {
schema: {
initialFilter: z => z.enum(['owned', 'starred', 'all']).default('owned'),
},
configSchema: {
initialFilter: z.enum(['owned', 'starred', 'all']).default('owned'),
},
factory(originalFactory, { config }) {
return originalFactory({
+31 -34
View File
@@ -20,6 +20,7 @@ import {
createExtensionInput,
PageBlueprint,
} from '@backstage/frontend-plugin-api';
import { z } from 'zod/v4';
import {
AsyncEntityProvider,
entityRouteRef,
@@ -40,20 +41,17 @@ export const catalogPage = PageBlueprint.makeWithOverrides({
inputs: {
filters: createExtensionInput([coreExtensionData.reactElement]),
},
config: {
schema: {
pagination: z =>
z
.union([
z.boolean(),
z.object({
mode: z.enum(['cursor', 'offset']),
limit: z.number().optional(),
offset: z.number().optional(),
}),
])
.default(true),
},
configSchema: {
pagination: z
.union([
z.boolean(),
z.object({
mode: z.enum(['cursor', 'offset']),
limit: z.number().optional(),
offset: z.number().optional(),
}),
])
.default(true),
},
factory(originalFactory, { inputs, config }) {
return originalFactory({
@@ -101,26 +99,25 @@ export const catalogEntityPage = PageBlueprint.makeWithOverrides({
EntityContextMenuItemBlueprint.dataRefs.filterFunction.optional(),
]),
},
config: {
schema: {
groups: z =>
z
.array(
z.record(
z.string(),
z.object({
title: z.string(),
icon: z.string().optional(),
aliases: z.array(z.string()).optional(),
contentOrder: z.enum(['title', 'natural']).optional(),
}),
),
)
.optional(),
defaultContentOrder: z =>
z.enum(['title', 'natural']).optional().default('title'),
showNavItemIcons: z => z.boolean().optional().default(false),
},
configSchema: {
groups: z
.array(
z.record(
z.string(),
z.object({
title: z.string(),
icon: z.string().optional(),
aliases: z.array(z.string()).optional(),
contentOrder: z.enum(['title', 'natural']).optional(),
}),
),
)
.optional(),
defaultContentOrder: z
.enum(['title', 'natural'])
.optional()
.default('title'),
showNavItemIcons: z.boolean().optional().default(false),
},
factory(originalFactory, { config, inputs }) {
return originalFactory({
+10 -6
View File
@@ -43,8 +43,12 @@ const _default: OverridableFrontendPlugin<
'nav-item:devtools': OverridableExtensionDefinition<{
kind: 'nav-item';
name: undefined;
config: {};
configInput: {};
config: {
title: string | undefined;
};
configInput: {
title?: string | undefined;
};
output: ExtensionDataRef<
{
title: string;
@@ -67,8 +71,8 @@ const _default: OverridableFrontendPlugin<
title: string | undefined;
};
configInput: {
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
@@ -145,8 +149,8 @@ const _default: OverridableFrontendPlugin<
title: string | undefined;
};
configInput: {
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
@@ -183,8 +187,8 @@ const _default: OverridableFrontendPlugin<
title: string | undefined;
};
configInput: {
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
@@ -221,8 +225,8 @@ const _default: OverridableFrontendPlugin<
title: string | undefined;
};
configInput: {
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
+7 -3
View File
@@ -84,8 +84,12 @@ const _default: OverridableFrontendPlugin<
'nav-item:home': OverridableExtensionDefinition<{
kind: 'nav-item';
name: undefined;
config: {};
configInput: {};
config: {
title: string | undefined;
};
configInput: {
title?: string | undefined;
};
output: ExtensionDataRef<
{
title: string;
@@ -108,8 +112,8 @@ const _default: OverridableFrontendPlugin<
title: string | undefined;
};
configInput: {
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
+1 -1
View File
@@ -168,8 +168,8 @@ const _default: OverridableFrontendPlugin<
title: string | undefined;
};
configInput: {
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
+1 -1
View File
@@ -42,8 +42,8 @@ const _default: OverridableFrontendPlugin<
title: string | undefined;
};
configInput: {
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
+1 -1
View File
@@ -48,8 +48,8 @@ const _default: OverridableFrontendPlugin<
title: string | undefined;
};
configInput: {
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
+2 -1
View File
@@ -66,7 +66,8 @@
"p-limit": "^3.1.0",
"pluralize": "^8.0.0",
"qs": "^6.10.1",
"react-use": "^17.2.4"
"react-use": "^17.2.4",
"zod": "^3.25.76 || ^4.0.0"
},
"devDependencies": {
"@backstage/catalog-client": "workspace:^",
+3 -3
View File
@@ -69,8 +69,8 @@ const _default: OverridableFrontendPlugin<
type: 'content' | 'info' | undefined;
};
configInput: {
showAggregateMembersToggle?: boolean | undefined;
initialRelationAggregation?: 'direct' | 'aggregated' | undefined;
showAggregateMembersToggle?: boolean | undefined;
filter?: FilterPredicate | undefined;
type?: 'content' | 'info' | undefined;
};
@@ -115,8 +115,8 @@ const _default: OverridableFrontendPlugin<
type: 'content' | 'info' | undefined;
};
configInput: {
showAggregateMembersToggle?: boolean | undefined;
initialRelationAggregation?: 'direct' | 'aggregated' | undefined;
showAggregateMembersToggle?: boolean | undefined;
ownedKinds?: string[] | undefined;
filter?: FilterPredicate | undefined;
type?: 'content' | 'info' | undefined;
@@ -161,8 +161,8 @@ const _default: OverridableFrontendPlugin<
type: 'content' | 'info' | undefined;
};
configInput: {
hideIcons?: boolean | undefined;
maxRelations?: number | undefined;
hideIcons?: boolean | undefined;
filter?: FilterPredicate | undefined;
type?: 'content' | 'info' | undefined;
};
+11 -18
View File
@@ -15,6 +15,7 @@
*/
import { createFrontendPlugin } from '@backstage/frontend-plugin-api';
import { z } from 'zod/v4';
import { RiTeamLine } from '@remixicon/react';
import { catalogIndexRouteRef } from './routes';
import { EntityCardBlueprint } from '@backstage/plugin-catalog-react/alpha';
@@ -35,12 +36,9 @@ const EntityGroupProfileCard = EntityCardBlueprint.make({
/** @alpha */
const EntityMembersListCard = EntityCardBlueprint.makeWithOverrides({
name: 'members-list',
config: {
schema: {
initialRelationAggregation: z =>
z.enum(['direct', 'aggregated']).optional(),
showAggregateMembersToggle: z => z.boolean().optional(),
},
configSchema: {
initialRelationAggregation: z.enum(['direct', 'aggregated']).optional(),
showAggregateMembersToggle: z.boolean().optional(),
},
factory(originalFactory, { config }) {
return originalFactory({
@@ -61,13 +59,10 @@ const EntityMembersListCard = EntityCardBlueprint.makeWithOverrides({
/** @alpha */
const EntityOwnershipCard = EntityCardBlueprint.makeWithOverrides({
name: 'ownership',
config: {
schema: {
initialRelationAggregation: z =>
z.enum(['direct', 'aggregated']).optional(),
showAggregateMembersToggle: z => z.boolean().optional(),
ownedKinds: z => z.array(z.string()).optional(),
},
configSchema: {
initialRelationAggregation: z.enum(['direct', 'aggregated']).optional(),
showAggregateMembersToggle: z.boolean().optional(),
ownedKinds: z.array(z.string()).optional(),
},
factory(originalFactory, { config }) {
return originalFactory({
@@ -93,11 +88,9 @@ const EntityOwnershipCard = EntityCardBlueprint.makeWithOverrides({
/** @alpha */
const EntityUserProfileCard = EntityCardBlueprint.makeWithOverrides({
name: 'user-profile',
config: {
schema: {
maxRelations: z => z.number().optional(),
hideIcons: z => z.boolean().default(false),
},
configSchema: {
maxRelations: z.number().optional(),
hideIcons: z.boolean().default(false),
},
factory(originalFactory, { config }) {
return originalFactory({
+13 -9
View File
@@ -143,9 +143,9 @@ const _default: OverridableFrontendPlugin<
filter: FilterPredicate | undefined;
};
configInput: {
filter?: FilterPredicate | undefined;
label?: string | undefined;
title?: string | undefined;
filter?: FilterPredicate | undefined;
};
output:
| ExtensionDataRef<
@@ -176,8 +176,12 @@ const _default: OverridableFrontendPlugin<
'nav-item:scaffolder': OverridableExtensionDefinition<{
kind: 'nav-item';
name: undefined;
config: {};
configInput: {};
config: {
title: string | undefined;
};
configInput: {
title?: string | undefined;
};
output: ExtensionDataRef<
{
title: string;
@@ -200,8 +204,8 @@ const _default: OverridableFrontendPlugin<
title: string | undefined;
};
configInput: {
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
@@ -440,8 +444,8 @@ const _default: OverridableFrontendPlugin<
title: string | undefined;
};
configInput: {
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
@@ -478,8 +482,8 @@ const _default: OverridableFrontendPlugin<
title: string | undefined;
};
configInput: {
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
@@ -516,8 +520,8 @@ const _default: OverridableFrontendPlugin<
title: string | undefined;
};
configInput: {
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
@@ -552,8 +556,8 @@ const _default: OverridableFrontendPlugin<
title: string | undefined;
};
configInput: {
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
@@ -592,8 +596,8 @@ const _default: OverridableFrontendPlugin<
title: string | undefined;
};
configInput: {
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
+2 -1
View File
@@ -69,7 +69,8 @@
"lodash": "^4.17.21",
"qs": "^6.9.4",
"react-use": "^17.3.2",
"uuid": "^11.0.2"
"uuid": "^11.0.2",
"zod": "^3.25.76 || ^4.0.0"
},
"devDependencies": {
"@backstage/cli": "workspace:^",
@@ -15,6 +15,7 @@
*/
import { lazy, JSX } from 'react';
import { z } from 'zod/v4';
import {
createExtensionBlueprint,
ExtensionBoundary,
@@ -59,10 +60,8 @@ export const SearchResultListItemBlueprint = createExtensionBlueprint({
id: 'page:search',
input: 'items',
},
config: {
schema: {
noTrack: z => z.boolean().default(false),
},
configSchema: {
noTrack: z.boolean().default(false),
},
output: [searchResultListItemDataRef],
dataRefs: {
+2 -1
View File
@@ -71,7 +71,8 @@
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.9.1",
"qs": "^6.9.4",
"react-use": "^17.2.4"
"react-use": "^17.2.4",
"zod": "^3.25.76 || ^4.0.0"
},
"devDependencies": {
"@backstage/cli": "workspace:^",
+14 -6
View File
@@ -47,8 +47,12 @@ const _default: OverridableFrontendPlugin<
'nav-item:search': OverridableExtensionDefinition<{
kind: 'nav-item';
name: undefined;
config: {};
configInput: {};
config: {
title: string | undefined;
};
configInput: {
title?: string | undefined;
};
output: ExtensionDataRef<
{
title: string;
@@ -73,8 +77,8 @@ const _default: OverridableFrontendPlugin<
};
configInput: {
noTrack?: boolean | undefined;
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
@@ -214,8 +218,12 @@ export const searchApi: OverridableExtensionDefinition<{
export const searchNavItem: OverridableExtensionDefinition<{
kind: 'nav-item';
name: undefined;
config: {};
configInput: {};
config: {
title: string | undefined;
};
configInput: {
title?: string | undefined;
};
output: ExtensionDataRef<
{
title: string;
@@ -242,8 +250,8 @@ export const searchPage: OverridableExtensionDefinition<{
};
configInput: {
noTrack?: boolean | undefined;
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
+3 -4
View File
@@ -18,6 +18,7 @@ import Grid from '@material-ui/core/Grid';
import Paper from '@material-ui/core/Paper';
import { makeStyles, Theme } from '@material-ui/core/styles';
import SearchIcon from '@material-ui/icons/Search';
import { z } from 'zod/v4';
import {
CatalogIcon,
@@ -93,10 +94,8 @@ const useSearchPageStyles = makeStyles((theme: Theme) => ({
/** @alpha */
export const searchPage = PageBlueprint.makeWithOverrides({
config: {
schema: {
noTrack: z => z.boolean().default(false),
},
configSchema: {
noTrack: z.boolean().default(false),
},
inputs: {
items: createExtensionInput([SearchResultListItemBlueprint.dataRefs.item]),
+2 -1
View File
@@ -86,7 +86,8 @@
"git-url-parse": "^15.0.0",
"lodash": "^4.17.21",
"react-helmet": "6.1.0",
"react-use": "^17.2.4"
"react-use": "^17.2.4",
"zod": "^3.25.76 || ^4.0.0"
},
"devDependencies": {
"@backstage/cli": "workspace:^",
+11 -7
View File
@@ -229,9 +229,9 @@ const _default: OverridableFrontendPlugin<
filter: FilterPredicate | undefined;
};
configInput: {
filter?: FilterPredicate | undefined;
label?: string | undefined;
title?: string | undefined;
filter?: FilterPredicate | undefined;
};
output:
| ExtensionDataRef<
@@ -262,8 +262,12 @@ const _default: OverridableFrontendPlugin<
'nav-item:techdocs': OverridableExtensionDefinition<{
kind: 'nav-item';
name: undefined;
config: {};
configInput: {};
config: {
title: string | undefined;
};
configInput: {
title?: string | undefined;
};
output: ExtensionDataRef<
{
title: string;
@@ -288,8 +292,8 @@ const _default: OverridableFrontendPlugin<
title: string | undefined;
};
configInput: {
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
@@ -366,8 +370,8 @@ const _default: OverridableFrontendPlugin<
configInput: {
withoutSearch?: boolean | undefined;
withoutHeader?: boolean | undefined;
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
@@ -470,8 +474,8 @@ const _default: OverridableFrontendPlugin<
configInput: {
title?: string | undefined;
lineClamp?: number | undefined;
asListItem?: boolean | undefined;
asLink?: boolean | undefined;
asListItem?: boolean | undefined;
noTrack?: boolean | undefined;
};
output: ExtensionDataRef<
@@ -504,8 +508,8 @@ export const techDocsSearchResultListItemExtension: OverridableExtensionDefiniti
configInput: {
title?: string | undefined;
lineClamp?: number | undefined;
asListItem?: boolean | undefined;
asLink?: boolean | undefined;
asListItem?: boolean | undefined;
noTrack?: boolean | undefined;
};
output: ExtensionDataRef<
+9 -12
View File
@@ -15,6 +15,7 @@
*/
import { Suspense } from 'react';
import { z } from 'zod/v4';
import { RiArticleLine } from '@remixicon/react';
import {
createFrontendPlugin,
@@ -107,13 +108,11 @@ const techDocsClientApi = ApiBlueprint.make({
/** @alpha */
export const techDocsSearchResultListItemExtension =
SearchResultListItemBlueprint.makeWithOverrides({
config: {
schema: {
title: z => z.string().optional(),
lineClamp: z => z.number().default(5),
asLink: z => z.boolean().default(true),
asListItem: z => z.boolean().default(true),
},
configSchema: {
title: z.string().optional(),
lineClamp: z.number().default(5),
asLink: z.boolean().default(true),
asListItem: z.boolean().default(true),
},
factory(originalFactory, { config }) {
return originalFactory({
@@ -157,11 +156,9 @@ const techDocsReaderPage = PageBlueprint.makeWithOverrides({
inputs: {
addons: createExtensionInput([AddonBlueprint.dataRefs.addon]),
},
config: {
schema: {
withoutSearch: z => z.boolean().default(false),
withoutHeader: z => z.boolean().default(false),
},
configSchema: {
withoutSearch: z.boolean().default(false),
withoutHeader: z.boolean().default(false),
},
factory(originalFactory, { apis, inputs, config }) {
const addonsApi = apis.get(techdocsAddonsApiRef);
+16 -8
View File
@@ -26,8 +26,12 @@ const _default: OverridableFrontendPlugin<
'nav-item:user-settings': OverridableExtensionDefinition<{
kind: 'nav-item';
name: undefined;
config: {};
configInput: {};
config: {
title: string | undefined;
};
configInput: {
title?: string | undefined;
};
output: ExtensionDataRef<
{
title: string;
@@ -52,8 +56,8 @@ const _default: OverridableFrontendPlugin<
title: string | undefined;
};
configInput: {
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
@@ -126,8 +130,8 @@ const _default: OverridableFrontendPlugin<
title: string | undefined;
};
configInput: {
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
@@ -175,8 +179,8 @@ const _default: OverridableFrontendPlugin<
title: string | undefined;
};
configInput: {
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
@@ -213,8 +217,8 @@ const _default: OverridableFrontendPlugin<
title: string | undefined;
};
configInput: {
title?: string | undefined;
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
@@ -251,8 +255,12 @@ export default _default;
export const settingsNavItem: OverridableExtensionDefinition<{
kind: 'nav-item';
name: undefined;
config: {};
configInput: {};
config: {
title: string | undefined;
};
configInput: {
title?: string | undefined;
};
output: ExtensionDataRef<
{
title: string;
+6
View File
@@ -5270,6 +5270,7 @@ __metadata:
react-dom: "npm:^18.0.2"
react-router-dom: "npm:^6.30.2"
react-use: "npm:^17.2.4"
zod: "npm:^3.25.76 || ^4.0.0"
peerDependencies:
"@types/react": ^17.0.0 || ^18.0.0
react: ^17.0.0 || ^18.0.0
@@ -5517,6 +5518,7 @@ __metadata:
react-use: "npm:^17.2.4"
swr: "npm:^2.2.5"
zen-observable: "npm:^0.10.0"
zod: "npm:^3.25.76 || ^4.0.0"
peerDependencies:
"@types/react": ^17.0.0 || ^18.0.0
react: ^17.0.0 || ^18.0.0
@@ -6429,6 +6431,7 @@ __metadata:
react-dom: "npm:^18.0.2"
react-router-dom: "npm:^6.30.2"
react-use: "npm:^17.2.4"
zod: "npm:^3.25.76 || ^4.0.0"
peerDependencies:
"@types/react": ^17.0.0 || ^18.0.0
react: ^17.0.0 || ^18.0.0
@@ -7342,6 +7345,7 @@ __metadata:
react-router-dom: "npm:^6.30.2"
react-use: "npm:^17.3.2"
uuid: "npm:^11.0.2"
zod: "npm:^3.25.76 || ^4.0.0"
peerDependencies:
"@types/react": ^17.0.0 || ^18.0.0
react: ^17.0.0 || ^18.0.0
@@ -7384,6 +7388,7 @@ __metadata:
react-dom: "npm:^18.0.2"
react-router-dom: "npm:^6.30.2"
react-use: "npm:^17.2.4"
zod: "npm:^3.25.76 || ^4.0.0"
peerDependencies:
"@types/react": ^17.0.0 || ^18.0.0
react: ^17.0.0 || ^18.0.0
@@ -7735,6 +7740,7 @@ __metadata:
react-helmet: "npm:6.1.0"
react-router-dom: "npm:^6.30.2"
react-use: "npm:^17.2.4"
zod: "npm:^3.25.76 || ^4.0.0"
peerDependencies:
"@types/react": ^17.0.0 || ^18.0.0
react: ^17.0.0 || ^18.0.0