From 2d89e198bd809ceccc9db716c9c0386b0b67df85 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 10 Apr 2026 11:18:03 +0200 Subject: [PATCH] frontend-plugin-api: remove deprecated `createSchemaFromZod` The helper is no longer used internally and has been replaced by the `configSchema` option with direct Standard Schema values. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .../fix-zod-generic-frontend-plugin-api.md | 4 +- .../src/schema/createSchemaFromZod.test.ts | 43 ----------- .../src/schema/createSchemaFromZod.ts | 74 ------------------- plugins/api-docs/report-alpha.api.md | 8 +- plugins/catalog-react/report-alpha.api.md | 4 +- plugins/catalog/report-alpha.api.md | 4 +- plugins/kubernetes/report-alpha.api.md | 4 +- plugins/techdocs/report-alpha.api.md | 4 +- 8 files changed, 14 insertions(+), 131 deletions(-) delete mode 100644 packages/frontend-plugin-api/src/schema/createSchemaFromZod.test.ts delete mode 100644 packages/frontend-plugin-api/src/schema/createSchemaFromZod.ts diff --git a/.changeset/fix-zod-generic-frontend-plugin-api.md b/.changeset/fix-zod-generic-frontend-plugin-api.md index 8950ed70c9..e07a32322a 100644 --- a/.changeset/fix-zod-generic-frontend-plugin-api.md +++ b/.changeset/fix-zod-generic-frontend-plugin-api.md @@ -1,5 +1,5 @@ --- -'@backstage/frontend-plugin-api': patch +'@backstage/frontend-plugin-api': minor --- -Refactored the internal `createSchemaFromZod` helper to use a schema-first generic pattern, replacing the `ZodSchema` constraint with `TSchema extends ZodType`. This avoids "excessively deep" type inference errors when multiple Zod copies are resolved. +**BREAKING**: Removed the deprecated `createSchemaFromZod` helper. Use the `configSchema` option with Standard Schema values instead, for example `configSchema: { title: z.string() }` using zod v3.25+ or v4. diff --git a/packages/frontend-plugin-api/src/schema/createSchemaFromZod.test.ts b/packages/frontend-plugin-api/src/schema/createSchemaFromZod.test.ts deleted file mode 100644 index 477a1a58c6..0000000000 --- a/packages/frontend-plugin-api/src/schema/createSchemaFromZod.test.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2023 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { createSchemaFromZod } from './createSchemaFromZod'; - -describe('createSchemaFromZod', () => { - it('should provide nice parse errors', () => { - const { parse } = createSchemaFromZod(z => - z.object({ - foo: z.union([z.string(), z.number()]), - derp: z.object({ bar: z.number() }), - }), - ); - - expect(() => { - // @ts-expect-error - return parse({ derp: { bar: 'derp' } }); - }).toThrow( - `Missing required value at 'foo'; Expected number, received string at 'derp.bar'`, - ); - expect(() => { - // @ts-expect-error - return parse(undefined); - }).toThrow(`Missing required value`); - expect(() => { - // @ts-expect-error - return parse('derp'); - }).toThrow(`Expected object, received string`); - }); -}); diff --git a/packages/frontend-plugin-api/src/schema/createSchemaFromZod.ts b/packages/frontend-plugin-api/src/schema/createSchemaFromZod.ts deleted file mode 100644 index f71b875976..0000000000 --- a/packages/frontend-plugin-api/src/schema/createSchemaFromZod.ts +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2023 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { JsonObject } from '@backstage/types'; -import { z, type ZodIssue, type ZodType } from 'zod/v3'; -import zodToJsonSchema from 'zod-to-json-schema'; -import { PortableSchema } from './types'; - -/** - * @internal - * @deprecated Use {@link createConfigSchema} instead. - */ -export function createSchemaFromZod( - schemaCreator: (zImpl: typeof z) => TSchema, -): PortableSchema, z.input> { - const schema = schemaCreator(z); - - let cached: PortableSchema['schema'] | undefined; - - const result: PortableSchema, z.input> = { - parse: input => { - const parseResult = schema.safeParse(input); - if (parseResult.success) { - return parseResult.data; - } - throw new Error(parseResult.error.issues.map(formatIssue).join('; ')); - }, - schema: undefined as any, - }; - - Object.defineProperty(result, 'schema', { - get() { - if (!cached) { - const jsonSchema = zodToJsonSchema(schema) as JsonObject; - cached = Object.assign( - () => ({ schema: jsonSchema }), - jsonSchema, - ) as PortableSchema['schema']; - } - return cached; - }, - configurable: true, - enumerable: true, - }); - - return result; -} - -function formatIssue(issue: ZodIssue): string { - if (issue.code === 'invalid_union') { - return formatIssue(issue.unionErrors[0].issues[0]); - } - let message = issue.message; - if (message === 'Required') { - message = `Missing required value`; - } - if (issue.path.length) { - message += ` at '${issue.path.join('.')}'`; - } - return message; -} diff --git a/plugins/api-docs/report-alpha.api.md b/plugins/api-docs/report-alpha.api.md index 3a96dd015f..22f0b5ee1c 100644 --- a/plugins/api-docs/report-alpha.api.md +++ b/plugins/api-docs/report-alpha.api.md @@ -343,9 +343,9 @@ const _default: OverridableFrontendPlugin< icon: string | undefined; }; configInput: { - filter?: FilterPredicate | undefined; - title?: string | undefined; path?: string | undefined; + title?: string | undefined; + filter?: FilterPredicate | undefined; group?: string | false | undefined; icon?: string | undefined; }; @@ -413,9 +413,9 @@ const _default: OverridableFrontendPlugin< icon: string | undefined; }; configInput: { - filter?: FilterPredicate | undefined; - title?: string | undefined; path?: string | undefined; + title?: string | undefined; + filter?: FilterPredicate | undefined; group?: string | false | undefined; icon?: string | undefined; }; diff --git a/plugins/catalog-react/report-alpha.api.md b/plugins/catalog-react/report-alpha.api.md index 0135fe7d64..a110177e57 100644 --- a/plugins/catalog-react/report-alpha.api.md +++ b/plugins/catalog-react/report-alpha.api.md @@ -334,9 +334,9 @@ export const EntityContentBlueprint: ExtensionBlueprint<{ icon: string | undefined; }; configInput: { - filter?: FilterPredicate | undefined; - title?: string | undefined; path?: string | undefined; + title?: string | undefined; + filter?: FilterPredicate | undefined; group?: string | false | undefined; icon?: string | undefined; }; diff --git a/plugins/catalog/report-alpha.api.md b/plugins/catalog/report-alpha.api.md index cac3bd8ff2..bb7349826b 100644 --- a/plugins/catalog/report-alpha.api.md +++ b/plugins/catalog/report-alpha.api.md @@ -808,9 +808,9 @@ const _default: OverridableFrontendPlugin< icon: string | undefined; }; configInput: { - filter?: FilterPredicate | undefined; - title?: string | undefined; path?: string | undefined; + title?: string | undefined; + filter?: FilterPredicate | undefined; group?: string | false | undefined; icon?: string | undefined; }; diff --git a/plugins/kubernetes/report-alpha.api.md b/plugins/kubernetes/report-alpha.api.md index 136385e686..62b41f7466 100644 --- a/plugins/kubernetes/report-alpha.api.md +++ b/plugins/kubernetes/report-alpha.api.md @@ -101,9 +101,9 @@ const _default: OverridableFrontendPlugin< icon: string | undefined; }; configInput: { - filter?: FilterPredicate | undefined; - title?: string | undefined; path?: string | undefined; + title?: string | undefined; + filter?: FilterPredicate | undefined; group?: string | false | undefined; icon?: string | undefined; }; diff --git a/plugins/techdocs/report-alpha.api.md b/plugins/techdocs/report-alpha.api.md index afa6ce8de0..0a8e50c8e1 100644 --- a/plugins/techdocs/report-alpha.api.md +++ b/plugins/techdocs/report-alpha.api.md @@ -132,9 +132,9 @@ const _default: OverridableFrontendPlugin< icon: string | undefined; }; configInput: { - filter?: FilterPredicate | undefined; - title?: string | undefined; path?: string | undefined; + title?: string | undefined; + filter?: FilterPredicate | undefined; group?: string | false | undefined; icon?: string | undefined; };