Merge pull request #33930 from backstage/remove-portable-schema-deprecated-prop
frontend-plugin-api: remove deprecated PortableSchema .schema property
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/frontend-plugin-api': minor
|
||||
---
|
||||
|
||||
**BREAKING**: Removed the deprecated property form of `PortableSchema.schema`. The `schema` member is now a plain method that must be called as `schema()` — direct property access like `schema.type` or `schema.properties` is no longer supported.
|
||||
@@ -821,11 +821,8 @@ export type PluginWrapperDefinition<TValue = unknown | never> = {
|
||||
// @public (undocumented)
|
||||
export type PortableSchema<TOutput = unknown, TInput = TOutput> = {
|
||||
parse: (input: TInput) => TOutput;
|
||||
schema: {
|
||||
(): {
|
||||
schema: JsonObject;
|
||||
};
|
||||
[key: string]: any;
|
||||
schema: () => {
|
||||
schema: JsonObject;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -2409,11 +2409,8 @@ export type PluginWrapperDefinition<TValue = unknown | never> = {
|
||||
// @public (undocumented)
|
||||
export type PortableSchema<TOutput = unknown, TInput = TOutput> = {
|
||||
parse: (input: TInput) => TOutput;
|
||||
schema: {
|
||||
(): {
|
||||
schema: JsonObject;
|
||||
};
|
||||
[key: string]: any;
|
||||
schema: () => {
|
||||
schema: JsonObject;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -182,14 +182,8 @@ describe('ApiBlueprint', () => {
|
||||
"input": "apis",
|
||||
},
|
||||
"configSchema": {
|
||||
"_fields": {
|
||||
"test": {
|
||||
"required": false,
|
||||
"toJsonSchema": [Function],
|
||||
"validate": [Function],
|
||||
},
|
||||
},
|
||||
"parse": [Function],
|
||||
"schema": [Function],
|
||||
},
|
||||
"disabled": false,
|
||||
"factory": [Function],
|
||||
|
||||
@@ -39,14 +39,8 @@ describe('NavItemBlueprint', () => {
|
||||
"input": "items",
|
||||
},
|
||||
"configSchema": {
|
||||
"_fields": {
|
||||
"title": {
|
||||
"required": false,
|
||||
"toJsonSchema": [Function],
|
||||
"validate": [Function],
|
||||
},
|
||||
},
|
||||
"parse": [Function],
|
||||
"schema": [Function],
|
||||
},
|
||||
"disabled": false,
|
||||
"factory": [Function],
|
||||
|
||||
@@ -48,19 +48,8 @@ describe('PageBlueprint', () => {
|
||||
"input": "routes",
|
||||
},
|
||||
"configSchema": {
|
||||
"_fields": {
|
||||
"path": {
|
||||
"required": false,
|
||||
"toJsonSchema": [Function],
|
||||
"validate": [Function],
|
||||
},
|
||||
"title": {
|
||||
"required": false,
|
||||
"toJsonSchema": [Function],
|
||||
"validate": [Function],
|
||||
},
|
||||
},
|
||||
"parse": [Function],
|
||||
"schema": [Function],
|
||||
},
|
||||
"disabled": false,
|
||||
"factory": [Function],
|
||||
|
||||
@@ -143,13 +143,14 @@ describe('createConfigSchema', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should support backward-compatible property access on schema', () => {
|
||||
it('should return the schema as a method', () => {
|
||||
const schema = createConfigSchema({
|
||||
title: zodV4.string(),
|
||||
});
|
||||
|
||||
expect(schema.schema.type).toBe('object');
|
||||
expect(schema.schema.properties).toBeDefined();
|
||||
const result = schema.schema();
|
||||
expect(result.schema.type).toBe('object');
|
||||
expect(result.schema.properties).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -143,27 +143,20 @@ function buildPortableSchema<TOutput = unknown>(
|
||||
return result as TOutput;
|
||||
}
|
||||
|
||||
let cached: { schema: JsonObject } | undefined;
|
||||
|
||||
const result: MergeablePortableSchema<TOutput> = {
|
||||
parse,
|
||||
schema: undefined as any,
|
||||
_fields: fields,
|
||||
};
|
||||
|
||||
// Lazy getter — computes JSON Schema on first access, then caches it.
|
||||
let cached: PortableSchema['schema'] | undefined;
|
||||
Object.defineProperty(result, 'schema', {
|
||||
get() {
|
||||
schema() {
|
||||
if (!cached) {
|
||||
const jsonSchema = buildObjectJsonSchema(fields);
|
||||
const callable = Object.assign(
|
||||
() => ({ schema: jsonSchema }),
|
||||
jsonSchema,
|
||||
);
|
||||
cached = callable as PortableSchema['schema'];
|
||||
cached = { schema: buildObjectJsonSchema(fields) };
|
||||
}
|
||||
return cached;
|
||||
},
|
||||
configurable: true,
|
||||
} as MergeablePortableSchema<TOutput>;
|
||||
|
||||
Object.defineProperty(result, '_fields', {
|
||||
value: fields,
|
||||
enumerable: false,
|
||||
});
|
||||
|
||||
|
||||
@@ -19,14 +19,5 @@ import { JsonObject } from '@backstage/types';
|
||||
/** @public */
|
||||
export type PortableSchema<TOutput = unknown, TInput = TOutput> = {
|
||||
parse: (input: TInput) => TOutput;
|
||||
/**
|
||||
* The JSON Schema for this portable schema.
|
||||
*
|
||||
* @remarks
|
||||
* Can be accessed as a property for backward compatibility (returns the
|
||||
* JSON Schema object directly), or called as a method which returns
|
||||
* `{ schema: JsonObject }`. Both forms compute the schema lazily on
|
||||
* first access. The property form is deprecated — prefer `schema()`.
|
||||
*/
|
||||
schema: { (): { schema: JsonObject }; [key: string]: any };
|
||||
schema: () => { schema: JsonObject };
|
||||
};
|
||||
|
||||
@@ -45,19 +45,8 @@ describe('EntityCardBlueprint', () => {
|
||||
"input": "cards",
|
||||
},
|
||||
"configSchema": {
|
||||
"_fields": {
|
||||
"filter": {
|
||||
"required": false,
|
||||
"toJsonSchema": [Function],
|
||||
"validate": [Function],
|
||||
},
|
||||
"type": {
|
||||
"required": false,
|
||||
"toJsonSchema": [Function],
|
||||
"validate": [Function],
|
||||
},
|
||||
},
|
||||
"parse": [Function],
|
||||
"schema": [Function],
|
||||
},
|
||||
"disabled": false,
|
||||
"factory": [Function],
|
||||
|
||||
@@ -47,34 +47,8 @@ describe('EntityContentBlueprint', () => {
|
||||
"input": "contents",
|
||||
},
|
||||
"configSchema": {
|
||||
"_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],
|
||||
},
|
||||
},
|
||||
"parse": [Function],
|
||||
"schema": [Function],
|
||||
},
|
||||
"disabled": false,
|
||||
"factory": [Function],
|
||||
|
||||
@@ -63,14 +63,8 @@ describe('EntityContextMenuItemBlueprint', () => {
|
||||
"input": "contextMenuItems",
|
||||
},
|
||||
"configSchema": {
|
||||
"_fields": {
|
||||
"filter": {
|
||||
"required": false,
|
||||
"toJsonSchema": [Function],
|
||||
"validate": [Function],
|
||||
},
|
||||
},
|
||||
"parse": [Function],
|
||||
"schema": [Function],
|
||||
},
|
||||
"disabled": false,
|
||||
"factory": [Function],
|
||||
|
||||
@@ -45,14 +45,8 @@ describe('SearchResultListItemBlueprint', () => {
|
||||
"input": "items",
|
||||
},
|
||||
"configSchema": {
|
||||
"_fields": {
|
||||
"noTrack": {
|
||||
"required": false,
|
||||
"toJsonSchema": [Function],
|
||||
"validate": [Function],
|
||||
},
|
||||
},
|
||||
"parse": [Function],
|
||||
"schema": [Function],
|
||||
},
|
||||
"disabled": false,
|
||||
"factory": [Function],
|
||||
|
||||
Reference in New Issue
Block a user