diff --git a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts index bbd8ceeec3..afdbb2e939 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts @@ -738,19 +738,15 @@ export function createExtensionBlueprint(options: any): any { if: args.if ?? options.if, inputs: { ...args.inputs, ...options.inputs }, output: (args.output ?? options.output) as ExtensionDataRef[], - config: - options.config || args.config - ? { - schema: { - ...options.config?.schema, - ...args.config?.schema, - }, - } - : undefined, configSchema: - options.configSchema || args.configSchema + options.configSchema || + args.configSchema || + options.config?.schema || + args.config?.schema ? { + ...options.config?.schema, ...options.configSchema, + ...args.config?.schema, ...args.configSchema, } : (undefined as any), diff --git a/plugins/app/src/extensions/AppLanguageApi.ts b/plugins/app/src/extensions/AppLanguageApi.ts index 80efa1d9e9..f9a512b483 100644 --- a/plugins/app/src/extensions/AppLanguageApi.ts +++ b/plugins/app/src/extensions/AppLanguageApi.ts @@ -18,14 +18,13 @@ 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'; export const AppLanguageApi = ApiBlueprint.makeWithOverrides({ name: 'app-language', - config: { - schema: { - defaultLanguage: z => z.string().optional(), - availableLanguages: z => z.array(z.string()).optional(), - }, + configSchema: { + defaultLanguage: z.string().optional(), + availableLanguages: z.array(z.string()).optional(), }, factory(originalFactory, { config }) { return originalFactory(defineParams => diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index 04b05330ff..acaa6ad1c8 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -86,7 +86,8 @@ "qs": "^6.9.4", "react-use": "^17.2.4", "yaml": "^2.0.0", - "zen-observable": "^0.10.0" + "zen-observable": "^0.10.0", + "zod": "^3.25.76 || ^4.0.0" }, "devDependencies": { "@backstage/cli": "workspace:^", @@ -104,8 +105,7 @@ "react": "^18.0.2", "react-dom": "^18.0.2", "react-router-dom": "^6.30.2", - "react-test-renderer": "^16.13.1", - "zod": "^3.25.76 || ^4.0.0" + "react-test-renderer": "^16.13.1" }, "peerDependencies": { "@backstage/frontend-test-utils": "workspace:^", diff --git a/plugins/catalog-react/src/alpha/blueprints/EntityCardBlueprint.test.tsx b/plugins/catalog-react/src/alpha/blueprints/EntityCardBlueprint.test.tsx index 491f3a2dba..0bf88b18c4 100644 --- a/plugins/catalog-react/src/alpha/blueprints/EntityCardBlueprint.test.tsx +++ b/plugins/catalog-react/src/alpha/blueprints/EntityCardBlueprint.test.tsx @@ -45,158 +45,20 @@ describe('EntityCardBlueprint', () => { "input": "cards", }, "configSchema": { - "parse": [Function], - "schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "filter": { - "anyOf": [ - { - "type": "string", - }, - { - "anyOf": [ - { - "anyOf": [ - { - "additionalProperties": { - "anyOf": [ - { - "type": [ - "string", - "number", - "boolean", - ], - }, - { - "additionalProperties": false, - "properties": { - "$exists": { - "type": "boolean", - }, - }, - "required": [ - "$exists", - ], - "type": "object", - }, - { - "additionalProperties": false, - "properties": { - "$in": { - "items": { - "$ref": "#/properties/filter/anyOf/1/anyOf/0/anyOf/0/additionalProperties/anyOf/0", - }, - "type": "array", - }, - }, - "required": [ - "$in", - ], - "type": "object", - }, - { - "additionalProperties": false, - "properties": { - "$contains": { - "$ref": "#/properties/filter/anyOf/1", - }, - }, - "required": [ - "$contains", - ], - "type": "object", - }, - { - "additionalProperties": false, - "properties": { - "$hasPrefix": { - "type": "string", - }, - }, - "required": [ - "$hasPrefix", - ], - "type": "object", - }, - ], - }, - "propertyNames": { - "pattern": "^(?!\\$).*$", - }, - "type": "object", - }, - { - "additionalProperties": { - "not": {}, - }, - "propertyNames": { - "pattern": "^\\$", - }, - "type": "object", - }, - ], - }, - { - "$ref": "#/properties/filter/anyOf/1/anyOf/0/anyOf/0/additionalProperties/anyOf/0", - }, - { - "additionalProperties": false, - "properties": { - "$all": { - "items": { - "$ref": "#/properties/filter/anyOf/1", - }, - "type": "array", - }, - }, - "required": [ - "$all", - ], - "type": "object", - }, - { - "additionalProperties": false, - "properties": { - "$any": { - "items": { - "$ref": "#/properties/filter/anyOf/1", - }, - "type": "array", - }, - }, - "required": [ - "$any", - ], - "type": "object", - }, - { - "additionalProperties": false, - "properties": { - "$not": { - "$ref": "#/properties/filter/anyOf/1", - }, - }, - "required": [ - "$not", - ], - "type": "object", - }, - ], - }, - ], - }, - "type": { - "enum": [ - "info", - "content", - ], - "type": "string", - }, + "_fields": { + "filter": { + "required": false, + "toJsonSchema": [Function], + "validate": [Function], + }, + "type": { + "required": false, + "toJsonSchema": [Function], + "validate": [Function], }, - "type": "object", }, + "parse": [Function], + "schema": [Function], }, "disabled": false, "factory": [Function], diff --git a/plugins/catalog-react/src/alpha/blueprints/EntityCardBlueprint.ts b/plugins/catalog-react/src/alpha/blueprints/EntityCardBlueprint.ts index 7717b6a1f9..949f34e48f 100644 --- a/plugins/catalog-react/src/alpha/blueprints/EntityCardBlueprint.ts +++ b/plugins/catalog-react/src/alpha/blueprints/EntityCardBlueprint.ts @@ -32,6 +32,7 @@ import { } from '@backstage/filter-predicates'; import { resolveEntityFilterData } from './resolveEntityFilterData'; import { Entity } from '@backstage/catalog-model'; +import { z } from 'zod/v3'; /** * @alpha @@ -51,12 +52,11 @@ export const EntityCardBlueprint = createExtensionBlueprint({ filterExpression: entityFilterExpressionDataRef, type: entityCardTypeDataRef, }, - config: { - schema: { - filter: z => - z.union([z.string(), createZodV3FilterPredicateSchema(z)]).optional(), - type: z => z.enum(entityCardTypes).optional(), - }, + configSchema: { + filter: z + .union([z.string(), createZodV3FilterPredicateSchema(z)]) + .optional(), + type: z.enum(entityCardTypes).optional(), }, *factory( { diff --git a/plugins/catalog-react/src/alpha/blueprints/EntityContentBlueprint.test.tsx b/plugins/catalog-react/src/alpha/blueprints/EntityContentBlueprint.test.tsx index 5bc1aba2c2..d0dff2a939 100644 --- a/plugins/catalog-react/src/alpha/blueprints/EntityContentBlueprint.test.tsx +++ b/plugins/catalog-react/src/alpha/blueprints/EntityContentBlueprint.test.tsx @@ -47,171 +47,35 @@ describe('EntityContentBlueprint', () => { "input": "contents", }, "configSchema": { - "parse": [Function], - "schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "filter": { - "anyOf": [ - { - "type": "string", - }, - { - "anyOf": [ - { - "anyOf": [ - { - "additionalProperties": { - "anyOf": [ - { - "type": [ - "string", - "number", - "boolean", - ], - }, - { - "additionalProperties": false, - "properties": { - "$exists": { - "type": "boolean", - }, - }, - "required": [ - "$exists", - ], - "type": "object", - }, - { - "additionalProperties": false, - "properties": { - "$in": { - "items": { - "$ref": "#/properties/filter/anyOf/1/anyOf/0/anyOf/0/additionalProperties/anyOf/0", - }, - "type": "array", - }, - }, - "required": [ - "$in", - ], - "type": "object", - }, - { - "additionalProperties": false, - "properties": { - "$contains": { - "$ref": "#/properties/filter/anyOf/1", - }, - }, - "required": [ - "$contains", - ], - "type": "object", - }, - { - "additionalProperties": false, - "properties": { - "$hasPrefix": { - "type": "string", - }, - }, - "required": [ - "$hasPrefix", - ], - "type": "object", - }, - ], - }, - "propertyNames": { - "pattern": "^(?!\\$).*$", - }, - "type": "object", - }, - { - "additionalProperties": { - "not": {}, - }, - "propertyNames": { - "pattern": "^\\$", - }, - "type": "object", - }, - ], - }, - { - "$ref": "#/properties/filter/anyOf/1/anyOf/0/anyOf/0/additionalProperties/anyOf/0", - }, - { - "additionalProperties": false, - "properties": { - "$all": { - "items": { - "$ref": "#/properties/filter/anyOf/1", - }, - "type": "array", - }, - }, - "required": [ - "$all", - ], - "type": "object", - }, - { - "additionalProperties": false, - "properties": { - "$any": { - "items": { - "$ref": "#/properties/filter/anyOf/1", - }, - "type": "array", - }, - }, - "required": [ - "$any", - ], - "type": "object", - }, - { - "additionalProperties": false, - "properties": { - "$not": { - "$ref": "#/properties/filter/anyOf/1", - }, - }, - "required": [ - "$not", - ], - "type": "object", - }, - ], - }, - ], - }, - "group": { - "anyOf": [ - { - "const": false, - "type": "boolean", - }, - { - "type": "string", - }, - ], - }, - "icon": { - "type": "string", - }, - "path": { - "type": "string", - }, - "title": { - "type": "string", - }, + "_fields": { + "filter": { + "required": false, + "toJsonSchema": [Function], + "validate": [Function], + }, + "group": { + "required": false, + "toJsonSchema": [Function], + "validate": [Function], + }, + "icon": { + "required": false, + "toJsonSchema": [Function], + "validate": [Function], + }, + "path": { + "required": false, + "toJsonSchema": [Function], + "validate": [Function], + }, + "title": { + "required": false, + "toJsonSchema": [Function], + "validate": [Function], }, - "type": "object", }, + "parse": [Function], + "schema": [Function], }, "disabled": false, "factory": [Function], diff --git a/plugins/catalog-react/src/alpha/blueprints/EntityContentBlueprint.ts b/plugins/catalog-react/src/alpha/blueprints/EntityContentBlueprint.ts index 65896c7833..d41f14ff21 100644 --- a/plugins/catalog-react/src/alpha/blueprints/EntityContentBlueprint.ts +++ b/plugins/catalog-react/src/alpha/blueprints/EntityContentBlueprint.ts @@ -35,6 +35,7 @@ import { import { resolveEntityFilterData } from './resolveEntityFilterData'; import { Entity } from '@backstage/catalog-model'; import { ReactElement } from 'react'; +import { z } from 'zod/v3'; /** * @alpha @@ -60,15 +61,14 @@ export const EntityContentBlueprint = createExtensionBlueprint({ group: entityContentGroupDataRef, icon: entityContentIconDataRef, }, - config: { - schema: { - path: z => z.string().optional(), - title: z => z.string().optional(), - filter: z => - z.union([z.string(), createZodV3FilterPredicateSchema(z)]).optional(), - group: z => z.literal(false).or(z.string()).optional(), - icon: z => z.string().optional(), - }, + configSchema: { + path: z.string().optional(), + title: z.string().optional(), + filter: z + .union([z.string(), createZodV3FilterPredicateSchema(z)]) + .optional(), + group: z.literal(false).or(z.string()).optional(), + icon: z.string().optional(), }, *factory( params: { diff --git a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx index 40f8915917..463bc7cf60 100644 --- a/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx +++ b/plugins/catalog-react/src/alpha/blueprints/EntityContextMenuItemBlueprint.test.tsx @@ -63,144 +63,15 @@ describe('EntityContextMenuItemBlueprint', () => { "input": "contextMenuItems", }, "configSchema": { - "parse": [Function], - "schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "filter": { - "anyOf": [ - { - "anyOf": [ - { - "additionalProperties": { - "anyOf": [ - { - "type": [ - "string", - "number", - "boolean", - ], - }, - { - "additionalProperties": false, - "properties": { - "$exists": { - "type": "boolean", - }, - }, - "required": [ - "$exists", - ], - "type": "object", - }, - { - "additionalProperties": false, - "properties": { - "$in": { - "items": { - "$ref": "#/properties/filter/anyOf/0/anyOf/0/additionalProperties/anyOf/0", - }, - "type": "array", - }, - }, - "required": [ - "$in", - ], - "type": "object", - }, - { - "additionalProperties": false, - "properties": { - "$contains": { - "$ref": "#/properties/filter", - }, - }, - "required": [ - "$contains", - ], - "type": "object", - }, - { - "additionalProperties": false, - "properties": { - "$hasPrefix": { - "type": "string", - }, - }, - "required": [ - "$hasPrefix", - ], - "type": "object", - }, - ], - }, - "propertyNames": { - "pattern": "^(?!\\$).*$", - }, - "type": "object", - }, - { - "additionalProperties": { - "not": {}, - }, - "propertyNames": { - "pattern": "^\\$", - }, - "type": "object", - }, - ], - }, - { - "$ref": "#/properties/filter/anyOf/0/anyOf/0/additionalProperties/anyOf/0", - }, - { - "additionalProperties": false, - "properties": { - "$all": { - "items": { - "$ref": "#/properties/filter", - }, - "type": "array", - }, - }, - "required": [ - "$all", - ], - "type": "object", - }, - { - "additionalProperties": false, - "properties": { - "$any": { - "items": { - "$ref": "#/properties/filter", - }, - "type": "array", - }, - }, - "required": [ - "$any", - ], - "type": "object", - }, - { - "additionalProperties": false, - "properties": { - "$not": { - "$ref": "#/properties/filter", - }, - }, - "required": [ - "$not", - ], - "type": "object", - }, - ], - }, + "_fields": { + "filter": { + "required": false, + "toJsonSchema": [Function], + "validate": [Function], }, - "type": "object", }, + "parse": [Function], + "schema": [Function], }, "disabled": false, "factory": [Function],