From cc459f73a8b4096ed509b3f8913d4a329fa054b9 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Mar 2026 11:09:17 +0100 Subject: [PATCH 01/13] frontend-plugin-api: convert ApiRef to an opaque type Convert the ApiRef type in the new frontend system to an opaque type with a $$type discriminator, matching the pattern used by route refs and extension data refs. Add a builder-pattern creation overload (createApiRef().with({ id })) alongside the existing direct-config form. Create OpaqueApiRef in frontend-internal for internal type validation. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .changeset/opaque-api-ref-type.md | 7 ++ .../src/apis/system/ApiRef.test.ts | 1 + .../src/wiring/createSpecializedApp.test.tsx | 45 +++++---- .../src/apis/OpaqueApiRef.ts | 28 ++++++ packages/frontend-internal/src/apis/index.ts | 17 ++++ packages/frontend-internal/src/index.ts | 1 + packages/frontend-plugin-api/report.api.md | 10 +- .../src/apis/system/ApiRef.test.ts | 17 +++- .../src/apis/system/ApiRef.ts | 99 +++++++++++++------ .../src/apis/system/types.ts | 5 +- 10 files changed, 174 insertions(+), 56 deletions(-) create mode 100644 .changeset/opaque-api-ref-type.md create mode 100644 packages/frontend-internal/src/apis/OpaqueApiRef.ts create mode 100644 packages/frontend-internal/src/apis/index.ts diff --git a/.changeset/opaque-api-ref-type.md b/.changeset/opaque-api-ref-type.md new file mode 100644 index 0000000000..b1d7caf063 --- /dev/null +++ b/.changeset/opaque-api-ref-type.md @@ -0,0 +1,7 @@ +--- +'@backstage/frontend-plugin-api': minor +--- + +**BREAKING**: The `ApiRef` type is now an opaque type with a `$$type` discriminator field and `readonly` properties. This means that `ApiRef` instances can no longer be created as plain object literals. Use `createApiRef` to create API references. + +Added a new builder pattern for creating API references: `createApiRef().with({ id: 'plugin.my.api' })`. The existing `createApiRef({ id: 'plugin.my.api' })` pattern continues to work. diff --git a/packages/core-plugin-api/src/apis/system/ApiRef.test.ts b/packages/core-plugin-api/src/apis/system/ApiRef.test.ts index dab872236f..994cde44c6 100644 --- a/packages/core-plugin-api/src/apis/system/ApiRef.test.ts +++ b/packages/core-plugin-api/src/apis/system/ApiRef.test.ts @@ -19,6 +19,7 @@ import { createApiRef } from './ApiRef'; describe('ApiRef', () => { it('should be created', () => { const ref = createApiRef({ id: 'abc' }); + expect(ref.$$type).toBe('@backstage/ApiRef'); expect(ref.id).toBe('abc'); expect(String(ref)).toBe('apiRef{abc}'); expect(() => ref.T).toThrow('tried to read ApiRef.T of apiRef{abc}'); diff --git a/packages/frontend-app-api/src/wiring/createSpecializedApp.test.tsx b/packages/frontend-app-api/src/wiring/createSpecializedApp.test.tsx index 51c31aca25..e07e83677b 100644 --- a/packages/frontend-app-api/src/wiring/createSpecializedApp.test.tsx +++ b/packages/frontend-app-api/src/wiring/createSpecializedApp.test.tsx @@ -166,10 +166,11 @@ describe('createSpecializedApp', () => { "factories": Map { "core.featureflags" => { "factory": { - "api": ApiRefImpl { - "config": { - "id": "core.featureflags", - }, + "api": { + "$$type": "@backstage/ApiRef", + "id": "core.featureflags", + "toString": [Function], + "version": "v1", }, "deps": {}, "factory": [Function], @@ -178,10 +179,11 @@ describe('createSpecializedApp', () => { }, "core.app-tree" => { "factory": { - "api": ApiRefImpl { - "config": { - "id": "core.app-tree", - }, + "api": { + "$$type": "@backstage/ApiRef", + "id": "core.app-tree", + "toString": [Function], + "version": "v1", }, "deps": {}, "factory": [Function], @@ -190,10 +192,11 @@ describe('createSpecializedApp', () => { }, "core.config" => { "factory": { - "api": ApiRefImpl { - "config": { - "id": "core.config", - }, + "api": { + "$$type": "@backstage/ApiRef", + "id": "core.config", + "toString": [Function], + "version": "v1", }, "deps": {}, "factory": [Function], @@ -202,10 +205,11 @@ describe('createSpecializedApp', () => { }, "core.route-resolution" => { "factory": { - "api": ApiRefImpl { - "config": { - "id": "core.route-resolution", - }, + "api": { + "$$type": "@backstage/ApiRef", + "id": "core.route-resolution", + "toString": [Function], + "version": "v1", }, "deps": {}, "factory": [Function], @@ -214,10 +218,11 @@ describe('createSpecializedApp', () => { }, "core.identity" => { "factory": { - "api": ApiRefImpl { - "config": { - "id": "core.identity", - }, + "api": { + "$$type": "@backstage/ApiRef", + "id": "core.identity", + "toString": [Function], + "version": "v1", }, "deps": {}, "factory": [Function], diff --git a/packages/frontend-internal/src/apis/OpaqueApiRef.ts b/packages/frontend-internal/src/apis/OpaqueApiRef.ts new file mode 100644 index 0000000000..5e054a4bc5 --- /dev/null +++ b/packages/frontend-internal/src/apis/OpaqueApiRef.ts @@ -0,0 +1,28 @@ +/* + * Copyright 2025 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 { ApiRef } from '@backstage/frontend-plugin-api'; +import { OpaqueType } from '@internal/opaque'; + +export const OpaqueApiRef = OpaqueType.create<{ + public: ApiRef; + versions: { + readonly version: 'v1'; + }; +}>({ + type: '@backstage/ApiRef', + versions: ['v1'], +}); diff --git a/packages/frontend-internal/src/apis/index.ts b/packages/frontend-internal/src/apis/index.ts new file mode 100644 index 0000000000..8476e86409 --- /dev/null +++ b/packages/frontend-internal/src/apis/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2025 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. + */ + +export { OpaqueApiRef } from './OpaqueApiRef'; diff --git a/packages/frontend-internal/src/index.ts b/packages/frontend-internal/src/index.ts index 38bfdc53f8..4bd0348345 100644 --- a/packages/frontend-internal/src/index.ts +++ b/packages/frontend-internal/src/index.ts @@ -14,5 +14,6 @@ * limitations under the License. */ +export * from './apis'; export * from './routing'; export * from './wiring'; diff --git a/packages/frontend-plugin-api/report.api.md b/packages/frontend-plugin-api/report.api.md index 768f26c0eb..bf71922386 100644 --- a/packages/frontend-plugin-api/report.api.md +++ b/packages/frontend-plugin-api/report.api.md @@ -188,8 +188,9 @@ export type ApiHolder = { // @public export type ApiRef = { - id: string; - T: T; + readonly $$type: '@backstage/ApiRef'; + readonly id: string; + readonly T: T; }; // @public @@ -418,6 +419,11 @@ export function createApiFactory( // @public export function createApiRef(config: ApiRefConfig): ApiRef; +// @public +export function createApiRef(): { + with(config: ApiRefConfig): ApiRef; +}; + // @public export function createExtension< UOutput extends ExtensionDataRef, diff --git a/packages/frontend-plugin-api/src/apis/system/ApiRef.test.ts b/packages/frontend-plugin-api/src/apis/system/ApiRef.test.ts index dab872236f..556fc3e477 100644 --- a/packages/frontend-plugin-api/src/apis/system/ApiRef.test.ts +++ b/packages/frontend-plugin-api/src/apis/system/ApiRef.test.ts @@ -17,8 +17,17 @@ import { createApiRef } from './ApiRef'; describe('ApiRef', () => { - it('should be created', () => { + it('should be created with config', () => { const ref = createApiRef({ id: 'abc' }); + expect(ref.$$type).toBe('@backstage/ApiRef'); + expect(ref.id).toBe('abc'); + expect(String(ref)).toBe('apiRef{abc}'); + expect(() => ref.T).toThrow('tried to read ApiRef.T of apiRef{abc}'); + }); + + it('should be created with builder pattern', () => { + const ref = createApiRef().with({ id: 'abc' }); + expect(ref.$$type).toBe('@backstage/ApiRef'); expect(ref.id).toBe('abc'); expect(String(ref)).toBe('apiRef{abc}'); expect(() => ref.T).toThrow('tried to read ApiRef.T of apiRef{abc}'); @@ -47,4 +56,10 @@ describe('ApiRef', () => { ); } }); + + it('should reject invalid ids with builder pattern', () => { + expect(() => createApiRef().with({ id: '123' })).toThrow( + `API id must only contain period separated lowercase alphanum tokens with dashes, got '123'`, + ); + }); }); diff --git a/packages/frontend-plugin-api/src/apis/system/ApiRef.ts b/packages/frontend-plugin-api/src/apis/system/ApiRef.ts index 0db3d89bd5..0dc181591c 100644 --- a/packages/frontend-plugin-api/src/apis/system/ApiRef.ts +++ b/packages/frontend-plugin-api/src/apis/system/ApiRef.ts @@ -25,48 +25,85 @@ export type ApiRefConfig = { id: string; }; -class ApiRefImpl implements ApiRef { - constructor(private readonly config: ApiRefConfig) { - const valid = config.id - .split('.') - .flatMap(part => part.split('-')) - .every(part => part.match(/^[a-z][a-z0-9]*$/)); - if (!valid) { - throw new Error( - `API id must only contain period separated lowercase alphanum tokens with dashes, got '${config.id}'`, - ); - } +function validateId(id: string): void { + const valid = id + .split('.') + .flatMap(part => part.split('-')) + .every(part => part.match(/^[a-z][a-z0-9]*$/)); + if (!valid) { + throw new Error( + `API id must only contain period separated lowercase alphanum tokens with dashes, got '${id}'`, + ); } +} - get id(): string { - return this.config.id; - } - - // Utility for getting type of an api, using `typeof apiRef.T` - get T(): T { - throw new Error(`tried to read ApiRef.T of ${this}`); - } - - toString() { - return `apiRef{${this.config.id}}`; - } +function makeApiRef(id: string): ApiRef { + const ref = { + $$type: '@backstage/ApiRef' as const, + version: 'v1', + id, + toString() { + return `apiRef{${id}}`; + }, + }; + Object.defineProperty(ref, 'T', { + get(): T { + throw new Error(`tried to read ApiRef.T of ${this}`); + }, + enumerable: false, + }); + return ref as unknown as ApiRef; } /** - * Creates a reference to an API. The provided `id` is a stable identifier for - * the API implementation. + * Creates a reference to an API. * * @remarks * - * The frontend system infers the owning plugin for an API from the `id`. The - * recommended pattern is `plugin..*` (for example, + * The `id` is a stable identifier for the API implementation. The frontend + * system infers the owning plugin for an API from the `id`. The recommended + * pattern is `plugin..*` (for example, * `plugin.catalog.entity-presentation`). This ensures that other plugins can't * mistakenly override your API implementation. * - * @param config - The descriptor of the API to reference. - * @returns An API reference. + * The recommended way to create an API reference is: + * + * ```ts + * const myApiRef = createApiRef().with({ id: 'plugin.my.api' }); + * ``` + * + * For backwards compatibility, you can also pass the config directly: + * + * ```ts + * const myApiRef = createApiRef({ id: 'plugin.my.api' }); + * ``` + * * @public */ -export function createApiRef(config: ApiRefConfig): ApiRef { - return new ApiRefImpl(config); +export function createApiRef(config: ApiRefConfig): ApiRef; +/** + * Creates a reference to an API. + * + * @remarks + * + * Returns a builder with a `.with()` method for providing the `id`. + * + * @public + */ +export function createApiRef(): { + with(config: ApiRefConfig): ApiRef; +}; +export function createApiRef( + config?: ApiRefConfig, +): ApiRef | { with(config: ApiRefConfig): ApiRef } { + if (config) { + validateId(config.id); + return makeApiRef(config.id); + } + return { + with(withConfig: ApiRefConfig): ApiRef { + validateId(withConfig.id); + return makeApiRef(withConfig.id); + }, + }; } diff --git a/packages/frontend-plugin-api/src/apis/system/types.ts b/packages/frontend-plugin-api/src/apis/system/types.ts index 96614c320c..570e9a4e25 100644 --- a/packages/frontend-plugin-api/src/apis/system/types.ts +++ b/packages/frontend-plugin-api/src/apis/system/types.ts @@ -20,8 +20,9 @@ * @public */ export type ApiRef = { - id: string; - T: T; + readonly $$type: '@backstage/ApiRef'; + readonly id: string; + readonly T: T; }; /** From d911b7281160a2bc3acd40282d84bb4a43822891 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Mar 2026 16:40:44 +0100 Subject: [PATCH 02/13] frontend-plugin-api: add explicit ApiRef plugin ownership Add the new frontend ApiRef builder form while preserving compatibility with existing refs, and let frontend apps resolve API ownership through an explicit pluginId when provided. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .changeset/api-ref-plugin-owner-app.md | 5 ++ .changeset/api-ref-plugin-owner-core.md | 5 ++ .changeset/opaque-api-ref-type.md | 8 +- packages/core-plugin-api/report.api.md | 4 +- .../core-plugin-api/src/apis/system/ApiRef.ts | 22 ++++- .../src/wiring/createSpecializedApp.test.tsx | 53 ++++++++++++ .../src/wiring/createSpecializedApp.tsx | 9 +- .../src/apis/OpaqueApiRef.ts | 28 ------- packages/frontend-internal/src/apis/index.ts | 17 ---- packages/frontend-internal/src/index.ts | 1 - .../frontend-plugin-api/report-alpha.api.md | 4 +- packages/frontend-plugin-api/report.api.md | 38 ++++++--- .../src/apis/definitions/AlertApi.ts | 3 +- .../src/apis/definitions/AnalyticsApi.ts | 8 +- .../src/apis/definitions/AppLanguageApi.ts | 8 +- .../src/apis/definitions/AppThemeApi.ts | 8 +- .../src/apis/definitions/AppTreeApi.ts | 5 +- .../src/apis/definitions/ConfigApi.ts | 3 +- .../src/apis/definitions/DialogApi.ts | 3 +- .../src/apis/definitions/DiscoveryApi.ts | 8 +- .../src/apis/definitions/ErrorApi.ts | 3 +- .../src/apis/definitions/FeatureFlagsApi.ts | 8 +- .../src/apis/definitions/FetchApi.ts | 3 +- .../src/apis/definitions/IconsApi.ts | 3 +- .../src/apis/definitions/IdentityApi.ts | 8 +- .../src/apis/definitions/OAuthRequestApi.ts | 8 +- .../definitions/PluginHeaderActionsApi.ts | 8 +- .../src/apis/definitions/PluginWrapperApi.ts | 3 +- .../apis/definitions/RouteResolutionApi.ts | 3 +- .../src/apis/definitions/StorageApi.ts | 8 +- .../definitions/SwappableComponentsApi.ts | 8 +- .../src/apis/definitions/TranslationApi.ts | 8 +- .../src/apis/definitions/auth.ts | 84 ++++++++++++++++--- .../src/apis/system/ApiRef.test.ts | 3 +- .../src/apis/system/ApiRef.ts | 79 ++++++++++++----- .../src/apis/system/types.ts | 3 +- .../src/apis/system/useApi.test.tsx | 6 +- .../src/blueprints/ApiBlueprint.test.ts | 8 +- plugins/scaffolder-react/report-alpha.api.md | 4 +- plugins/scaffolder-react/report.api.md | 4 +- plugins/scaffolder/report-alpha.api.md | 4 +- plugins/scaffolder/report.api.md | 4 +- 42 files changed, 355 insertions(+), 155 deletions(-) create mode 100644 .changeset/api-ref-plugin-owner-app.md create mode 100644 .changeset/api-ref-plugin-owner-core.md delete mode 100644 packages/frontend-internal/src/apis/OpaqueApiRef.ts delete mode 100644 packages/frontend-internal/src/apis/index.ts diff --git a/.changeset/api-ref-plugin-owner-app.md b/.changeset/api-ref-plugin-owner-app.md new file mode 100644 index 0000000000..e9727a3255 --- /dev/null +++ b/.changeset/api-ref-plugin-owner-app.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': patch +--- + +Frontend apps now respect an explicit `pluginId` on `ApiRef`s when deciding which plugin owns an API factory. diff --git a/.changeset/api-ref-plugin-owner-core.md b/.changeset/api-ref-plugin-owner-core.md new file mode 100644 index 0000000000..005dc06424 --- /dev/null +++ b/.changeset/api-ref-plugin-owner-core.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-plugin-api': patch +--- + +Updated `createApiRef` to preserve the direct config call without deprecation warnings while staying compatible with the new frontend API ref typing. diff --git a/.changeset/opaque-api-ref-type.md b/.changeset/opaque-api-ref-type.md index b1d7caf063..7397982cf6 100644 --- a/.changeset/opaque-api-ref-type.md +++ b/.changeset/opaque-api-ref-type.md @@ -1,7 +1,5 @@ ---- -'@backstage/frontend-plugin-api': minor ---- +## '@backstage/frontend-plugin-api': patch -**BREAKING**: The `ApiRef` type is now an opaque type with a `$$type` discriminator field and `readonly` properties. This means that `ApiRef` instances can no longer be created as plain object literals. Use `createApiRef` to create API references. +Added a builder form for `createApiRef` in the new frontend system and deprecated the direct `createApiRef({ ... })` call in favor of `createApiRef().with({ ... })`. -Added a new builder pattern for creating API references: `createApiRef().with({ id: 'plugin.my.api' })`. The existing `createApiRef({ id: 'plugin.my.api' })` pattern continues to work. +`ApiRef` and `ApiRefConfig` now also support an explicit `pluginId`, making it possible to declare API ownership without encoding the plugin ID into the API ref ID. diff --git a/packages/core-plugin-api/report.api.md b/packages/core-plugin-api/report.api.md index 654bbe94d1..7165cfc697 100644 --- a/packages/core-plugin-api/report.api.md +++ b/packages/core-plugin-api/report.api.md @@ -28,7 +28,6 @@ import { ComponentType } from 'react'; import { ConfigApi } from '@backstage/frontend-plugin-api'; import { configApiRef } from '@backstage/frontend-plugin-api'; import { createApiFactory } from '@backstage/frontend-plugin-api'; -import { createApiRef } from '@backstage/frontend-plugin-api'; import { DiscoveryApi } from '@backstage/frontend-plugin-api'; import { discoveryApiRef } from '@backstage/frontend-plugin-api'; import { ErrorApi } from '@backstage/frontend-plugin-api'; @@ -256,7 +255,8 @@ export { configApiRef }; export { createApiFactory }; -export { createApiRef }; +// @public +export function createApiRef(config: ApiRefConfig): ApiRef; // @public export function createComponentExtension< diff --git a/packages/core-plugin-api/src/apis/system/ApiRef.ts b/packages/core-plugin-api/src/apis/system/ApiRef.ts index ffd074b9a7..8c3986c583 100644 --- a/packages/core-plugin-api/src/apis/system/ApiRef.ts +++ b/packages/core-plugin-api/src/apis/system/ApiRef.ts @@ -14,5 +14,23 @@ * limitations under the License. */ -export { createApiRef } from '@backstage/frontend-plugin-api'; -export type { ApiRefConfig } from '@backstage/frontend-plugin-api'; +import { + createApiRef as createFrontendApiRef, + type ApiRef, + type ApiRefConfig, +} from '@backstage/frontend-plugin-api'; + +const createFrontendApiRefCompat = createFrontendApiRef as ( + config: ApiRefConfig, +) => ApiRef; + +/** + * Creates a reference to an API. + * + * @public + */ +export function createApiRef(config: ApiRefConfig): ApiRef { + return createFrontendApiRefCompat(config); +} + +export type { ApiRefConfig }; diff --git a/packages/frontend-app-api/src/wiring/createSpecializedApp.test.tsx b/packages/frontend-app-api/src/wiring/createSpecializedApp.test.tsx index e07e83677b..d01bc4fe9c 100644 --- a/packages/frontend-app-api/src/wiring/createSpecializedApp.test.tsx +++ b/packages/frontend-app-api/src/wiring/createSpecializedApp.test.tsx @@ -169,6 +169,7 @@ describe('createSpecializedApp', () => { "api": { "$$type": "@backstage/ApiRef", "id": "core.featureflags", + "pluginId": "app", "toString": [Function], "version": "v1", }, @@ -182,6 +183,7 @@ describe('createSpecializedApp', () => { "api": { "$$type": "@backstage/ApiRef", "id": "core.app-tree", + "pluginId": "app", "toString": [Function], "version": "v1", }, @@ -195,6 +197,7 @@ describe('createSpecializedApp', () => { "api": { "$$type": "@backstage/ApiRef", "id": "core.config", + "pluginId": "app", "toString": [Function], "version": "v1", }, @@ -208,6 +211,7 @@ describe('createSpecializedApp', () => { "api": { "$$type": "@backstage/ApiRef", "id": "core.route-resolution", + "pluginId": "app", "toString": [Function], "version": "v1", }, @@ -221,6 +225,7 @@ describe('createSpecializedApp', () => { "api": { "$$type": "@backstage/ApiRef", "id": "core.identity", + "pluginId": "app", "toString": [Function], "version": "v1", }, @@ -364,6 +369,54 @@ describe('createSpecializedApp', () => { expect(app.apis.get(testApiRef)).toEqual({ value: 'owner' }); }); + it('should select the API factory from an explicitly owned plugin on conflict', () => { + const testApiRef = createApiRef<{ value: string }>().with({ + id: 'shared.api', + pluginId: 'owner', + }); + + const app = createSpecializedApp({ + features: [ + makeAppPlugin(), + createFrontendPlugin({ + pluginId: 'other-before', + extensions: [ + ApiBlueprint.make({ + params: defineParams => + defineParams({ + api: testApiRef, + deps: {}, + factory: () => ({ value: 'other' }), + }), + }), + ], + }), + createFrontendPlugin({ + pluginId: 'owner', + extensions: [ + ApiBlueprint.make({ + params: defineParams => + defineParams({ + api: testApiRef, + deps: {}, + factory: () => ({ value: 'owner' }), + }), + }), + ], + }), + ], + }); + + expect(app.errors).toEqual([ + expect.objectContaining({ + code: 'API_FACTORY_CONFLICT', + message: expect.stringContaining("API 'shared.api'"), + }), + ]); + + expect(app.apis.get(testApiRef)).toEqual({ value: 'owner' }); + }); + it('should allow API overrides within the same plugin', () => { const testApiRef = createApiRef<{ value: string }>({ id: 'test.api' }); diff --git a/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx b/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx index fda00b70b1..7ab36f2fad 100644 --- a/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx +++ b/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx @@ -401,7 +401,7 @@ function createApiFactories(options: { const apiFactory = apiNode.instance?.getData(ApiBlueprint.dataRefs.factory); if (apiFactory) { const apiRefId = apiFactory.api.id; - const ownerId = getApiOwnerId(apiRefId); + const ownerId = getApiOwnerId(apiFactory.api); const pluginId = apiNode.spec.plugin.pluginId ?? 'app'; const existingFactory = factoriesById.get(apiRefId); @@ -455,7 +455,12 @@ function createApiFactories(options: { // TODO(Rugvip): It would be good if this was more explicit, but I think that // might need to wait for some future update for API factories. -function getApiOwnerId(apiRefId: string): string { +function getApiOwnerId(apiRef: { id: string; pluginId?: string }): string { + if (apiRef.pluginId) { + return apiRef.pluginId; + } + + const apiRefId = apiRef.id; const [prefix, ...rest] = apiRefId.split('.'); if (!prefix) { return apiRefId; diff --git a/packages/frontend-internal/src/apis/OpaqueApiRef.ts b/packages/frontend-internal/src/apis/OpaqueApiRef.ts deleted file mode 100644 index 5e054a4bc5..0000000000 --- a/packages/frontend-internal/src/apis/OpaqueApiRef.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2025 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 { ApiRef } from '@backstage/frontend-plugin-api'; -import { OpaqueType } from '@internal/opaque'; - -export const OpaqueApiRef = OpaqueType.create<{ - public: ApiRef; - versions: { - readonly version: 'v1'; - }; -}>({ - type: '@backstage/ApiRef', - versions: ['v1'], -}); diff --git a/packages/frontend-internal/src/apis/index.ts b/packages/frontend-internal/src/apis/index.ts deleted file mode 100644 index 8476e86409..0000000000 --- a/packages/frontend-internal/src/apis/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2025 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. - */ - -export { OpaqueApiRef } from './OpaqueApiRef'; diff --git a/packages/frontend-internal/src/index.ts b/packages/frontend-internal/src/index.ts index 4bd0348345..38bfdc53f8 100644 --- a/packages/frontend-internal/src/index.ts +++ b/packages/frontend-internal/src/index.ts @@ -14,6 +14,5 @@ * limitations under the License. */ -export * from './apis'; export * from './routing'; export * from './wiring'; diff --git a/packages/frontend-plugin-api/report-alpha.api.md b/packages/frontend-plugin-api/report-alpha.api.md index 76678107ef..c1a3c71a21 100644 --- a/packages/frontend-plugin-api/report-alpha.api.md +++ b/packages/frontend-plugin-api/report-alpha.api.md @@ -24,7 +24,9 @@ export type PluginWrapperApi = { }; // @public -export const pluginWrapperApiRef: ApiRef; +export const pluginWrapperApiRef: ApiRef & { + readonly $$type: '@backstage/ApiRef'; +}; // @public export const PluginWrapperBlueprint: ExtensionBlueprint<{ diff --git a/packages/frontend-plugin-api/report.api.md b/packages/frontend-plugin-api/report.api.md index bf71922386..17b3ecc75d 100644 --- a/packages/frontend-plugin-api/report.api.md +++ b/packages/frontend-plugin-api/report.api.md @@ -188,14 +188,16 @@ export type ApiHolder = { // @public export type ApiRef = { - readonly $$type: '@backstage/ApiRef'; + readonly $$type?: '@backstage/ApiRef'; readonly id: string; + readonly pluginId?: string; readonly T: T; }; // @public export type ApiRefConfig = { id: string; + pluginId?: string; }; // @public (undocumented) @@ -306,7 +308,9 @@ export interface AppTreeApi { } // @public -export const appTreeApiRef: ApiRef_2; +export const appTreeApiRef: ApiRef_2 & { + readonly $$type: '@backstage/ApiRef'; +}; // @public export const atlassianAuthApiRef: ApiRef< @@ -416,12 +420,16 @@ export function createApiFactory( instance: Impl, ): ApiFactory; -// @public -export function createApiRef(config: ApiRefConfig): ApiRef; +// @public @deprecated +export function createApiRef(config: ApiRefConfig): ApiRef & { + readonly $$type: '@backstage/ApiRef'; +}; // @public export function createApiRef(): { - with(config: ApiRefConfig): ApiRef; + with(config: ApiRefConfig): ApiRef & { + readonly $$type: '@backstage/ApiRef'; + }; }; // @public @@ -875,7 +883,9 @@ export interface DialogApiDialog { } // @public -export const dialogApiRef: ApiRef_2; +export const dialogApiRef: ApiRef_2 & { + readonly $$type: '@backstage/ApiRef'; +}; // @public export type DiscoveryApi = { @@ -1436,7 +1446,9 @@ export interface IconsApi { } // @public -export const iconsApiRef: ApiRef_2; +export const iconsApiRef: ApiRef_2 & { + readonly $$type: '@backstage/ApiRef'; +}; // @public export type IdentityApi = { @@ -1851,7 +1863,9 @@ export type PluginHeaderActionsApi = { }; // @public -export const pluginHeaderActionsApiRef: ApiRef_2; +export const pluginHeaderActionsApiRef: ApiRef_2 & { + readonly $$type: '@backstage/ApiRef'; +}; // @public (undocumented) export interface PluginOptions< @@ -1999,7 +2013,9 @@ export interface RouteResolutionApi { } // @public -export const routeResolutionApiRef: ApiRef_2; +export const routeResolutionApiRef: ApiRef_2 & { + readonly $$type: '@backstage/ApiRef'; +}; // @public export type SessionApi = { @@ -2127,7 +2143,9 @@ export interface SwappableComponentsApi { } // @public -export const swappableComponentsApiRef: ApiRef_2; +export const swappableComponentsApiRef: ApiRef_2 & { + readonly $$type: '@backstage/ApiRef'; +}; // @public (undocumented) export type TranslationApi = { diff --git a/packages/frontend-plugin-api/src/apis/definitions/AlertApi.ts b/packages/frontend-plugin-api/src/apis/definitions/AlertApi.ts index afdcb6a617..09d979ad9a 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/AlertApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/AlertApi.ts @@ -51,6 +51,7 @@ export type AlertApi = { * * @public */ -export const alertApiRef: ApiRef = createApiRef({ +export const alertApiRef: ApiRef = createApiRef().with({ id: 'core.alert', + pluginId: 'app', }); diff --git a/packages/frontend-plugin-api/src/apis/definitions/AnalyticsApi.ts b/packages/frontend-plugin-api/src/apis/definitions/AnalyticsApi.ts index aa1f08ffbe..51acc1851d 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/AnalyticsApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/AnalyticsApi.ts @@ -151,6 +151,8 @@ export type AnalyticsApi = { * * @public */ -export const analyticsApiRef: ApiRef = createApiRef({ - id: 'core.analytics', -}); +export const analyticsApiRef: ApiRef = + createApiRef().with({ + id: 'core.analytics', + pluginId: 'app', + }); diff --git a/packages/frontend-plugin-api/src/apis/definitions/AppLanguageApi.ts b/packages/frontend-plugin-api/src/apis/definitions/AppLanguageApi.ts index 36b97f9fff..c4a1c8be73 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/AppLanguageApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/AppLanguageApi.ts @@ -31,6 +31,8 @@ export type AppLanguageApi = { /** * @public */ -export const appLanguageApiRef: ApiRef = createApiRef({ - id: 'core.applanguage', -}); +export const appLanguageApiRef: ApiRef = + createApiRef().with({ + id: 'core.applanguage', + pluginId: 'app', + }); diff --git a/packages/frontend-plugin-api/src/apis/definitions/AppThemeApi.ts b/packages/frontend-plugin-api/src/apis/definitions/AppThemeApi.ts index e771fad597..39561f5f96 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/AppThemeApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/AppThemeApi.ts @@ -82,6 +82,8 @@ export type AppThemeApi = { * * @public */ -export const appThemeApiRef: ApiRef = createApiRef({ - id: 'core.apptheme', -}); +export const appThemeApiRef: ApiRef = + createApiRef().with({ + id: 'core.apptheme', + pluginId: 'app', + }); diff --git a/packages/frontend-plugin-api/src/apis/definitions/AppTreeApi.ts b/packages/frontend-plugin-api/src/apis/definitions/AppTreeApi.ts index 89902d2727..16369680f2 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/AppTreeApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/AppTreeApi.ts @@ -117,4 +117,7 @@ export interface AppTreeApi { * * @public */ -export const appTreeApiRef = createApiRef({ id: 'core.app-tree' }); +export const appTreeApiRef = createApiRef().with({ + id: 'core.app-tree', + pluginId: 'app', +}); diff --git a/packages/frontend-plugin-api/src/apis/definitions/ConfigApi.ts b/packages/frontend-plugin-api/src/apis/definitions/ConfigApi.ts index f935dfa3af..eb52c1cbca 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/ConfigApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/ConfigApi.ts @@ -29,6 +29,7 @@ export type ConfigApi = Config; * * @public */ -export const configApiRef: ApiRef = createApiRef({ +export const configApiRef: ApiRef = createApiRef().with({ id: 'core.config', + pluginId: 'app', }); diff --git a/packages/frontend-plugin-api/src/apis/definitions/DialogApi.ts b/packages/frontend-plugin-api/src/apis/definitions/DialogApi.ts index d7ab2e5d75..bcb92f528a 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/DialogApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/DialogApi.ts @@ -173,6 +173,7 @@ export interface DialogApi { * * @public */ -export const dialogApiRef = createApiRef({ +export const dialogApiRef = createApiRef().with({ id: 'core.dialog', + pluginId: 'app', }); diff --git a/packages/frontend-plugin-api/src/apis/definitions/DiscoveryApi.ts b/packages/frontend-plugin-api/src/apis/definitions/DiscoveryApi.ts index d23fe3db6c..fb348c156d 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/DiscoveryApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/DiscoveryApi.ts @@ -50,6 +50,8 @@ export type DiscoveryApi = { * * @public */ -export const discoveryApiRef: ApiRef = createApiRef({ - id: 'core.discovery', -}); +export const discoveryApiRef: ApiRef = + createApiRef().with({ + id: 'core.discovery', + pluginId: 'app', + }); diff --git a/packages/frontend-plugin-api/src/apis/definitions/ErrorApi.ts b/packages/frontend-plugin-api/src/apis/definitions/ErrorApi.ts index 9c73d94cac..d106ccc05c 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/ErrorApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/ErrorApi.ts @@ -86,6 +86,7 @@ export type ErrorApi = { * * @public */ -export const errorApiRef: ApiRef = createApiRef({ +export const errorApiRef: ApiRef = createApiRef().with({ id: 'core.error', + pluginId: 'app', }); diff --git a/packages/frontend-plugin-api/src/apis/definitions/FeatureFlagsApi.ts b/packages/frontend-plugin-api/src/apis/definitions/FeatureFlagsApi.ts index d4429975cc..7206dd9900 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/FeatureFlagsApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/FeatureFlagsApi.ts @@ -121,6 +121,8 @@ export interface FeatureFlagsApi { * * @public */ -export const featureFlagsApiRef: ApiRef = createApiRef({ - id: 'core.featureflags', -}); +export const featureFlagsApiRef: ApiRef = + createApiRef().with({ + id: 'core.featureflags', + pluginId: 'app', + }); diff --git a/packages/frontend-plugin-api/src/apis/definitions/FetchApi.ts b/packages/frontend-plugin-api/src/apis/definitions/FetchApi.ts index aba0e53bb7..4e4909b7d4 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/FetchApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/FetchApi.ts @@ -46,6 +46,7 @@ export type FetchApi = { * * @public */ -export const fetchApiRef: ApiRef = createApiRef({ +export const fetchApiRef: ApiRef = createApiRef().with({ id: 'core.fetch', + pluginId: 'app', }); diff --git a/packages/frontend-plugin-api/src/apis/definitions/IconsApi.ts b/packages/frontend-plugin-api/src/apis/definitions/IconsApi.ts index d22ebcce4a..a54ae7f3b1 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/IconsApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/IconsApi.ts @@ -41,6 +41,7 @@ export interface IconsApi { * * @public */ -export const iconsApiRef = createApiRef({ +export const iconsApiRef = createApiRef().with({ id: 'core.icons', + pluginId: 'app', }); diff --git a/packages/frontend-plugin-api/src/apis/definitions/IdentityApi.ts b/packages/frontend-plugin-api/src/apis/definitions/IdentityApi.ts index 1b127a1971..dc23202c2e 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/IdentityApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/IdentityApi.ts @@ -51,6 +51,8 @@ export type IdentityApi = { * * @public */ -export const identityApiRef: ApiRef = createApiRef({ - id: 'core.identity', -}); +export const identityApiRef: ApiRef = + createApiRef().with({ + id: 'core.identity', + pluginId: 'app', + }); diff --git a/packages/frontend-plugin-api/src/apis/definitions/OAuthRequestApi.ts b/packages/frontend-plugin-api/src/apis/definitions/OAuthRequestApi.ts index 75bf3a3864..0c199948af 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/OAuthRequestApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/OAuthRequestApi.ts @@ -126,6 +126,8 @@ export type OAuthRequestApi = { * * @public */ -export const oauthRequestApiRef: ApiRef = createApiRef({ - id: 'core.oauthrequest', -}); +export const oauthRequestApiRef: ApiRef = + createApiRef().with({ + id: 'core.oauthrequest', + pluginId: 'app', + }); diff --git a/packages/frontend-plugin-api/src/apis/definitions/PluginHeaderActionsApi.ts b/packages/frontend-plugin-api/src/apis/definitions/PluginHeaderActionsApi.ts index 78d0e2623f..9e2d1ca0fd 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/PluginHeaderActionsApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/PluginHeaderActionsApi.ts @@ -40,6 +40,8 @@ export type PluginHeaderActionsApi = { * * @public */ -export const pluginHeaderActionsApiRef = createApiRef({ - id: 'core.plugin-header-actions', -}); +export const pluginHeaderActionsApiRef = + createApiRef().with({ + id: 'core.plugin-header-actions', + pluginId: 'app', + }); diff --git a/packages/frontend-plugin-api/src/apis/definitions/PluginWrapperApi.ts b/packages/frontend-plugin-api/src/apis/definitions/PluginWrapperApi.ts index 8d9b224b1f..7965b8ccb4 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/PluginWrapperApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/PluginWrapperApi.ts @@ -47,6 +47,7 @@ export type PluginWrapperApi = { * * @public */ -export const pluginWrapperApiRef = createApiRef({ +export const pluginWrapperApiRef = createApiRef().with({ id: 'core.plugin-wrapper', + pluginId: 'app', }); diff --git a/packages/frontend-plugin-api/src/apis/definitions/RouteResolutionApi.ts b/packages/frontend-plugin-api/src/apis/definitions/RouteResolutionApi.ts index 0c3ca9c4cf..9dea5d7bc2 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/RouteResolutionApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/RouteResolutionApi.ts @@ -65,6 +65,7 @@ export interface RouteResolutionApi { * * @public */ -export const routeResolutionApiRef = createApiRef({ +export const routeResolutionApiRef = createApiRef().with({ id: 'core.route-resolution', + pluginId: 'app', }); diff --git a/packages/frontend-plugin-api/src/apis/definitions/StorageApi.ts b/packages/frontend-plugin-api/src/apis/definitions/StorageApi.ts index 1506e5f143..7e8372b6fb 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/StorageApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/StorageApi.ts @@ -105,6 +105,8 @@ export interface StorageApi { * * @public */ -export const storageApiRef: ApiRef = createApiRef({ - id: 'core.storage', -}); +export const storageApiRef: ApiRef = + createApiRef().with({ + id: 'core.storage', + pluginId: 'app', + }); diff --git a/packages/frontend-plugin-api/src/apis/definitions/SwappableComponentsApi.ts b/packages/frontend-plugin-api/src/apis/definitions/SwappableComponentsApi.ts index 09dff04f43..47ffed91ef 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/SwappableComponentsApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/SwappableComponentsApi.ts @@ -36,6 +36,8 @@ export interface SwappableComponentsApi { * * @public */ -export const swappableComponentsApiRef = createApiRef({ - id: 'core.swappable-components', -}); +export const swappableComponentsApiRef = + createApiRef().with({ + id: 'core.swappable-components', + pluginId: 'app', + }); diff --git a/packages/frontend-plugin-api/src/apis/definitions/TranslationApi.ts b/packages/frontend-plugin-api/src/apis/definitions/TranslationApi.ts index b569800e3e..6997269484 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/TranslationApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/TranslationApi.ts @@ -358,6 +358,8 @@ export type TranslationApi = { /** * @public */ -export const translationApiRef: ApiRef = createApiRef({ - id: 'core.translation', -}); +export const translationApiRef: ApiRef = + createApiRef().with({ + id: 'core.translation', + pluginId: 'app', + }); diff --git a/packages/frontend-plugin-api/src/apis/definitions/auth.ts b/packages/frontend-plugin-api/src/apis/definitions/auth.ts index 76aa24e8f8..0c05047f24 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/auth.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/auth.ts @@ -28,7 +28,10 @@ import { Observable } from '@backstage/types'; * For example, a Google OAuth provider that supports OAuth 2 and OpenID Connect, * would be declared as follows: * - * const googleAuthApiRef = createApiRef({ ... }) + * const googleAuthApiRef = createApiRef().with({ + * id: 'core.auth.google', + * pluginId: 'app', + * }) */ /** @@ -339,8 +342,15 @@ export const googleAuthApiRef: ApiRef< ProfileInfoApi & BackstageIdentityApi & SessionApi -> = createApiRef({ +> = createApiRef< + OAuthApi & + OpenIdConnectApi & + ProfileInfoApi & + BackstageIdentityApi & + SessionApi +>().with({ id: 'core.auth.google', + pluginId: 'app', }); /** @@ -354,8 +364,11 @@ export const googleAuthApiRef: ApiRef< */ export const githubAuthApiRef: ApiRef< OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi -> = createApiRef({ +> = createApiRef< + OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi +>().with({ id: 'core.auth.github', + pluginId: 'app', }); /** @@ -373,8 +386,15 @@ export const oktaAuthApiRef: ApiRef< ProfileInfoApi & BackstageIdentityApi & SessionApi -> = createApiRef({ +> = createApiRef< + OAuthApi & + OpenIdConnectApi & + ProfileInfoApi & + BackstageIdentityApi & + SessionApi +>().with({ id: 'core.auth.okta', + pluginId: 'app', }); /** @@ -392,8 +412,15 @@ export const gitlabAuthApiRef: ApiRef< ProfileInfoApi & BackstageIdentityApi & SessionApi -> = createApiRef({ +> = createApiRef< + OAuthApi & + OpenIdConnectApi & + ProfileInfoApi & + BackstageIdentityApi & + SessionApi +>().with({ id: 'core.auth.gitlab', + pluginId: 'app', }); /** @@ -412,8 +439,15 @@ export const microsoftAuthApiRef: ApiRef< ProfileInfoApi & BackstageIdentityApi & SessionApi -> = createApiRef({ +> = createApiRef< + OAuthApi & + OpenIdConnectApi & + ProfileInfoApi & + BackstageIdentityApi & + SessionApi +>().with({ id: 'core.auth.microsoft', + pluginId: 'app', }); /** @@ -427,8 +461,15 @@ export const oneloginAuthApiRef: ApiRef< ProfileInfoApi & BackstageIdentityApi & SessionApi -> = createApiRef({ +> = createApiRef< + OAuthApi & + OpenIdConnectApi & + ProfileInfoApi & + BackstageIdentityApi & + SessionApi +>().with({ id: 'core.auth.onelogin', + pluginId: 'app', }); /** @@ -442,8 +483,11 @@ export const oneloginAuthApiRef: ApiRef< */ export const bitbucketAuthApiRef: ApiRef< OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi -> = createApiRef({ +> = createApiRef< + OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi +>().with({ id: 'core.auth.bitbucket', + pluginId: 'app', }); /** @@ -457,8 +501,11 @@ export const bitbucketAuthApiRef: ApiRef< */ export const bitbucketServerAuthApiRef: ApiRef< OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi -> = createApiRef({ +> = createApiRef< + OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi +>().with({ id: 'core.auth.bitbucket-server', + pluginId: 'app', }); /** @@ -472,8 +519,11 @@ export const bitbucketServerAuthApiRef: ApiRef< */ export const atlassianAuthApiRef: ApiRef< OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi -> = createApiRef({ +> = createApiRef< + OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi +>().with({ id: 'core.auth.atlassian', + pluginId: 'app', }); /** @@ -491,8 +541,15 @@ export const vmwareCloudAuthApiRef: ApiRef< ProfileInfoApi & BackstageIdentityApi & SessionApi -> = createApiRef({ +> = createApiRef< + OAuthApi & + OpenIdConnectApi & + ProfileInfoApi & + BackstageIdentityApi & + SessionApi +>().with({ id: 'core.auth.vmware-cloud', + pluginId: 'app', }); /** @@ -508,6 +565,9 @@ export const vmwareCloudAuthApiRef: ApiRef< */ export const openshiftAuthApiRef: ApiRef< OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi -> = createApiRef({ +> = createApiRef< + OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi +>().with({ id: 'core.auth.openshift', + pluginId: 'app', }); diff --git a/packages/frontend-plugin-api/src/apis/system/ApiRef.test.ts b/packages/frontend-plugin-api/src/apis/system/ApiRef.test.ts index 556fc3e477..b20134cc2a 100644 --- a/packages/frontend-plugin-api/src/apis/system/ApiRef.test.ts +++ b/packages/frontend-plugin-api/src/apis/system/ApiRef.test.ts @@ -26,9 +26,10 @@ describe('ApiRef', () => { }); it('should be created with builder pattern', () => { - const ref = createApiRef().with({ id: 'abc' }); + const ref = createApiRef().with({ id: 'abc', pluginId: 'test' }); expect(ref.$$type).toBe('@backstage/ApiRef'); expect(ref.id).toBe('abc'); + expect(ref.pluginId).toBe('test'); expect(String(ref)).toBe('apiRef{abc}'); expect(() => ref.T).toThrow('tried to read ApiRef.T of apiRef{abc}'); }); diff --git a/packages/frontend-plugin-api/src/apis/system/ApiRef.ts b/packages/frontend-plugin-api/src/apis/system/ApiRef.ts index 0dc181591c..3cc7fc6649 100644 --- a/packages/frontend-plugin-api/src/apis/system/ApiRef.ts +++ b/packages/frontend-plugin-api/src/apis/system/ApiRef.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import { OpaqueType } from '@internal/opaque'; import type { ApiRef } from './types'; /** @@ -23,8 +24,21 @@ import type { ApiRef } from './types'; */ export type ApiRefConfig = { id: string; + pluginId?: string; }; +const OpaqueApiRef = OpaqueType.create<{ + public: ApiRef & { + readonly $$type: '@backstage/ApiRef'; + }; + versions: { + readonly version: 'v1'; + }; +}>({ + type: '@backstage/ApiRef', + versions: ['v1'], +}); + function validateId(id: string): void { const valid = id .split('.') @@ -37,22 +51,24 @@ function validateId(id: string): void { } } -function makeApiRef(id: string): ApiRef { - const ref = { - $$type: '@backstage/ApiRef' as const, - version: 'v1', - id, +function makeApiRef( + config: ApiRefConfig, +): ApiRef & { readonly $$type: '@backstage/ApiRef' } { + const ref = OpaqueApiRef.createInstance('v1', { + id: config.id, + ...(config.pluginId ? { pluginId: config.pluginId } : {}), + T: undefined as T, toString() { - return `apiRef{${id}}`; + return `apiRef{${config.id}}`; }, - }; + }) as ApiRef & { readonly $$type: '@backstage/ApiRef' }; Object.defineProperty(ref, 'T', { get(): T { throw new Error(`tried to read ApiRef.T of ${this}`); }, enumerable: false, }); - return ref as unknown as ApiRef; + return ref; } /** @@ -61,18 +77,22 @@ function makeApiRef(id: string): ApiRef { * @remarks * * The `id` is a stable identifier for the API implementation. The frontend - * system infers the owning plugin for an API from the `id`. The recommended - * pattern is `plugin..*` (for example, + * system infers the owning plugin for an API from the `id`, unless you provide + * a `pluginId` explicitly. The recommended pattern is `plugin..*` + * (for example, * `plugin.catalog.entity-presentation`). This ensures that other plugins can't * mistakenly override your API implementation. * * The recommended way to create an API reference is: * * ```ts - * const myApiRef = createApiRef().with({ id: 'plugin.my.api' }); + * const myApiRef = createApiRef().with({ + * id: 'my-api', + * pluginId: 'my-plugin', + * }); * ``` * - * For backwards compatibility, you can also pass the config directly: + * The legacy way to create an API reference is: * * ```ts * const myApiRef = createApiRef({ id: 'plugin.my.api' }); @@ -80,30 +100,47 @@ function makeApiRef(id: string): ApiRef { * * @public */ -export function createApiRef(config: ApiRefConfig): ApiRef; +/** + * Creates a reference to an API. + * + * @deprecated Use `createApiRef().with(...)` instead. + * @public + */ +export function createApiRef( + config: ApiRefConfig, +): ApiRef & { readonly $$type: '@backstage/ApiRef' }; /** * Creates a reference to an API. * * @remarks * - * Returns a builder with a `.with()` method for providing the `id`. + * Returns a builder with a `.with()` method for providing the API reference + * configuration. * * @public */ export function createApiRef(): { - with(config: ApiRefConfig): ApiRef; + with(config: ApiRefConfig): ApiRef & { + readonly $$type: '@backstage/ApiRef'; + }; }; -export function createApiRef( - config?: ApiRefConfig, -): ApiRef | { with(config: ApiRefConfig): ApiRef } { +export function createApiRef(config?: ApiRefConfig): + | (ApiRef & { readonly $$type: '@backstage/ApiRef' }) + | { + with(config: ApiRefConfig): ApiRef & { + readonly $$type: '@backstage/ApiRef'; + }; + } { if (config) { validateId(config.id); - return makeApiRef(config.id); + return makeApiRef(config); } return { - with(withConfig: ApiRefConfig): ApiRef { + with(withConfig: ApiRefConfig): ApiRef & { + readonly $$type: '@backstage/ApiRef'; + } { validateId(withConfig.id); - return makeApiRef(withConfig.id); + return makeApiRef(withConfig); }, }; } diff --git a/packages/frontend-plugin-api/src/apis/system/types.ts b/packages/frontend-plugin-api/src/apis/system/types.ts index 570e9a4e25..90e7365164 100644 --- a/packages/frontend-plugin-api/src/apis/system/types.ts +++ b/packages/frontend-plugin-api/src/apis/system/types.ts @@ -20,8 +20,9 @@ * @public */ export type ApiRef = { - readonly $$type: '@backstage/ApiRef'; + readonly $$type?: '@backstage/ApiRef'; readonly id: string; + readonly pluginId?: string; readonly T: T; }; diff --git a/packages/frontend-plugin-api/src/apis/system/useApi.test.tsx b/packages/frontend-plugin-api/src/apis/system/useApi.test.tsx index 7596105810..a5cfb627ac 100644 --- a/packages/frontend-plugin-api/src/apis/system/useApi.test.tsx +++ b/packages/frontend-plugin-api/src/apis/system/useApi.test.tsx @@ -38,7 +38,9 @@ describe('useApiHolder', () => { const renderedHook = renderHook(() => useApiHolder()); const holder = renderedHook.result.current; - expect(holder.get(createApiRef({ id: 'x' }))).toBeUndefined(); + expect( + holder.get(createApiRef().with({ id: 'x' })), + ).toBeUndefined(); }); }); @@ -53,7 +55,7 @@ describe('useApi', () => { const get = jest.fn(() => 'my-api-impl'); context.set({ 1: { get } }); - const apiRef = createApiRef({ id: 'x' }); + const apiRef = createApiRef().with({ id: 'x' }); const renderedHook = renderHook(() => useApi(apiRef)); const value = renderedHook.result.current; diff --git a/packages/frontend-plugin-api/src/blueprints/ApiBlueprint.test.ts b/packages/frontend-plugin-api/src/blueprints/ApiBlueprint.test.ts index 8043752687..8e9c35afc8 100644 --- a/packages/frontend-plugin-api/src/blueprints/ApiBlueprint.test.ts +++ b/packages/frontend-plugin-api/src/blueprints/ApiBlueprint.test.ts @@ -20,7 +20,7 @@ import { createApiRef } from '../apis/system'; describe('ApiBlueprint', () => { it('should create an extension with sensible defaults', () => { - const api = createApiRef<{ foo: string }>({ id: 'test' }); + const api = createApiRef<{ foo: string }>().with({ id: 'test' }); const extension = ApiBlueprint.make({ params: defineParams => @@ -57,8 +57,8 @@ describe('ApiBlueprint', () => { }); it('should properly type the API factory', () => { - const fooApi = createApiRef<{ foo: string }>({ id: 'foo' }); - const barApi = createApiRef<{ bar: string }>({ id: 'bar' }); + const fooApi = createApiRef<{ foo: string }>().with({ id: 'foo' }); + const barApi = createApiRef<{ bar: string }>().with({ id: 'bar' }); expect('test').not.toBe('failing without assertions'); @@ -152,7 +152,7 @@ describe('ApiBlueprint', () => { }); it('should create an extension with custom factory', () => { - const api = createApiRef<{ foo: string }>({ id: 'test' }); + const api = createApiRef<{ foo: string }>().with({ id: 'test' }); const factory = jest.fn(() => ({ foo: 'bar' })); const extension = ApiBlueprint.makeWithOverrides({ diff --git a/plugins/scaffolder-react/report-alpha.api.md b/plugins/scaffolder-react/report-alpha.api.md index c546f265be..9e01257c5c 100644 --- a/plugins/scaffolder-react/report-alpha.api.md +++ b/plugins/scaffolder-react/report-alpha.api.md @@ -200,7 +200,9 @@ export type FormFieldExtensionData< }; // @alpha (undocumented) -export const formFieldsApiRef: ApiRef; +export const formFieldsApiRef: ApiRef & { + readonly $$type: '@backstage/ApiRef'; +}; // @alpha (undocumented) export type FormValidation = { diff --git a/plugins/scaffolder-react/report.api.md b/plugins/scaffolder-react/report.api.md index daec52a7e3..d40b0278bf 100644 --- a/plugins/scaffolder-react/report.api.md +++ b/plugins/scaffolder-react/report.api.md @@ -208,7 +208,9 @@ export type ReviewStepProps = { export type ScaffolderApi = ScaffolderApi_2; // @public (undocumented) -export const scaffolderApiRef: ApiRef; +export const scaffolderApiRef: ApiRef & { + readonly $$type: '@backstage/ApiRef'; +}; // @public @deprecated (undocumented) export type ScaffolderDryRunOptions = ScaffolderDryRunOptions_2; diff --git a/plugins/scaffolder/report-alpha.api.md b/plugins/scaffolder/report-alpha.api.md index 7c96a74c8b..b2cd1bbcbe 100644 --- a/plugins/scaffolder/report-alpha.api.md +++ b/plugins/scaffolder/report-alpha.api.md @@ -479,7 +479,9 @@ export const formDecoratorsApi: OverridableExtensionDefinition<{ }>; // @alpha (undocumented) -export const formDecoratorsApiRef: ApiRef; +export const formDecoratorsApiRef: ApiRef & { + readonly $$type: '@backstage/ApiRef'; +}; export { formFieldsApiRef }; diff --git a/plugins/scaffolder/report.api.md b/plugins/scaffolder/report.api.md index 5c0fffbcc1..17fd25e646 100644 --- a/plugins/scaffolder/report.api.md +++ b/plugins/scaffolder/report.api.md @@ -528,7 +528,9 @@ export type RouterProps = { export type ScaffolderApi = ScaffolderApi_2; // @public @deprecated (undocumented) -export const scaffolderApiRef: ApiRef; +export const scaffolderApiRef: ApiRef & { + readonly $$type: '@backstage/ApiRef'; +}; // @public @deprecated export class ScaffolderClient extends ScaffolderClient_2 {} From 476df5ffd5a5a8ba7d9b780fc74059c170d52269 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Mar 2026 17:04:41 +0100 Subject: [PATCH 03/13] Fix changeset frontmatter formatting Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .changeset/opaque-api-ref-type.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.changeset/opaque-api-ref-type.md b/.changeset/opaque-api-ref-type.md index 7397982cf6..81f365b578 100644 --- a/.changeset/opaque-api-ref-type.md +++ b/.changeset/opaque-api-ref-type.md @@ -1,4 +1,6 @@ -## '@backstage/frontend-plugin-api': patch +--- +'@backstage/frontend-plugin-api': patch +--- Added a builder form for `createApiRef` in the new frontend system and deprecated the direct `createApiRef({ ... })` call in favor of `createApiRef().with({ ... })`. From 29b87812ba3171b3c7058681452e1e98eeeab3ca Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Mar 2026 17:31:06 +0100 Subject: [PATCH 04/13] Regenerate API reports Signed-off-by: Patrik Oldsberg Made-with: Cursor --- packages/app-example-plugin/report.api.md | 2 +- packages/cli-defaults/report.api.md | 4 +- packages/core-components/report-alpha.api.md | 4 +- packages/frontend-plugin-api/report.api.md | 8 ++- plugins/api-docs/report-alpha.api.md | 34 +++++------ plugins/app-visualizer/report.api.md | 8 +-- plugins/app/report.api.md | 4 +- plugins/auth/report.api.md | 2 +- plugins/catalog-graph/report-alpha.api.md | 14 ++--- plugins/catalog-import/report-alpha.api.md | 10 ++-- plugins/catalog-react/report-alpha.api.md | 30 +++++----- .../report-alpha.api.md | 4 +- plugins/catalog/report-alpha.api.md | 58 +++++++++---------- plugins/catalog/report.api.md | 2 +- plugins/devtools-react/report.api.md | 2 +- plugins/devtools/report-alpha.api.md | 2 +- plugins/home/report-alpha.api.md | 4 +- plugins/kubernetes-react/report-alpha.api.md | 8 +-- plugins/kubernetes/report-alpha.api.md | 6 +- plugins/mui-to-bui/report.api.md | 2 +- plugins/notifications/report-alpha.api.md | 14 ++--- plugins/org/report-alpha.api.md | 16 ++--- .../report.api.md | 28 ++++----- .../report.api.md | 2 +- .../report.api.md | 2 +- .../report.api.md | 22 +++---- .../report.api.md | 34 +++++------ .../report.api.md | 4 +- plugins/scaffolder-backend/report.api.md | 2 +- plugins/scaffolder-react/report-alpha.api.md | 2 +- plugins/scaffolder/report-alpha.api.md | 30 +++++----- .../report.api.md | 4 +- plugins/search/report-alpha.api.md | 4 +- plugins/techdocs/report-alpha.api.md | 10 ++-- plugins/user-settings/report-alpha.api.md | 12 ++-- 35 files changed, 197 insertions(+), 197 deletions(-) diff --git a/packages/app-example-plugin/report.api.md b/packages/app-example-plugin/report.api.md index 432174da68..0879f318aa 100644 --- a/packages/app-example-plugin/report.api.md +++ b/packages/app-example-plugin/report.api.md @@ -27,8 +27,8 @@ const examplePlugin: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - title?: string | undefined; path?: string | undefined; + title?: string | undefined; }; output: | ExtensionDataRef diff --git a/packages/cli-defaults/report.api.md b/packages/cli-defaults/report.api.md index 573f8ee454..1a40836eaa 100644 --- a/packages/cli-defaults/report.api.md +++ b/packages/cli-defaults/report.api.md @@ -3,10 +3,8 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { CliModule } from '@backstage/cli-node'; - // @public -const _default: CliModule[]; +const _default: any[]; export default _default; // (No @packageDocumentation comment for this package) diff --git a/packages/core-components/report-alpha.api.md b/packages/core-components/report-alpha.api.md index f373dd56ff..7b7f514dcf 100644 --- a/packages/core-components/report-alpha.api.md +++ b/packages/core-components/report-alpha.api.md @@ -12,8 +12,8 @@ export const coreComponentsTranslationRef: TranslationRef< readonly 'table.filter.title': 'Filters'; readonly 'table.filter.placeholder': 'All results'; readonly 'table.filter.clearAll': 'Clear all'; - readonly 'table.body.emptyDataSourceMessage': 'No records to display'; readonly 'table.header.actions': 'Actions'; + readonly 'table.body.emptyDataSourceMessage': 'No records to display'; readonly 'table.toolbar.search': 'Filter'; readonly 'table.pagination.labelDisplayedRows': '{from}-{to} of {count}'; readonly 'table.pagination.firstTooltip': 'First Page'; @@ -37,9 +37,9 @@ export const coreComponentsTranslationRef: TranslationRef< readonly 'signIn.guestProvider.subtitle': 'Enter as a Guest User.\n You will not have a verified identity, meaning some features might be unavailable.'; readonly skipToContent: 'Skip to content'; readonly 'copyTextButton.tooltipText': 'Text copied to clipboard'; - readonly 'simpleStepper.finish': 'Finish'; readonly 'simpleStepper.reset': 'Reset'; readonly 'simpleStepper.next': 'Next'; + readonly 'simpleStepper.finish': 'Finish'; readonly 'simpleStepper.skip': 'Skip'; readonly 'simpleStepper.back': 'Back'; readonly 'errorPage.title': 'Looks like someone dropped the mic!'; diff --git a/packages/frontend-plugin-api/report.api.md b/packages/frontend-plugin-api/report.api.md index 17b3ecc75d..72f22b4093 100644 --- a/packages/frontend-plugin-api/report.api.md +++ b/packages/frontend-plugin-api/report.api.md @@ -1792,8 +1792,8 @@ export const PageBlueprint: ExtensionBlueprint_2<{ title: string | undefined; }; configInput: { - title?: string | undefined; path?: string | undefined; + title?: string | undefined; }; dataRefs: never; }>; @@ -1907,7 +1907,9 @@ export type PluginWrapperApi = { }; // @public -export const pluginWrapperApiRef: ApiRef_2; +export const pluginWrapperApiRef: ApiRef_2 & { + readonly $$type: '@backstage/ApiRef'; +}; // @public export const PluginWrapperBlueprint: ExtensionBlueprint_2<{ @@ -2102,8 +2104,8 @@ export const SubPageBlueprint: ExtensionBlueprint_2<{ title: string | undefined; }; configInput: { - title?: string | undefined; path?: string | undefined; + title?: string | undefined; }; dataRefs: never; }>; diff --git a/plugins/api-docs/report-alpha.api.md b/plugins/api-docs/report-alpha.api.md index 0ee7ac5460..434cc38691 100644 --- a/plugins/api-docs/report-alpha.api.md +++ b/plugins/api-docs/report-alpha.api.md @@ -91,11 +91,11 @@ const _default: OverridableFrontendPlugin< name: 'consumed-apis'; config: { filter: FilterPredicate | undefined; - type: 'content' | 'info' | undefined; + type: 'info' | 'content' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'content' | 'info' | undefined; + type?: 'info' | 'content' | undefined; }; output: | ExtensionDataRef @@ -132,11 +132,11 @@ const _default: OverridableFrontendPlugin< name: 'consuming-components'; config: { filter: FilterPredicate | undefined; - type: 'content' | 'info' | undefined; + type: 'info' | 'content' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'content' | 'info' | undefined; + type?: 'info' | 'content' | undefined; }; output: | ExtensionDataRef @@ -173,11 +173,11 @@ const _default: OverridableFrontendPlugin< name: 'definition'; config: { filter: FilterPredicate | undefined; - type: 'content' | 'info' | undefined; + type: 'info' | 'content' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'content' | 'info' | undefined; + type?: 'info' | 'content' | undefined; }; output: | ExtensionDataRef @@ -214,11 +214,11 @@ const _default: OverridableFrontendPlugin< name: 'has-apis'; config: { filter: FilterPredicate | undefined; - type: 'content' | 'info' | undefined; + type: 'info' | 'content' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'content' | 'info' | undefined; + type?: 'info' | 'content' | undefined; }; output: | ExtensionDataRef @@ -255,11 +255,11 @@ const _default: OverridableFrontendPlugin< name: 'provided-apis'; config: { filter: FilterPredicate | undefined; - type: 'content' | 'info' | undefined; + type: 'info' | 'content' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'content' | 'info' | undefined; + type?: 'info' | 'content' | undefined; }; output: | ExtensionDataRef @@ -296,11 +296,11 @@ const _default: OverridableFrontendPlugin< name: 'providing-components'; config: { filter: FilterPredicate | undefined; - type: 'content' | 'info' | undefined; + type: 'info' | 'content' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'content' | 'info' | undefined; + type?: 'info' | 'content' | undefined; }; output: | ExtensionDataRef @@ -344,10 +344,10 @@ const _default: OverridableFrontendPlugin< }; configInput: { filter?: FilterPredicate | undefined; - title?: string | undefined; path?: string | undefined; - group?: string | false | undefined; + title?: string | undefined; icon?: string | undefined; + group?: string | false | undefined; }; output: | ExtensionDataRef @@ -414,10 +414,10 @@ const _default: OverridableFrontendPlugin< }; configInput: { filter?: FilterPredicate | undefined; - title?: string | undefined; path?: string | undefined; - group?: string | false | undefined; + title?: string | undefined; icon?: string | undefined; + group?: string | false | undefined; }; output: | ExtensionDataRef @@ -501,8 +501,8 @@ const _default: OverridableFrontendPlugin< }; configInput: { initiallySelectedFilter?: 'all' | 'owned' | 'starred' | undefined; - title?: string | undefined; path?: string | undefined; + title?: string | undefined; }; output: | ExtensionDataRef diff --git a/plugins/app-visualizer/report.api.md b/plugins/app-visualizer/report.api.md index 9ee06eccb0..2550026e98 100644 --- a/plugins/app-visualizer/report.api.md +++ b/plugins/app-visualizer/report.api.md @@ -49,8 +49,8 @@ const visualizerPlugin: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - title?: string | undefined; path?: string | undefined; + title?: string | undefined; }; output: | ExtensionDataRef @@ -138,8 +138,8 @@ const visualizerPlugin: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - title?: string | undefined; path?: string | undefined; + title?: string | undefined; }; output: | ExtensionDataRef @@ -176,8 +176,8 @@ const visualizerPlugin: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - title?: string | undefined; path?: string | undefined; + title?: string | undefined; }; output: | ExtensionDataRef @@ -214,8 +214,8 @@ const visualizerPlugin: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - title?: string | undefined; path?: string | undefined; + title?: string | undefined; }; output: | ExtensionDataRef diff --git a/plugins/app/report.api.md b/plugins/app/report.api.md index 0262c4c1ef..b6b23a0d3b 100644 --- a/plugins/app/report.api.md +++ b/plugins/app/report.api.md @@ -775,14 +775,14 @@ const appPlugin: OverridableFrontendPlugin< transientTimeoutMs: number; anchorOrigin: { horizontal: 'center' | 'left' | 'right'; - vertical: 'top' | 'bottom'; + vertical: 'bottom' | 'top'; }; }; configInput: { anchorOrigin?: | { horizontal?: 'center' | 'left' | 'right' | undefined; - vertical?: 'top' | 'bottom' | undefined; + vertical?: 'bottom' | 'top' | undefined; } | undefined; transientTimeoutMs?: number | undefined; diff --git a/plugins/auth/report.api.md b/plugins/auth/report.api.md index 8e8ac71d31..903b8397c9 100644 --- a/plugins/auth/report.api.md +++ b/plugins/auth/report.api.md @@ -28,8 +28,8 @@ const _default: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - title?: string | undefined; path?: string | undefined; + title?: string | undefined; }; output: | ExtensionDataRef diff --git a/plugins/catalog-graph/report-alpha.api.md b/plugins/catalog-graph/report-alpha.api.md index f9d4542625..e1497f7623 100644 --- a/plugins/catalog-graph/report-alpha.api.md +++ b/plugins/catalog-graph/report-alpha.api.md @@ -95,14 +95,14 @@ const _default: OverridableFrontendPlugin< title: string | undefined; height: number | undefined; filter: FilterPredicate | undefined; - type: 'content' | 'info' | undefined; + type: 'info' | 'content' | undefined; }; configInput: { + title?: string | undefined; height?: number | undefined; - curve?: 'curveStepBefore' | 'curveMonotoneX' | undefined; direction?: 'TB' | 'BT' | 'LR' | 'RL' | undefined; zoom?: 'disabled' | 'enabled' | 'enable-on-click' | undefined; - title?: string | undefined; + curve?: 'curveStepBefore' | 'curveMonotoneX' | undefined; relations?: string[] | undefined; maxDepth?: number | undefined; kinds?: string[] | undefined; @@ -110,7 +110,7 @@ const _default: OverridableFrontendPlugin< relationPairs?: [string, string][] | undefined; unidirectional?: boolean | undefined; filter?: FilterPredicate | undefined; - type?: 'content' | 'info' | undefined; + type?: 'info' | 'content' | undefined; }; output: | ExtensionDataRef @@ -163,12 +163,12 @@ const _default: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - curve?: 'curveStepBefore' | 'curveMonotoneX' | undefined; direction?: 'TB' | 'BT' | 'LR' | 'RL' | undefined; zoom?: 'disabled' | 'enabled' | 'enable-on-click' | undefined; + curve?: 'curveStepBefore' | 'curveMonotoneX' | undefined; relations?: string[] | undefined; - maxDepth?: number | undefined; rootEntityRefs?: string[] | undefined; + maxDepth?: number | undefined; kinds?: string[] | undefined; mergeRelations?: boolean | undefined; relationPairs?: [string, string][] | undefined; @@ -176,8 +176,8 @@ const _default: OverridableFrontendPlugin< selectedRelations?: string[] | undefined; selectedKinds?: string[] | undefined; showFilters?: boolean | undefined; - title?: string | undefined; path?: string | undefined; + title?: string | undefined; }; output: | ExtensionDataRef diff --git a/plugins/catalog-import/report-alpha.api.md b/plugins/catalog-import/report-alpha.api.md index b58b641050..70799ed325 100644 --- a/plugins/catalog-import/report-alpha.api.md +++ b/plugins/catalog-import/report-alpha.api.md @@ -34,8 +34,8 @@ export const catalogImportTranslationRef: TranslationRef< readonly 'importInfoCard.fileLinkDescription': 'The wizard analyzes the file, previews the entities, and adds them to the {{appTitle}} catalog.'; readonly 'importInfoCard.exampleDescription': 'The wizard discovers all {{catalogFilename}} files in the repository, previews the entities, and adds them to the {{appTitle}} catalog.'; readonly 'importInfoCard.preparePullRequestDescription': 'If no entities are found, the wizard will prepare a Pull Request that adds an example {{catalogFilename}} and prepares the {{appTitle}} catalog to load all entities as soon as the Pull Request is merged.'; - readonly 'importInfoCard.githubIntegration.label': 'GitHub only'; readonly 'importInfoCard.githubIntegration.title': 'Link to a repository'; + readonly 'importInfoCard.githubIntegration.label': 'GitHub only'; readonly 'importStepper.finish.title': 'Finish'; readonly 'importStepper.singleLocation.title': 'Select Locations'; readonly 'importStepper.singleLocation.description': 'Discovered Locations: 1'; @@ -62,8 +62,8 @@ export const catalogImportTranslationRef: TranslationRef< readonly 'importStepper.review.title': 'Review'; readonly 'stepFinishImportLocation.repository.title': 'The following Pull Request has been opened: '; readonly 'stepFinishImportLocation.repository.description': 'Your entities will be imported as soon as the Pull Request is merged.'; - readonly 'stepFinishImportLocation.locations.new': 'The following entities have been added to the catalog:'; readonly 'stepFinishImportLocation.locations.backButtonText': 'Register another'; + readonly 'stepFinishImportLocation.locations.new': 'The following entities have been added to the catalog:'; readonly 'stepFinishImportLocation.locations.existing': 'A refresh was triggered for the following locations:'; readonly 'stepFinishImportLocation.locations.viewButtonText': 'View Component'; readonly 'stepFinishImportLocation.backButtonText': 'Register another'; @@ -83,9 +83,9 @@ export const catalogImportTranslationRef: TranslationRef< readonly 'stepPrepareSelectLocations.nextButtonText': 'Review'; readonly 'stepPrepareSelectLocations.existingLocations.description': 'These locations already exist in the catalog:'; readonly 'stepReviewLocation.refresh': 'Refresh'; - readonly 'stepReviewLocation.import': 'Import'; - readonly 'stepReviewLocation.catalog.new': 'The following entities will be added to the catalog:'; readonly 'stepReviewLocation.catalog.exists': 'The following locations already exist in the catalog:'; + readonly 'stepReviewLocation.catalog.new': 'The following entities will be added to the catalog:'; + readonly 'stepReviewLocation.import': 'Import'; readonly 'stepReviewLocation.prepareResult.title': 'The following Pull Request has been opened: '; readonly 'stepReviewLocation.prepareResult.description': 'You can already import the location and {{appTitle}} will fetch the entities as soon as the Pull Request is merged.'; } @@ -121,8 +121,8 @@ const _default: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - title?: string | undefined; path?: string | undefined; + title?: string | undefined; }; output: | ExtensionDataRef diff --git a/plugins/catalog-react/report-alpha.api.md b/plugins/catalog-react/report-alpha.api.md index 9c76a221dc..ee0b8bb3ff 100644 --- a/plugins/catalog-react/report-alpha.api.md +++ b/plugins/catalog-react/report-alpha.api.md @@ -73,17 +73,17 @@ export const catalogReactTranslationRef: TranslationRef< readonly 'inspectEntityDialog.jsonPage.title': 'Entity as JSON'; readonly 'inspectEntityDialog.jsonPage.description': 'This is the raw entity data as received from the catalog, on JSON form.'; readonly 'inspectEntityDialog.overviewPage.title': 'Overview'; - readonly 'inspectEntityDialog.overviewPage.metadata.title': 'Metadata'; - readonly 'inspectEntityDialog.overviewPage.labels': 'Labels'; readonly 'inspectEntityDialog.overviewPage.status.title': 'Status'; readonly 'inspectEntityDialog.overviewPage.identity.title': 'Identity'; + readonly 'inspectEntityDialog.overviewPage.metadata.title': 'Metadata'; readonly 'inspectEntityDialog.overviewPage.annotations': 'Annotations'; readonly 'inspectEntityDialog.overviewPage.tags': 'Tags'; + readonly 'inspectEntityDialog.overviewPage.labels': 'Labels'; readonly 'inspectEntityDialog.overviewPage.relation.title': 'Relations'; readonly 'inspectEntityDialog.yamlPage.title': 'Entity as YAML'; readonly 'inspectEntityDialog.yamlPage.description': 'This is the raw entity data as received from the catalog, on YAML form.'; - readonly 'inspectEntityDialog.tabNames.json': 'Raw JSON'; readonly 'inspectEntityDialog.tabNames.yaml': 'Raw YAML'; + readonly 'inspectEntityDialog.tabNames.json': 'Raw JSON'; readonly 'inspectEntityDialog.tabNames.overview': 'Overview'; readonly 'inspectEntityDialog.tabNames.ancestry': 'Ancestry'; readonly 'inspectEntityDialog.tabNames.colocated': 'Colocated'; @@ -108,17 +108,17 @@ export const catalogReactTranslationRef: TranslationRef< readonly 'userListPicker.personalFilter.ownedLabel': 'Owned'; readonly 'userListPicker.personalFilter.starredLabel': 'Starred'; readonly 'entityTableColumnTitle.name': 'Name'; - readonly 'entityTableColumnTitle.type': 'Type'; - readonly 'entityTableColumnTitle.label': 'Label'; + readonly 'entityTableColumnTitle.namespace': 'Namespace'; readonly 'entityTableColumnTitle.title': 'Title'; readonly 'entityTableColumnTitle.description': 'Description'; - readonly 'entityTableColumnTitle.system': 'System'; - readonly 'entityTableColumnTitle.namespace': 'Namespace'; - readonly 'entityTableColumnTitle.domain': 'Domain'; + readonly 'entityTableColumnTitle.type': 'Type'; + readonly 'entityTableColumnTitle.label': 'Label'; readonly 'entityTableColumnTitle.tags': 'Tags'; readonly 'entityTableColumnTitle.owner': 'Owner'; readonly 'entityTableColumnTitle.lifecycle': 'Lifecycle'; + readonly 'entityTableColumnTitle.system': 'System'; readonly 'entityTableColumnTitle.targets': 'Targets'; + readonly 'entityTableColumnTitle.domain': 'Domain'; readonly 'missingAnnotationEmptyState.title': 'Missing Annotation'; readonly 'missingAnnotationEmptyState.readMore': 'Read more'; readonly 'missingAnnotationEmptyState.annotationYaml': 'Add the annotation to your {{entityKind}} YAML as shown in the highlighted example below:'; @@ -213,11 +213,11 @@ export const EntityCardBlueprint: ExtensionBlueprint<{ inputs: {}; config: { filter: FilterPredicate | undefined; - type: 'content' | 'info' | undefined; + type: 'info' | 'content' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'content' | 'info' | undefined; + type?: 'info' | 'content' | undefined; }; dataRefs: { filterFunction: ConfigurableExtensionDataRef< @@ -305,10 +305,10 @@ export const EntityContentBlueprint: ExtensionBlueprint<{ }; configInput: { filter?: FilterPredicate | undefined; - title?: string | undefined; path?: string | undefined; - group?: string | false | undefined; + title?: string | undefined; icon?: string | undefined; + group?: string | false | undefined; }; dataRefs: { title: ConfigurableExtensionDataRef< @@ -535,8 +535,8 @@ export const EntityIconLinkBlueprint: ExtensionBlueprint<{ }; configInput: { filter?: FilterPredicate | undefined; - label?: string | undefined; title?: string | undefined; + label?: string | undefined; }; dataRefs: { useProps: ConfigurableExtensionDataRef< @@ -561,9 +561,8 @@ export const EntityIconLinkBlueprint: ExtensionBlueprint<{ export const EntityTableColumnTitle: ( input: EntityTableColumnTitleProps, ) => - | 'System' - | 'Title' | 'Domain' + | 'System' | 'Lifecycle' | 'Namespace' | 'Owner' @@ -572,6 +571,7 @@ export const EntityTableColumnTitle: ( | 'Name' | 'Description' | 'Targets' + | 'Title' | 'Label'; // @alpha (undocumented) diff --git a/plugins/catalog-unprocessed-entities/report-alpha.api.md b/plugins/catalog-unprocessed-entities/report-alpha.api.md index 7408831f87..2d254d15ac 100644 --- a/plugins/catalog-unprocessed-entities/report-alpha.api.md +++ b/plugins/catalog-unprocessed-entities/report-alpha.api.md @@ -70,8 +70,8 @@ const _default: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - title?: string | undefined; path?: string | undefined; + title?: string | undefined; }; output: | ExtensionDataRef @@ -151,8 +151,8 @@ export const unprocessedEntitiesDevToolsContent: OverridableExtensionDefinition< title: string | undefined; }; configInput: { - title?: string | undefined; path?: string | undefined; + title?: string | undefined; }; output: | ExtensionDataRef diff --git a/plugins/catalog/report-alpha.api.md b/plugins/catalog/report-alpha.api.md index a0b092a453..d77b673744 100644 --- a/plugins/catalog/report-alpha.api.md +++ b/plugins/catalog/report-alpha.api.md @@ -46,8 +46,8 @@ export const catalogTranslationRef: TranslationRef< readonly 'indexPage.supportButtonContent': 'All your software catalog entities'; readonly 'entityPage.notFoundMessage': 'There is no {{kind}} with the requested {{link}}.'; readonly 'entityPage.notFoundLinkText': 'kind, namespace, and name'; - readonly 'aboutCard.title': 'About'; readonly 'aboutCard.unknown': 'unknown'; + readonly 'aboutCard.title': 'About'; readonly 'aboutCard.refreshButtonTitle': 'Schedule entity refresh'; readonly 'aboutCard.editButtonTitle': 'Edit Metadata'; readonly 'aboutCard.editButtonAriaLabel': 'Edit'; @@ -72,8 +72,8 @@ export const catalogTranslationRef: TranslationRef< readonly 'aboutCard.tagsField.value': 'No Tags'; readonly 'aboutCard.tagsField.label': 'Tags'; readonly 'aboutCard.targetsField.label': 'Targets'; - readonly 'searchResultItem.type': 'Type'; readonly 'searchResultItem.kind': 'Kind'; + readonly 'searchResultItem.type': 'Type'; readonly 'searchResultItem.owner': 'Owner'; readonly 'searchResultItem.lifecycle': 'Lifecycle'; readonly 'catalogTable.allFilters': 'All'; @@ -308,11 +308,11 @@ const _default: OverridableFrontendPlugin< 'entity-card:catalog/about': OverridableExtensionDefinition<{ config: { filter: FilterPredicate | undefined; - type: 'content' | 'info' | undefined; + type: 'info' | 'content' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'content' | 'info' | undefined; + type?: 'info' | 'content' | undefined; }; output: | ExtensionDataRef @@ -378,11 +378,11 @@ const _default: OverridableFrontendPlugin< name: 'depends-on-components'; config: { filter: FilterPredicate | undefined; - type: 'content' | 'info' | undefined; + type: 'info' | 'content' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'content' | 'info' | undefined; + type?: 'info' | 'content' | undefined; }; output: | ExtensionDataRef @@ -419,11 +419,11 @@ const _default: OverridableFrontendPlugin< name: 'depends-on-resources'; config: { filter: FilterPredicate | undefined; - type: 'content' | 'info' | undefined; + type: 'info' | 'content' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'content' | 'info' | undefined; + type?: 'info' | 'content' | undefined; }; output: | ExtensionDataRef @@ -460,11 +460,11 @@ const _default: OverridableFrontendPlugin< name: 'has-components'; config: { filter: FilterPredicate | undefined; - type: 'content' | 'info' | undefined; + type: 'info' | 'content' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'content' | 'info' | undefined; + type?: 'info' | 'content' | undefined; }; output: | ExtensionDataRef @@ -501,11 +501,11 @@ const _default: OverridableFrontendPlugin< name: 'has-resources'; config: { filter: FilterPredicate | undefined; - type: 'content' | 'info' | undefined; + type: 'info' | 'content' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'content' | 'info' | undefined; + type?: 'info' | 'content' | undefined; }; output: | ExtensionDataRef @@ -542,11 +542,11 @@ const _default: OverridableFrontendPlugin< name: 'has-subcomponents'; config: { filter: FilterPredicate | undefined; - type: 'content' | 'info' | undefined; + type: 'info' | 'content' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'content' | 'info' | undefined; + type?: 'info' | 'content' | undefined; }; output: | ExtensionDataRef @@ -583,11 +583,11 @@ const _default: OverridableFrontendPlugin< name: 'has-subdomains'; config: { filter: FilterPredicate | undefined; - type: 'content' | 'info' | undefined; + type: 'info' | 'content' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'content' | 'info' | undefined; + type?: 'info' | 'content' | undefined; }; output: | ExtensionDataRef @@ -624,11 +624,11 @@ const _default: OverridableFrontendPlugin< name: 'has-systems'; config: { filter: FilterPredicate | undefined; - type: 'content' | 'info' | undefined; + type: 'info' | 'content' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'content' | 'info' | undefined; + type?: 'info' | 'content' | undefined; }; output: | ExtensionDataRef @@ -665,11 +665,11 @@ const _default: OverridableFrontendPlugin< name: 'labels'; config: { filter: FilterPredicate | undefined; - type: 'content' | 'info' | undefined; + type: 'info' | 'content' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'content' | 'info' | undefined; + type?: 'info' | 'content' | undefined; }; output: | ExtensionDataRef @@ -706,11 +706,11 @@ const _default: OverridableFrontendPlugin< name: 'links'; config: { filter: FilterPredicate | undefined; - type: 'content' | 'info' | undefined; + type: 'info' | 'content' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'content' | 'info' | undefined; + type?: 'info' | 'content' | undefined; }; output: | ExtensionDataRef @@ -752,10 +752,10 @@ const _default: OverridableFrontendPlugin< }; configInput: { filter?: FilterPredicate | undefined; - title?: string | undefined; path?: string | undefined; - group?: string | false | undefined; + title?: string | undefined; icon?: string | undefined; + group?: string | false | undefined; }; output: | ExtensionDataRef @@ -941,8 +941,8 @@ const _default: OverridableFrontendPlugin< }; configInput: { filter?: FilterPredicate | undefined; - label?: string | undefined; title?: string | undefined; + label?: string | undefined; }; output: | ExtensionDataRef< @@ -996,7 +996,7 @@ const _default: OverridableFrontendPlugin< pagination: | boolean | { - mode: 'offset' | 'cursor'; + mode: 'cursor' | 'offset'; offset?: number | undefined; limit?: number | undefined; }; @@ -1007,13 +1007,13 @@ const _default: OverridableFrontendPlugin< pagination?: | boolean | { - mode: 'offset' | 'cursor'; + mode: 'cursor' | 'offset'; offset?: number | undefined; limit?: number | undefined; } | undefined; - title?: string | undefined; path?: string | undefined; + title?: string | undefined; }; output: | ExtensionDataRef @@ -1122,8 +1122,8 @@ const _default: OverridableFrontendPlugin< | undefined; defaultContentOrder?: 'title' | 'natural' | undefined; showNavItemIcons?: boolean | undefined; - title?: string | undefined; path?: string | undefined; + title?: string | undefined; }; output: | ExtensionDataRef diff --git a/plugins/catalog/report.api.md b/plugins/catalog/report.api.md index 48e3f53de2..6d482004bf 100644 --- a/plugins/catalog/report.api.md +++ b/plugins/catalog/report.api.md @@ -455,7 +455,7 @@ export function EntityRelationWarning(): JSX_2.Element | null; // @public (undocumented) export const EntitySwitch: { - (props: EntitySwitchProps): JSX.Element; + (props: EntitySwitchProps): JSX_2.Element; Case: (_props: EntitySwitchCaseProps) => null; }; diff --git a/plugins/devtools-react/report.api.md b/plugins/devtools-react/report.api.md index 6916afed84..5fb187ee6a 100644 --- a/plugins/devtools-react/report.api.md +++ b/plugins/devtools-react/report.api.md @@ -30,8 +30,8 @@ export const DevToolsContentBlueprint: ExtensionBlueprint<{ title: string | undefined; }; configInput: { - title?: string | undefined; path?: string | undefined; + title?: string | undefined; }; dataRefs: never; }>; diff --git a/plugins/devtools/report-alpha.api.md b/plugins/devtools/report-alpha.api.md index 753875eaaa..7be1867d5d 100644 --- a/plugins/devtools/report-alpha.api.md +++ b/plugins/devtools/report-alpha.api.md @@ -67,8 +67,8 @@ const _default: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - title?: string | undefined; path?: string | undefined; + title?: string | undefined; }; output: | ExtensionDataRef diff --git a/plugins/home/report-alpha.api.md b/plugins/home/report-alpha.api.md index 0269f471fe..e1cc4f8f62 100644 --- a/plugins/home/report-alpha.api.md +++ b/plugins/home/report-alpha.api.md @@ -108,8 +108,8 @@ const _default: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - title?: string | undefined; path?: string | undefined; + title?: string | undefined; }; output: | ExtensionDataRef @@ -224,9 +224,9 @@ export const homeTranslationRef: TranslationRef< readonly 'widgetSettingsOverlay.deleteWidgetTooltip': 'Delete widget'; readonly 'widgetSettingsOverlay.submitButtonTitle': 'Submit'; readonly 'starredEntityListItem.removeFavoriteEntityTitle': 'Remove entity from favorites'; + readonly 'visitList.few.title': 'The more pages you visit, the more pages will appear here.'; readonly 'visitList.empty.title': 'There are no visits to show yet.'; readonly 'visitList.empty.description': 'Once you start using Backstage, your visits will appear here as a quick link to carry on where you left off.'; - readonly 'visitList.few.title': 'The more pages you visit, the more pages will appear here.'; readonly 'quickStart.title': 'Onboarding'; readonly 'quickStart.description': 'Get started with Backstage'; readonly 'quickStart.learnMoreLinkTitle': 'Learn more'; diff --git a/plugins/kubernetes-react/report-alpha.api.md b/plugins/kubernetes-react/report-alpha.api.md index f638bf6789..adb92a772b 100644 --- a/plugins/kubernetes-react/report-alpha.api.md +++ b/plugins/kubernetes-react/report-alpha.api.md @@ -24,6 +24,9 @@ export const kubernetesReactTranslationRef: TranslationRef< readonly 'cluster.noPodsWithErrors': 'No pods with errors'; readonly 'pods.pods_one': '{{count}} pod'; readonly 'pods.pods_other': '{{count}} pods'; + readonly 'podsTable.unknown': 'unknown'; + readonly 'podsTable.status.running': 'Running'; + readonly 'podsTable.status.ok': 'OK'; readonly 'podsTable.columns.name': 'name'; readonly 'podsTable.columns.id': 'ID'; readonly 'podsTable.columns.status': 'status'; @@ -32,9 +35,6 @@ export const kubernetesReactTranslationRef: TranslationRef< readonly 'podsTable.columns.totalRestarts': 'total restarts'; readonly 'podsTable.columns.cpuUsage': 'CPU usage %'; readonly 'podsTable.columns.memoryUsage': 'Memory usage %'; - readonly 'podsTable.unknown': 'unknown'; - readonly 'podsTable.status.running': 'Running'; - readonly 'podsTable.status.ok': 'OK'; readonly 'errorPanel.message': 'There was a problem retrieving some Kubernetes resources for the entity: {{entityName}}. This could mean that the Error Reporting card is not completely accurate.'; readonly 'errorPanel.title': 'There was a problem retrieving Kubernetes objects'; readonly 'errorPanel.errorsLabel': 'Errors'; @@ -65,12 +65,12 @@ export const kubernetesReactTranslationRef: TranslationRef< readonly 'hpa.currentCpuUsageLabel': 'current CPU usage: {{value}}%'; readonly 'hpa.targetCpuUsage': 'target CPU usage:'; readonly 'hpa.targetCpuUsageLabel': 'target CPU usage: {{value}}%'; + readonly 'errorReporting.title': 'Error Reporting'; readonly 'errorReporting.columns.name': 'name'; readonly 'errorReporting.columns.kind': 'kind'; readonly 'errorReporting.columns.namespace': 'namespace'; readonly 'errorReporting.columns.messages': 'messages'; readonly 'errorReporting.columns.cluster': 'cluster'; - readonly 'errorReporting.title': 'Error Reporting'; readonly 'podLogs.title': 'No logs emitted'; readonly 'podLogs.description': 'No logs were emitted by the container'; readonly 'podLogs.buttonText': 'Logs'; diff --git a/plugins/kubernetes/report-alpha.api.md b/plugins/kubernetes/report-alpha.api.md index 7086976724..25090f7431 100644 --- a/plugins/kubernetes/report-alpha.api.md +++ b/plugins/kubernetes/report-alpha.api.md @@ -102,10 +102,10 @@ const _default: OverridableFrontendPlugin< }; configInput: { filter?: FilterPredicate | undefined; - title?: string | undefined; path?: string | undefined; - group?: string | false | undefined; + title?: string | undefined; icon?: string | undefined; + group?: string | false | undefined; }; output: | ExtensionDataRef @@ -168,8 +168,8 @@ const _default: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - title?: string | undefined; path?: string | undefined; + title?: string | undefined; }; output: | ExtensionDataRef diff --git a/plugins/mui-to-bui/report.api.md b/plugins/mui-to-bui/report.api.md index f4bf566c9e..c1c97a49a2 100644 --- a/plugins/mui-to-bui/report.api.md +++ b/plugins/mui-to-bui/report.api.md @@ -42,8 +42,8 @@ const _default: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - title?: string | undefined; path?: string | undefined; + title?: string | undefined; }; output: | ExtensionDataRef diff --git a/plugins/notifications/report-alpha.api.md b/plugins/notifications/report-alpha.api.md index e1feed0cde..ae826a05a1 100644 --- a/plugins/notifications/report-alpha.api.md +++ b/plugins/notifications/report-alpha.api.md @@ -48,8 +48,8 @@ const _default: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - title?: string | undefined; path?: string | undefined; + title?: string | undefined; }; output: | ExtensionDataRef @@ -124,13 +124,13 @@ export default _default; export const notificationsTranslationRef: TranslationRef< 'plugin.notifications', { - readonly 'table.errors.markAllReadFailed': 'Failed to mark all notifications as read'; readonly 'table.pagination.labelDisplayedRows': '{from}-{to} of {count}'; readonly 'table.pagination.firstTooltip': 'First Page'; readonly 'table.pagination.labelRowsSelect': 'rows'; readonly 'table.pagination.lastTooltip': 'Last Page'; readonly 'table.pagination.nextTooltip': 'Next Page'; readonly 'table.pagination.previousTooltip': 'Previous Page'; + readonly 'table.errors.markAllReadFailed': 'Failed to mark all notifications as read'; readonly 'table.emptyMessage': 'No records to display'; readonly 'table.bulkActions.markAllRead': 'Mark all read'; readonly 'table.bulkActions.markSelectedAsRead': 'Mark selected as read'; @@ -140,16 +140,16 @@ export const notificationsTranslationRef: TranslationRef< readonly 'table.confirmDialog.title': 'Are you sure?'; readonly 'table.confirmDialog.markAllReadDescription': 'Mark all notifications as read.'; readonly 'table.confirmDialog.markAllReadConfirmation': 'Mark All'; - readonly 'filters.view.all': 'All'; + readonly 'filters.title': 'Filters'; readonly 'filters.view.label': 'View'; + readonly 'filters.view.all': 'All'; readonly 'filters.view.read': 'Read notifications'; readonly 'filters.view.saved': 'Saved'; readonly 'filters.view.unread': 'Unread notifications'; - readonly 'filters.title': 'Filters'; readonly 'filters.severity.normal': 'Normal'; + readonly 'filters.severity.label': 'Min severity'; readonly 'filters.severity.high': 'High'; readonly 'filters.severity.low': 'Low'; - readonly 'filters.severity.label': 'Min severity'; readonly 'filters.severity.critical': 'Critical'; readonly 'filters.topic.label': 'Topic'; readonly 'filters.topic.anyTopic': 'Any topic'; @@ -161,12 +161,12 @@ export const notificationsTranslationRef: TranslationRef< readonly 'filters.sortBy.origin': 'Origin'; readonly 'filters.sortBy.label': 'Sort by'; readonly 'filters.sortBy.placeholder': 'Field to sort by'; + readonly 'filters.sortBy.topic': 'Topic'; readonly 'filters.sortBy.newest': 'Newest on top'; readonly 'filters.sortBy.oldest': 'Oldest on top'; - readonly 'filters.sortBy.topic': 'Topic'; + readonly 'settings.title': 'Notification settings'; readonly 'settings.table.origin': 'Origin'; readonly 'settings.table.topic': 'Topic'; - readonly 'settings.title': 'Notification settings'; readonly 'settings.errors.useNotificationFormat': 'useNotificationFormat must be used within a NotificationFormatProvider'; readonly 'settings.errorTitle': 'Failed to load settings'; readonly 'settings.noSettingsAvailable': 'No notification settings available, check back later'; diff --git a/plugins/org/report-alpha.api.md b/plugins/org/report-alpha.api.md index 44fd429bfa..76bbc52da2 100644 --- a/plugins/org/report-alpha.api.md +++ b/plugins/org/report-alpha.api.md @@ -25,11 +25,11 @@ const _default: OverridableFrontendPlugin< name: 'group-profile'; config: { filter: FilterPredicate | undefined; - type: 'content' | 'info' | undefined; + type: 'info' | 'content' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'content' | 'info' | undefined; + type?: 'info' | 'content' | undefined; }; output: | ExtensionDataRef @@ -66,13 +66,13 @@ const _default: OverridableFrontendPlugin< initialRelationAggregation: 'direct' | 'aggregated' | undefined; showAggregateMembersToggle: boolean | undefined; filter: FilterPredicate | undefined; - type: 'content' | 'info' | undefined; + type: 'info' | 'content' | undefined; }; configInput: { showAggregateMembersToggle?: boolean | undefined; initialRelationAggregation?: 'direct' | 'aggregated' | undefined; filter?: FilterPredicate | undefined; - type?: 'content' | 'info' | undefined; + type?: 'info' | 'content' | undefined; }; output: | ExtensionDataRef @@ -112,14 +112,14 @@ const _default: OverridableFrontendPlugin< showAggregateMembersToggle: boolean | undefined; ownedKinds: string[] | undefined; filter: FilterPredicate | undefined; - type: 'content' | 'info' | undefined; + type: 'info' | 'content' | undefined; }; configInput: { showAggregateMembersToggle?: boolean | undefined; initialRelationAggregation?: 'direct' | 'aggregated' | undefined; ownedKinds?: string[] | undefined; filter?: FilterPredicate | undefined; - type?: 'content' | 'info' | undefined; + type?: 'info' | 'content' | undefined; }; output: | ExtensionDataRef @@ -158,13 +158,13 @@ const _default: OverridableFrontendPlugin< maxRelations: number | undefined; hideIcons: boolean; filter: FilterPredicate | undefined; - type: 'content' | 'info' | undefined; + type: 'info' | 'content' | undefined; }; configInput: { hideIcons?: boolean | undefined; maxRelations?: number | undefined; filter?: FilterPredicate | undefined; - type?: 'content' | 'info' | undefined; + type?: 'info' | 'content' | undefined; }; output: | ExtensionDataRef diff --git a/plugins/scaffolder-backend-module-bitbucket-cloud/report.api.md b/plugins/scaffolder-backend-module-bitbucket-cloud/report.api.md index af34609213..a7050aa68c 100644 --- a/plugins/scaffolder-backend-module-bitbucket-cloud/report.api.md +++ b/plugins/scaffolder-backend-module-bitbucket-cloud/report.api.md @@ -25,25 +25,25 @@ export const createBitbucketPipelinesRunAction: (options: { | { type?: string | undefined; source?: string | undefined; - selector?: - | { - type: string; - pattern: string; - } - | undefined; - pull_request?: - | { - id: string; - } - | undefined; commit?: | { type: string; hash: string; } | undefined; - destination?: string | undefined; + selector?: + | { + type: string; + pattern: string; + } + | undefined; ref_name?: string | undefined; + destination?: string | undefined; + pull_request?: + | { + id: string; + } + | undefined; ref_type?: string | undefined; destination_commit?: | { @@ -54,8 +54,8 @@ export const createBitbucketPipelinesRunAction: (options: { | undefined; variables?: | { - key: string; value: string; + key: string; secured: boolean; }[] | undefined; @@ -80,7 +80,7 @@ export function createPublishBitbucketCloudAction(options: { repoUrl: string; description?: string | undefined; defaultBranch?: string | undefined; - repoVisibility?: 'private' | 'public' | undefined; + repoVisibility?: 'public' | 'private' | undefined; gitCommitMessage?: string | undefined; sourcePath?: string | undefined; token?: string | undefined; diff --git a/plugins/scaffolder-backend-module-bitbucket-server/report.api.md b/plugins/scaffolder-backend-module-bitbucket-server/report.api.md index 929eb165c4..a52bee490e 100644 --- a/plugins/scaffolder-backend-module-bitbucket-server/report.api.md +++ b/plugins/scaffolder-backend-module-bitbucket-server/report.api.md @@ -20,7 +20,7 @@ export function createPublishBitbucketServerAction(options: { { repoUrl: string; description?: string | undefined; - repoVisibility?: 'private' | 'public' | undefined; + repoVisibility?: 'public' | 'private' | undefined; defaultBranch?: string | undefined; sourcePath?: string | undefined; enableLFS?: boolean | undefined; diff --git a/plugins/scaffolder-backend-module-gitea/report.api.md b/plugins/scaffolder-backend-module-gitea/report.api.md index afc8286365..8a0393abef 100644 --- a/plugins/scaffolder-backend-module-gitea/report.api.md +++ b/plugins/scaffolder-backend-module-gitea/report.api.md @@ -17,7 +17,7 @@ export function createPublishGiteaAction(options: { repoUrl: string; description: string; defaultBranch?: string | undefined; - repoVisibility?: 'private' | 'public' | undefined; + repoVisibility?: 'public' | 'private' | undefined; gitCommitMessage?: string | undefined; gitAuthorName?: string | undefined; gitAuthorEmail?: string | undefined; diff --git a/plugins/scaffolder-backend-module-github/report.api.md b/plugins/scaffolder-backend-module-github/report.api.md index 9e930a7866..3dbc72b57b 100644 --- a/plugins/scaffolder-backend-module-github/report.api.md +++ b/plugins/scaffolder-backend-module-github/report.api.md @@ -67,14 +67,14 @@ export function createGithubBranchProtectionAction(options: { bypassPullRequestAllowances?: | { apps?: string[] | undefined; - teams?: string[] | undefined; users?: string[] | undefined; + teams?: string[] | undefined; } | undefined; restrictions?: | { - teams: string[]; users: string[]; + teams: string[]; apps?: string[] | undefined; } | undefined; @@ -242,8 +242,8 @@ export function createGithubRepoCreateAction(options: { bypassPullRequestAllowances?: | { apps?: string[] | undefined; - teams?: string[] | undefined; users?: string[] | undefined; + teams?: string[] | undefined; } | undefined; collaborators?: @@ -279,7 +279,7 @@ export function createGithubRepoCreateAction(options: { protectDefaultBranch?: boolean | undefined; protectEnforceAdmins?: boolean | undefined; repoVariables?: Record | undefined; - repoVisibility?: 'internal' | 'private' | 'public' | undefined; + repoVisibility?: 'public' | 'internal' | 'private' | undefined; requireBranchesToBeUpToDate?: boolean | undefined; requireCodeOwnerReviews?: boolean | undefined; requiredApprovingReviewCount?: number | undefined; @@ -290,8 +290,8 @@ export function createGithubRepoCreateAction(options: { requireLastPushApproval?: boolean | undefined; restrictions?: | { - teams: string[]; users: string[]; + teams: string[]; apps?: string[] | undefined; } | undefined; @@ -306,7 +306,7 @@ export function createGithubRepoCreateAction(options: { subscribe?: boolean | undefined; token?: string | undefined; topics?: string[] | undefined; - workflowAccess?: 'none' | 'organization' | 'user' | undefined; + workflowAccess?: 'none' | 'user' | 'organization' | undefined; }, { remoteUrl: string; @@ -329,15 +329,15 @@ export function createGithubRepoPushAction(options: { bypassPullRequestAllowances?: | { apps?: string[] | undefined; - teams?: string[] | undefined; users?: string[] | undefined; + teams?: string[] | undefined; } | undefined; requiredApprovingReviewCount?: number | undefined; restrictions?: | { - teams: string[]; users: string[]; + teams: string[]; apps?: string[] | undefined; } | undefined; @@ -399,15 +399,15 @@ export function createPublishGithubAction(options: { bypassPullRequestAllowances?: | { apps?: string[] | undefined; - teams?: string[] | undefined; users?: string[] | undefined; + teams?: string[] | undefined; } | undefined; requiredApprovingReviewCount?: number | undefined; restrictions?: | { - teams: string[]; users: string[]; + teams: string[]; apps?: string[] | undefined; } | undefined; @@ -417,7 +417,7 @@ export function createPublishGithubAction(options: { requireBranchesToBeUpToDate?: boolean | undefined; requiredConversationResolution?: boolean | undefined; requireLastPushApproval?: boolean | undefined; - repoVisibility?: 'internal' | 'private' | 'public' | undefined; + repoVisibility?: 'public' | 'internal' | 'private' | undefined; defaultBranch?: string | undefined; protectDefaultBranch?: boolean | undefined; protectEnforceAdmins?: boolean | undefined; diff --git a/plugins/scaffolder-backend-module-gitlab/report.api.md b/plugins/scaffolder-backend-module-gitlab/report.api.md index cbe31b02f3..5f119024b7 100644 --- a/plugins/scaffolder-backend-module-gitlab/report.api.md +++ b/plugins/scaffolder-backend-module-gitlab/report.api.md @@ -154,7 +154,7 @@ export const createGitlabRepoPushAction: (options: { sourcePath?: string | undefined; targetPath?: string | undefined; token?: string | undefined; - commitAction?: 'auto' | 'update' | 'delete' | 'create' | undefined; + commitAction?: 'auto' | 'create' | 'update' | 'delete' | undefined; }, { projectid: string; @@ -193,7 +193,7 @@ export function createPublishGitlabAction(options: { }): TemplateAction< { repoUrl: string; - repoVisibility?: 'internal' | 'private' | 'public' | undefined; + repoVisibility?: 'public' | 'internal' | 'private' | undefined; defaultBranch?: string | undefined; gitCommitMessage?: string | undefined; gitAuthorName?: string | undefined; @@ -206,24 +206,24 @@ export function createPublishGitlabAction(options: { topics?: string[] | undefined; settings?: | { - visibility?: 'internal' | 'private' | 'public' | undefined; path?: string | undefined; description?: string | undefined; - merge_method?: 'merge' | 'rebase_merge' | 'ff' | undefined; + visibility?: 'public' | 'internal' | 'private' | undefined; topics?: string[] | undefined; + merge_method?: 'merge' | 'rebase_merge' | 'ff' | undefined; auto_devops_enabled?: boolean | undefined; - only_allow_merge_if_pipeline_succeeds?: boolean | undefined; - allow_merge_on_skipped_pipeline?: boolean | undefined; + ci_config_path?: string | undefined; + squash_option?: + | 'never' + | 'always' + | 'default_off' + | 'default_on' + | undefined; only_allow_merge_if_all_discussions_are_resolved?: | boolean | undefined; - squash_option?: - | 'always' - | 'never' - | 'default_on' - | 'default_off' - | undefined; - ci_config_path?: string | undefined; + only_allow_merge_if_pipeline_succeeds?: boolean | undefined; + allow_merge_on_skipped_pipeline?: boolean | undefined; } | undefined; branches?: @@ -236,15 +236,15 @@ export function createPublishGitlabAction(options: { | undefined; projectVariables?: | { - key: string; value: string; - raw?: boolean | undefined; + key: string; description?: string | undefined; protected?: boolean | undefined; + raw?: boolean | undefined; variable_type?: 'file' | 'env_var' | undefined; masked?: boolean | undefined; - environment_scope?: string | undefined; masked_and_hidden?: boolean | undefined; + environment_scope?: string | undefined; }[] | undefined; }, @@ -271,7 +271,7 @@ export const createPublishGitlabMergeRequestAction: (options: { sourcePath?: string | undefined; targetPath?: string | undefined; token?: string | undefined; - commitAction?: 'auto' | 'update' | 'delete' | 'create' | 'skip' | undefined; + commitAction?: 'auto' | 'create' | 'update' | 'delete' | 'skip' | undefined; projectid?: string | undefined; removeSourceBranch?: boolean | undefined; assignee?: string | undefined; diff --git a/plugins/scaffolder-backend-module-rails/report.api.md b/plugins/scaffolder-backend-module-rails/report.api.md index b09b75591b..8efc166c97 100644 --- a/plugins/scaffolder-backend-module-rails/report.api.md +++ b/plugins/scaffolder-backend-module-rails/report.api.md @@ -47,9 +47,8 @@ export function createFetchRailsAction(options: { values: { railsArguments?: | { - template?: string | undefined; api?: boolean | undefined; - force?: boolean | undefined; + template?: string | undefined; database?: | 'sqlite3' | 'mysql' @@ -61,6 +60,7 @@ export function createFetchRailsAction(options: { | 'jdbcpostgresql' | 'jdbc' | undefined; + force?: boolean | undefined; minimal?: boolean | undefined; railsVersion?: 'edge' | 'master' | 'dev' | 'fromImage' | undefined; skipActionCable?: boolean | undefined; diff --git a/plugins/scaffolder-backend/report.api.md b/plugins/scaffolder-backend/report.api.md index 8f9249cc5e..f203dd2faa 100644 --- a/plugins/scaffolder-backend/report.api.md +++ b/plugins/scaffolder-backend/report.api.md @@ -217,8 +217,8 @@ export const createFilesystemReadDirAction: () => TemplateAction< export const createFilesystemRenameAction: () => TemplateAction< { files: { - from: string; to: string; + from: string; overwrite?: boolean | undefined; }[]; }, diff --git a/plugins/scaffolder-react/report-alpha.api.md b/plugins/scaffolder-react/report-alpha.api.md index 9e01257c5c..609debaca2 100644 --- a/plugins/scaffolder-react/report-alpha.api.md +++ b/plugins/scaffolder-react/report-alpha.api.md @@ -318,8 +318,8 @@ export const scaffolderReactTranslationRef: TranslationRef< readonly 'stepper.reviewButtonText': 'Review'; readonly 'stepper.stepIndexLabel': 'Step {{index, number}}'; readonly 'passwordWidget.content': 'This widget is insecure. Please use [`ui:field: Secret`](https://backstage.io/docs/features/software-templates/writing-templates/#using-secrets) instead of `ui:widget: password`'; - readonly 'scaffolderPageContextMenu.createLabel': 'Create'; readonly 'scaffolderPageContextMenu.moreLabel': 'more'; + readonly 'scaffolderPageContextMenu.createLabel': 'Create'; readonly 'scaffolderPageContextMenu.editorLabel': 'Manage Templates'; readonly 'scaffolderPageContextMenu.actionsLabel': 'Installed Actions'; readonly 'scaffolderPageContextMenu.tasksLabel': 'Task List'; diff --git a/plugins/scaffolder/report-alpha.api.md b/plugins/scaffolder/report-alpha.api.md index b2cd1bbcbe..87cb54d687 100644 --- a/plugins/scaffolder/report-alpha.api.md +++ b/plugins/scaffolder/report-alpha.api.md @@ -144,8 +144,8 @@ const _default: OverridableFrontendPlugin< }; configInput: { filter?: FilterPredicate | undefined; - label?: string | undefined; title?: string | undefined; + label?: string | undefined; }; output: | ExtensionDataRef< @@ -200,8 +200,8 @@ const _default: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - title?: string | undefined; path?: string | undefined; + title?: string | undefined; }; output: | ExtensionDataRef @@ -572,24 +572,24 @@ export const scaffolderTranslationRef: TranslationRef< readonly 'fields.repoOwnerPicker.title': 'Owner'; readonly 'fields.repoOwnerPicker.description': 'The owner of the repository'; readonly 'aboutCard.launchTemplate': 'Launch Template'; + readonly 'actionsPage.title': 'Installed actions'; + readonly 'actionsPage.action.output': 'Output'; + readonly 'actionsPage.action.input': 'Input'; + readonly 'actionsPage.action.examples': 'Examples'; readonly 'actionsPage.content.emptyState.title': 'No information to display'; readonly 'actionsPage.content.emptyState.description': 'There are no actions installed or there was an issue communicating with backend.'; readonly 'actionsPage.content.searchFieldPlaceholder': 'Search for an action'; - readonly 'actionsPage.title': 'Installed actions'; - readonly 'actionsPage.action.input': 'Input'; - readonly 'actionsPage.action.output': 'Output'; - readonly 'actionsPage.action.examples': 'Examples'; readonly 'actionsPage.subtitle': 'This is the collection of all installed actions'; readonly 'actionsPage.pageTitle': 'Create a New Component'; + readonly 'listTaskPage.title': 'List template tasks'; readonly 'listTaskPage.content.emptyState.title': 'No information to display'; readonly 'listTaskPage.content.emptyState.description': 'There are no tasks or there was an issue communicating with backend.'; - readonly 'listTaskPage.content.tableCell.template': 'Template'; + readonly 'listTaskPage.content.tableTitle': 'Tasks'; readonly 'listTaskPage.content.tableCell.status': 'Status'; + readonly 'listTaskPage.content.tableCell.template': 'Template'; readonly 'listTaskPage.content.tableCell.owner': 'Owner'; readonly 'listTaskPage.content.tableCell.created': 'Created'; readonly 'listTaskPage.content.tableCell.taskID': 'Task ID'; - readonly 'listTaskPage.content.tableTitle': 'Tasks'; - readonly 'listTaskPage.title': 'List template tasks'; readonly 'listTaskPage.subtitle': 'All tasks that have been started'; readonly 'listTaskPage.pageTitle': 'Templates Tasks'; readonly 'ownerListPicker.title': 'Task Owner'; @@ -614,28 +614,28 @@ export const scaffolderTranslationRef: TranslationRef< readonly 'templateEditorForm.stepper.emptyText': 'There are no spec parameters in the template to preview.'; readonly 'renderSchema.undefined': 'No schema defined'; readonly 'renderSchema.tableCell.name': 'Name'; - readonly 'renderSchema.tableCell.type': 'Type'; readonly 'renderSchema.tableCell.title': 'Title'; readonly 'renderSchema.tableCell.description': 'Description'; + readonly 'renderSchema.tableCell.type': 'Type'; + readonly 'templatingExtensions.title': 'Templating Extensions'; readonly 'templatingExtensions.content.values.title': 'Values'; readonly 'templatingExtensions.content.values.notAvailable': 'There are no global template values defined.'; readonly 'templatingExtensions.content.emptyState.title': 'No information to display'; readonly 'templatingExtensions.content.emptyState.description': 'There are no templating extensions available or there was an issue communicating with the backend.'; readonly 'templatingExtensions.content.filters.title': 'Filters'; - readonly 'templatingExtensions.content.filters.schema.input': 'Input'; readonly 'templatingExtensions.content.filters.schema.output': 'Output'; + readonly 'templatingExtensions.content.filters.schema.input': 'Input'; readonly 'templatingExtensions.content.filters.schema.arguments': 'Arguments'; readonly 'templatingExtensions.content.filters.examples': 'Examples'; readonly 'templatingExtensions.content.filters.notAvailable': 'There are no template filters defined.'; readonly 'templatingExtensions.content.filters.metadataAbsent': 'Filter metadata unavailable'; + readonly 'templatingExtensions.content.searchFieldPlaceholder': 'Search for an extension'; readonly 'templatingExtensions.content.functions.title': 'Functions'; readonly 'templatingExtensions.content.functions.schema.output': 'Output'; readonly 'templatingExtensions.content.functions.schema.arguments': 'Arguments'; readonly 'templatingExtensions.content.functions.examples': 'Examples'; readonly 'templatingExtensions.content.functions.notAvailable': 'There are no global template functions defined.'; readonly 'templatingExtensions.content.functions.metadataAbsent': 'Function metadata unavailable'; - readonly 'templatingExtensions.content.searchFieldPlaceholder': 'Search for an extension'; - readonly 'templatingExtensions.title': 'Templating Extensions'; readonly 'templatingExtensions.subtitle': 'This is the collection of available templating extensions'; readonly 'templatingExtensions.pageTitle': 'Templating Extensions'; readonly 'templateTypePicker.title': 'Categories'; @@ -699,12 +699,12 @@ export const scaffolderTranslationRef: TranslationRef< readonly 'templateEditorToolbar.addToCatalogDialogTitle': 'Publish changes'; readonly 'templateEditorToolbar.addToCatalogDialogContent.stepsIntroduction': 'Follow the instructions below to create or update a template:'; readonly 'templateEditorToolbar.addToCatalogDialogContent.stepsListItems': 'Save the template files in a local directory\nCreate a pull request to a new or existing git repository\nIf the template already exists, the changes will be reflected in the software catalog once the pull request gets merged\nBut if you are creating a new template, follow the documentation linked below to register the new template repository in software catalog'; - readonly 'templateEditorToolbar.addToCatalogDialogActions.documentationUrl': 'https://backstage.io/docs/features/software-templates/adding-templates/'; readonly 'templateEditorToolbar.addToCatalogDialogActions.documentationButton': 'Go to the documentation'; - readonly 'templateEditorToolbarFileMenu.button': 'File'; + readonly 'templateEditorToolbar.addToCatalogDialogActions.documentationUrl': 'https://backstage.io/docs/features/software-templates/adding-templates/'; readonly 'templateEditorToolbarFileMenu.options.openDirectory': 'Open template directory'; readonly 'templateEditorToolbarFileMenu.options.createDirectory': 'Create template directory'; readonly 'templateEditorToolbarFileMenu.options.closeEditor': 'Close template editor'; + readonly 'templateEditorToolbarFileMenu.button': 'File'; readonly 'templateEditorToolbarTemplatesMenu.button': 'Templates'; } >; diff --git a/plugins/search-backend-module-elasticsearch/report.api.md b/plugins/search-backend-module-elasticsearch/report.api.md index afe06dd45e..f90dc2c0d9 100644 --- a/plugins/search-backend-module-elasticsearch/report.api.md +++ b/plugins/search-backend-module-elasticsearch/report.api.md @@ -7,8 +7,8 @@ import { ApiResponse } from '@opensearch-project/opensearch'; import { ApiResponse as ApiResponse_2 } from '@elastic/elasticsearch'; import { BackendFeature } from '@backstage/backend-plugin-api'; import { BatchSearchEngineIndexer } from '@backstage/plugin-search-backend-node'; -import { BulkHelper } from '@elastic/elasticsearch/lib/Helpers'; -import { BulkStats } from '@elastic/elasticsearch/lib/Helpers'; +import { BulkHelper } from '@opensearch-project/opensearch/lib/Helpers.js'; +import { BulkStats } from '@opensearch-project/opensearch/lib/Helpers.js'; import { Config } from '@backstage/config'; import type { ConnectionOptions } from 'node:tls'; import { ExtensionPoint } from '@backstage/backend-plugin-api'; diff --git a/plugins/search/report-alpha.api.md b/plugins/search/report-alpha.api.md index e3f2d6108a..9a31942231 100644 --- a/plugins/search/report-alpha.api.md +++ b/plugins/search/report-alpha.api.md @@ -73,8 +73,8 @@ const _default: OverridableFrontendPlugin< }; configInput: { noTrack?: boolean | undefined; - title?: string | undefined; path?: string | undefined; + title?: string | undefined; }; output: | ExtensionDataRef @@ -242,8 +242,8 @@ export const searchPage: OverridableExtensionDefinition<{ }; configInput: { noTrack?: boolean | undefined; - title?: string | undefined; path?: string | undefined; + title?: string | undefined; }; output: | ExtensionDataRef diff --git a/plugins/techdocs/report-alpha.api.md b/plugins/techdocs/report-alpha.api.md index aa14098288..dc3b144665 100644 --- a/plugins/techdocs/report-alpha.api.md +++ b/plugins/techdocs/report-alpha.api.md @@ -133,10 +133,10 @@ const _default: OverridableFrontendPlugin< }; configInput: { filter?: FilterPredicate | undefined; - title?: string | undefined; path?: string | undefined; - group?: string | false | undefined; + title?: string | undefined; icon?: string | undefined; + group?: string | false | undefined; }; output: | ExtensionDataRef @@ -230,8 +230,8 @@ const _default: OverridableFrontendPlugin< }; configInput: { filter?: FilterPredicate | undefined; - label?: string | undefined; title?: string | undefined; + label?: string | undefined; }; output: | ExtensionDataRef< @@ -288,8 +288,8 @@ const _default: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - title?: string | undefined; path?: string | undefined; + title?: string | undefined; }; output: | ExtensionDataRef @@ -366,8 +366,8 @@ const _default: OverridableFrontendPlugin< configInput: { withoutSearch?: boolean | undefined; withoutHeader?: boolean | undefined; - title?: string | undefined; path?: string | undefined; + title?: string | undefined; }; output: | ExtensionDataRef diff --git a/plugins/user-settings/report-alpha.api.md b/plugins/user-settings/report-alpha.api.md index c99709d777..35f7f1a262 100644 --- a/plugins/user-settings/report-alpha.api.md +++ b/plugins/user-settings/report-alpha.api.md @@ -50,8 +50,8 @@ const _default: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - title?: string | undefined; path?: string | undefined; + title?: string | undefined; }; output: | ExtensionDataRef @@ -164,22 +164,22 @@ export const userSettingsTranslationRef: TranslationRef< readonly 'featureFlags.filterTitle': 'Filter'; readonly 'featureFlags.clearFilter': 'Clear filter'; readonly 'featureFlags.emptyFlags.title': 'No Feature Flags'; + readonly 'featureFlags.emptyFlags.description': 'Feature Flags make it possible for plugins to register features in Backstage for users to opt into. You can use this to split out logic in your code for manual A/B testing, etc.'; readonly 'featureFlags.emptyFlags.action.title': 'An example for how to add a feature flag is highlighted below:'; readonly 'featureFlags.emptyFlags.action.readMoreButtonTitle': 'Read More'; - readonly 'featureFlags.emptyFlags.description': 'Feature Flags make it possible for plugins to register features in Backstage for users to opt into. You can use this to split out logic in your code for manual A/B testing, etc.'; readonly 'featureFlags.flagItem.title.disable': 'Disable'; readonly 'featureFlags.flagItem.title.enable': 'Enable'; readonly 'featureFlags.flagItem.subtitle.registeredInApplication': 'Registered in the application'; readonly 'featureFlags.flagItem.subtitle.registeredInPlugin': 'Registered in {{pluginId}} plugin'; - readonly 'languageToggle.select': 'Select language {{language}}'; readonly 'languageToggle.title': 'Language'; readonly 'languageToggle.description': 'Change the language'; - readonly 'themeToggle.select': 'Select {{theme}}'; + readonly 'languageToggle.select': 'Select language {{language}}'; readonly 'themeToggle.title': 'Theme'; readonly 'themeToggle.description': 'Change the theme mode'; + readonly 'themeToggle.select': 'Select {{theme}}'; readonly 'themeToggle.names.auto': 'Auto'; - readonly 'themeToggle.names.dark': 'Dark'; readonly 'themeToggle.names.light': 'Light'; + readonly 'themeToggle.names.dark': 'Dark'; readonly 'themeToggle.selectAuto': 'Select Auto Theme'; readonly 'signOutMenu.title': 'Sign Out'; readonly 'signOutMenu.moreIconTitle': 'more'; @@ -194,9 +194,9 @@ export const userSettingsTranslationRef: TranslationRef< readonly 'identityCard.ownershipEntities': 'Ownership Entities'; readonly 'defaultProviderSettings.description': 'Provides authentication towards {{provider}} APIs and identities'; readonly 'emptyProviders.title': 'No Authentication Providers'; + readonly 'emptyProviders.description': 'You can add Authentication Providers to Backstage which allows you to use these providers to authenticate yourself.'; readonly 'emptyProviders.action.title': 'Open app-config.yaml and make the changes as highlighted below:'; readonly 'emptyProviders.action.readMoreButtonTitle': 'Read More'; - readonly 'emptyProviders.description': 'You can add Authentication Providers to Backstage which allows you to use these providers to authenticate yourself.'; readonly 'providerSettingsItem.title.signOut': 'Sign out from {{title}}'; readonly 'providerSettingsItem.title.signIn': 'Sign in to {{title}}'; readonly 'providerSettingsItem.buttonTitle.signOut': 'Sign out'; From e8d410d9159104d4b6b2b79de104f24883d1a025 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Mar 2026 17:49:36 +0100 Subject: [PATCH 05/13] Regenerate API reports Signed-off-by: Patrik Oldsberg Made-with: Cursor --- packages/app-example-plugin/report.api.md | 2 +- packages/cli-defaults/report.api.md | 4 +- packages/core-components/report-alpha.api.md | 4 +- packages/frontend-plugin-api/report.api.md | 4 +- plugins/api-docs/report-alpha.api.md | 34 +++++------ plugins/app-visualizer/report.api.md | 8 +-- plugins/app/report.api.md | 4 +- plugins/auth/report.api.md | 2 +- plugins/catalog-graph/report-alpha.api.md | 14 ++--- plugins/catalog-import/report-alpha.api.md | 10 ++-- plugins/catalog-react/report-alpha.api.md | 30 +++++----- .../report-alpha.api.md | 4 +- plugins/catalog/report-alpha.api.md | 58 +++++++++---------- plugins/catalog/report.api.md | 2 +- plugins/devtools-react/report.api.md | 2 +- plugins/devtools/report-alpha.api.md | 2 +- plugins/home/report-alpha.api.md | 4 +- plugins/kubernetes-react/report-alpha.api.md | 8 +-- plugins/kubernetes/report-alpha.api.md | 6 +- plugins/mui-to-bui/report.api.md | 2 +- plugins/notifications/report-alpha.api.md | 14 ++--- plugins/org/report-alpha.api.md | 16 ++--- .../report.api.md | 20 +++---- .../report.api.md | 2 +- .../report.api.md | 2 +- .../report.api.md | 22 +++---- .../report.api.md | 34 +++++------ .../report.api.md | 4 +- plugins/scaffolder-backend/report.api.md | 2 +- plugins/scaffolder-react/report-alpha.api.md | 2 +- plugins/scaffolder/report-alpha.api.md | 30 +++++----- .../report.api.md | 4 +- plugins/search/report-alpha.api.md | 4 +- plugins/techdocs/report-alpha.api.md | 10 ++-- plugins/user-settings/report-alpha.api.md | 12 ++-- 35 files changed, 192 insertions(+), 190 deletions(-) diff --git a/packages/app-example-plugin/report.api.md b/packages/app-example-plugin/report.api.md index 0879f318aa..432174da68 100644 --- a/packages/app-example-plugin/report.api.md +++ b/packages/app-example-plugin/report.api.md @@ -27,8 +27,8 @@ const examplePlugin: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - path?: string | undefined; title?: string | undefined; + path?: string | undefined; }; output: | ExtensionDataRef diff --git a/packages/cli-defaults/report.api.md b/packages/cli-defaults/report.api.md index 1a40836eaa..573f8ee454 100644 --- a/packages/cli-defaults/report.api.md +++ b/packages/cli-defaults/report.api.md @@ -3,8 +3,10 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { CliModule } from '@backstage/cli-node'; + // @public -const _default: any[]; +const _default: CliModule[]; export default _default; // (No @packageDocumentation comment for this package) diff --git a/packages/core-components/report-alpha.api.md b/packages/core-components/report-alpha.api.md index 7b7f514dcf..f373dd56ff 100644 --- a/packages/core-components/report-alpha.api.md +++ b/packages/core-components/report-alpha.api.md @@ -12,8 +12,8 @@ export const coreComponentsTranslationRef: TranslationRef< readonly 'table.filter.title': 'Filters'; readonly 'table.filter.placeholder': 'All results'; readonly 'table.filter.clearAll': 'Clear all'; - readonly 'table.header.actions': 'Actions'; readonly 'table.body.emptyDataSourceMessage': 'No records to display'; + readonly 'table.header.actions': 'Actions'; readonly 'table.toolbar.search': 'Filter'; readonly 'table.pagination.labelDisplayedRows': '{from}-{to} of {count}'; readonly 'table.pagination.firstTooltip': 'First Page'; @@ -37,9 +37,9 @@ export const coreComponentsTranslationRef: TranslationRef< readonly 'signIn.guestProvider.subtitle': 'Enter as a Guest User.\n You will not have a verified identity, meaning some features might be unavailable.'; readonly skipToContent: 'Skip to content'; readonly 'copyTextButton.tooltipText': 'Text copied to clipboard'; + readonly 'simpleStepper.finish': 'Finish'; readonly 'simpleStepper.reset': 'Reset'; readonly 'simpleStepper.next': 'Next'; - readonly 'simpleStepper.finish': 'Finish'; readonly 'simpleStepper.skip': 'Skip'; readonly 'simpleStepper.back': 'Back'; readonly 'errorPage.title': 'Looks like someone dropped the mic!'; diff --git a/packages/frontend-plugin-api/report.api.md b/packages/frontend-plugin-api/report.api.md index 72f22b4093..f17ca670ea 100644 --- a/packages/frontend-plugin-api/report.api.md +++ b/packages/frontend-plugin-api/report.api.md @@ -1792,8 +1792,8 @@ export const PageBlueprint: ExtensionBlueprint_2<{ title: string | undefined; }; configInput: { - path?: string | undefined; title?: string | undefined; + path?: string | undefined; }; dataRefs: never; }>; @@ -2104,8 +2104,8 @@ export const SubPageBlueprint: ExtensionBlueprint_2<{ title: string | undefined; }; configInput: { - path?: string | undefined; title?: string | undefined; + path?: string | undefined; }; dataRefs: never; }>; diff --git a/plugins/api-docs/report-alpha.api.md b/plugins/api-docs/report-alpha.api.md index 434cc38691..0ee7ac5460 100644 --- a/plugins/api-docs/report-alpha.api.md +++ b/plugins/api-docs/report-alpha.api.md @@ -91,11 +91,11 @@ const _default: OverridableFrontendPlugin< name: 'consumed-apis'; config: { filter: FilterPredicate | undefined; - type: 'info' | 'content' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'info' | 'content' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -132,11 +132,11 @@ const _default: OverridableFrontendPlugin< name: 'consuming-components'; config: { filter: FilterPredicate | undefined; - type: 'info' | 'content' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'info' | 'content' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -173,11 +173,11 @@ const _default: OverridableFrontendPlugin< name: 'definition'; config: { filter: FilterPredicate | undefined; - type: 'info' | 'content' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'info' | 'content' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -214,11 +214,11 @@ const _default: OverridableFrontendPlugin< name: 'has-apis'; config: { filter: FilterPredicate | undefined; - type: 'info' | 'content' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'info' | 'content' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -255,11 +255,11 @@ const _default: OverridableFrontendPlugin< name: 'provided-apis'; config: { filter: FilterPredicate | undefined; - type: 'info' | 'content' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'info' | 'content' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -296,11 +296,11 @@ const _default: OverridableFrontendPlugin< name: 'providing-components'; config: { filter: FilterPredicate | undefined; - type: 'info' | 'content' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'info' | 'content' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -344,10 +344,10 @@ const _default: OverridableFrontendPlugin< }; configInput: { filter?: FilterPredicate | undefined; - path?: string | undefined; title?: string | undefined; - icon?: string | undefined; + path?: string | undefined; group?: string | false | undefined; + icon?: string | undefined; }; output: | ExtensionDataRef @@ -414,10 +414,10 @@ const _default: OverridableFrontendPlugin< }; configInput: { filter?: FilterPredicate | undefined; - path?: string | undefined; title?: string | undefined; - icon?: string | undefined; + path?: string | undefined; group?: string | false | undefined; + icon?: string | undefined; }; output: | ExtensionDataRef @@ -501,8 +501,8 @@ const _default: OverridableFrontendPlugin< }; configInput: { initiallySelectedFilter?: 'all' | 'owned' | 'starred' | undefined; - path?: string | undefined; title?: string | undefined; + path?: string | undefined; }; output: | ExtensionDataRef diff --git a/plugins/app-visualizer/report.api.md b/plugins/app-visualizer/report.api.md index 2550026e98..9ee06eccb0 100644 --- a/plugins/app-visualizer/report.api.md +++ b/plugins/app-visualizer/report.api.md @@ -49,8 +49,8 @@ const visualizerPlugin: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - path?: string | undefined; title?: string | undefined; + path?: string | undefined; }; output: | ExtensionDataRef @@ -138,8 +138,8 @@ const visualizerPlugin: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - path?: string | undefined; title?: string | undefined; + path?: string | undefined; }; output: | ExtensionDataRef @@ -176,8 +176,8 @@ const visualizerPlugin: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - path?: string | undefined; title?: string | undefined; + path?: string | undefined; }; output: | ExtensionDataRef @@ -214,8 +214,8 @@ const visualizerPlugin: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - path?: string | undefined; title?: string | undefined; + path?: string | undefined; }; output: | ExtensionDataRef diff --git a/plugins/app/report.api.md b/plugins/app/report.api.md index b6b23a0d3b..0262c4c1ef 100644 --- a/plugins/app/report.api.md +++ b/plugins/app/report.api.md @@ -775,14 +775,14 @@ const appPlugin: OverridableFrontendPlugin< transientTimeoutMs: number; anchorOrigin: { horizontal: 'center' | 'left' | 'right'; - vertical: 'bottom' | 'top'; + vertical: 'top' | 'bottom'; }; }; configInput: { anchorOrigin?: | { horizontal?: 'center' | 'left' | 'right' | undefined; - vertical?: 'bottom' | 'top' | undefined; + vertical?: 'top' | 'bottom' | undefined; } | undefined; transientTimeoutMs?: number | undefined; diff --git a/plugins/auth/report.api.md b/plugins/auth/report.api.md index 903b8397c9..8e8ac71d31 100644 --- a/plugins/auth/report.api.md +++ b/plugins/auth/report.api.md @@ -28,8 +28,8 @@ const _default: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - path?: string | undefined; title?: string | undefined; + path?: string | undefined; }; output: | ExtensionDataRef diff --git a/plugins/catalog-graph/report-alpha.api.md b/plugins/catalog-graph/report-alpha.api.md index e1497f7623..f9d4542625 100644 --- a/plugins/catalog-graph/report-alpha.api.md +++ b/plugins/catalog-graph/report-alpha.api.md @@ -95,14 +95,14 @@ const _default: OverridableFrontendPlugin< title: string | undefined; height: number | undefined; filter: FilterPredicate | undefined; - type: 'info' | 'content' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { - title?: string | undefined; height?: number | undefined; + curve?: 'curveStepBefore' | 'curveMonotoneX' | undefined; direction?: 'TB' | 'BT' | 'LR' | 'RL' | undefined; zoom?: 'disabled' | 'enabled' | 'enable-on-click' | undefined; - curve?: 'curveStepBefore' | 'curveMonotoneX' | undefined; + title?: string | undefined; relations?: string[] | undefined; maxDepth?: number | undefined; kinds?: string[] | undefined; @@ -110,7 +110,7 @@ const _default: OverridableFrontendPlugin< relationPairs?: [string, string][] | undefined; unidirectional?: boolean | undefined; filter?: FilterPredicate | undefined; - type?: 'info' | 'content' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -163,12 +163,12 @@ const _default: OverridableFrontendPlugin< title: string | undefined; }; configInput: { + curve?: 'curveStepBefore' | 'curveMonotoneX' | undefined; direction?: 'TB' | 'BT' | 'LR' | 'RL' | undefined; zoom?: 'disabled' | 'enabled' | 'enable-on-click' | undefined; - curve?: 'curveStepBefore' | 'curveMonotoneX' | undefined; relations?: string[] | undefined; - rootEntityRefs?: string[] | undefined; maxDepth?: number | undefined; + rootEntityRefs?: string[] | undefined; kinds?: string[] | undefined; mergeRelations?: boolean | undefined; relationPairs?: [string, string][] | undefined; @@ -176,8 +176,8 @@ const _default: OverridableFrontendPlugin< selectedRelations?: string[] | undefined; selectedKinds?: string[] | undefined; showFilters?: boolean | undefined; - path?: string | undefined; title?: string | undefined; + path?: string | undefined; }; output: | ExtensionDataRef diff --git a/plugins/catalog-import/report-alpha.api.md b/plugins/catalog-import/report-alpha.api.md index 70799ed325..b58b641050 100644 --- a/plugins/catalog-import/report-alpha.api.md +++ b/plugins/catalog-import/report-alpha.api.md @@ -34,8 +34,8 @@ export const catalogImportTranslationRef: TranslationRef< readonly 'importInfoCard.fileLinkDescription': 'The wizard analyzes the file, previews the entities, and adds them to the {{appTitle}} catalog.'; readonly 'importInfoCard.exampleDescription': 'The wizard discovers all {{catalogFilename}} files in the repository, previews the entities, and adds them to the {{appTitle}} catalog.'; readonly 'importInfoCard.preparePullRequestDescription': 'If no entities are found, the wizard will prepare a Pull Request that adds an example {{catalogFilename}} and prepares the {{appTitle}} catalog to load all entities as soon as the Pull Request is merged.'; - readonly 'importInfoCard.githubIntegration.title': 'Link to a repository'; readonly 'importInfoCard.githubIntegration.label': 'GitHub only'; + readonly 'importInfoCard.githubIntegration.title': 'Link to a repository'; readonly 'importStepper.finish.title': 'Finish'; readonly 'importStepper.singleLocation.title': 'Select Locations'; readonly 'importStepper.singleLocation.description': 'Discovered Locations: 1'; @@ -62,8 +62,8 @@ export const catalogImportTranslationRef: TranslationRef< readonly 'importStepper.review.title': 'Review'; readonly 'stepFinishImportLocation.repository.title': 'The following Pull Request has been opened: '; readonly 'stepFinishImportLocation.repository.description': 'Your entities will be imported as soon as the Pull Request is merged.'; - readonly 'stepFinishImportLocation.locations.backButtonText': 'Register another'; readonly 'stepFinishImportLocation.locations.new': 'The following entities have been added to the catalog:'; + readonly 'stepFinishImportLocation.locations.backButtonText': 'Register another'; readonly 'stepFinishImportLocation.locations.existing': 'A refresh was triggered for the following locations:'; readonly 'stepFinishImportLocation.locations.viewButtonText': 'View Component'; readonly 'stepFinishImportLocation.backButtonText': 'Register another'; @@ -83,9 +83,9 @@ export const catalogImportTranslationRef: TranslationRef< readonly 'stepPrepareSelectLocations.nextButtonText': 'Review'; readonly 'stepPrepareSelectLocations.existingLocations.description': 'These locations already exist in the catalog:'; readonly 'stepReviewLocation.refresh': 'Refresh'; - readonly 'stepReviewLocation.catalog.exists': 'The following locations already exist in the catalog:'; - readonly 'stepReviewLocation.catalog.new': 'The following entities will be added to the catalog:'; readonly 'stepReviewLocation.import': 'Import'; + readonly 'stepReviewLocation.catalog.new': 'The following entities will be added to the catalog:'; + readonly 'stepReviewLocation.catalog.exists': 'The following locations already exist in the catalog:'; readonly 'stepReviewLocation.prepareResult.title': 'The following Pull Request has been opened: '; readonly 'stepReviewLocation.prepareResult.description': 'You can already import the location and {{appTitle}} will fetch the entities as soon as the Pull Request is merged.'; } @@ -121,8 +121,8 @@ const _default: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - path?: string | undefined; title?: string | undefined; + path?: string | undefined; }; output: | ExtensionDataRef diff --git a/plugins/catalog-react/report-alpha.api.md b/plugins/catalog-react/report-alpha.api.md index ee0b8bb3ff..9c76a221dc 100644 --- a/plugins/catalog-react/report-alpha.api.md +++ b/plugins/catalog-react/report-alpha.api.md @@ -73,17 +73,17 @@ export const catalogReactTranslationRef: TranslationRef< readonly 'inspectEntityDialog.jsonPage.title': 'Entity as JSON'; readonly 'inspectEntityDialog.jsonPage.description': 'This is the raw entity data as received from the catalog, on JSON form.'; readonly 'inspectEntityDialog.overviewPage.title': 'Overview'; + readonly 'inspectEntityDialog.overviewPage.metadata.title': 'Metadata'; + readonly 'inspectEntityDialog.overviewPage.labels': 'Labels'; readonly 'inspectEntityDialog.overviewPage.status.title': 'Status'; readonly 'inspectEntityDialog.overviewPage.identity.title': 'Identity'; - readonly 'inspectEntityDialog.overviewPage.metadata.title': 'Metadata'; readonly 'inspectEntityDialog.overviewPage.annotations': 'Annotations'; readonly 'inspectEntityDialog.overviewPage.tags': 'Tags'; - readonly 'inspectEntityDialog.overviewPage.labels': 'Labels'; readonly 'inspectEntityDialog.overviewPage.relation.title': 'Relations'; readonly 'inspectEntityDialog.yamlPage.title': 'Entity as YAML'; readonly 'inspectEntityDialog.yamlPage.description': 'This is the raw entity data as received from the catalog, on YAML form.'; - readonly 'inspectEntityDialog.tabNames.yaml': 'Raw YAML'; readonly 'inspectEntityDialog.tabNames.json': 'Raw JSON'; + readonly 'inspectEntityDialog.tabNames.yaml': 'Raw YAML'; readonly 'inspectEntityDialog.tabNames.overview': 'Overview'; readonly 'inspectEntityDialog.tabNames.ancestry': 'Ancestry'; readonly 'inspectEntityDialog.tabNames.colocated': 'Colocated'; @@ -108,17 +108,17 @@ export const catalogReactTranslationRef: TranslationRef< readonly 'userListPicker.personalFilter.ownedLabel': 'Owned'; readonly 'userListPicker.personalFilter.starredLabel': 'Starred'; readonly 'entityTableColumnTitle.name': 'Name'; - readonly 'entityTableColumnTitle.namespace': 'Namespace'; - readonly 'entityTableColumnTitle.title': 'Title'; - readonly 'entityTableColumnTitle.description': 'Description'; readonly 'entityTableColumnTitle.type': 'Type'; readonly 'entityTableColumnTitle.label': 'Label'; + readonly 'entityTableColumnTitle.title': 'Title'; + readonly 'entityTableColumnTitle.description': 'Description'; + readonly 'entityTableColumnTitle.system': 'System'; + readonly 'entityTableColumnTitle.namespace': 'Namespace'; + readonly 'entityTableColumnTitle.domain': 'Domain'; readonly 'entityTableColumnTitle.tags': 'Tags'; readonly 'entityTableColumnTitle.owner': 'Owner'; readonly 'entityTableColumnTitle.lifecycle': 'Lifecycle'; - readonly 'entityTableColumnTitle.system': 'System'; readonly 'entityTableColumnTitle.targets': 'Targets'; - readonly 'entityTableColumnTitle.domain': 'Domain'; readonly 'missingAnnotationEmptyState.title': 'Missing Annotation'; readonly 'missingAnnotationEmptyState.readMore': 'Read more'; readonly 'missingAnnotationEmptyState.annotationYaml': 'Add the annotation to your {{entityKind}} YAML as shown in the highlighted example below:'; @@ -213,11 +213,11 @@ export const EntityCardBlueprint: ExtensionBlueprint<{ inputs: {}; config: { filter: FilterPredicate | undefined; - type: 'info' | 'content' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'info' | 'content' | undefined; + type?: 'content' | 'info' | undefined; }; dataRefs: { filterFunction: ConfigurableExtensionDataRef< @@ -305,10 +305,10 @@ export const EntityContentBlueprint: ExtensionBlueprint<{ }; configInput: { filter?: FilterPredicate | undefined; - path?: string | undefined; title?: string | undefined; - icon?: string | undefined; + path?: string | undefined; group?: string | false | undefined; + icon?: string | undefined; }; dataRefs: { title: ConfigurableExtensionDataRef< @@ -535,8 +535,8 @@ export const EntityIconLinkBlueprint: ExtensionBlueprint<{ }; configInput: { filter?: FilterPredicate | undefined; - title?: string | undefined; label?: string | undefined; + title?: string | undefined; }; dataRefs: { useProps: ConfigurableExtensionDataRef< @@ -561,8 +561,9 @@ export const EntityIconLinkBlueprint: ExtensionBlueprint<{ export const EntityTableColumnTitle: ( input: EntityTableColumnTitleProps, ) => - | 'Domain' | 'System' + | 'Title' + | 'Domain' | 'Lifecycle' | 'Namespace' | 'Owner' @@ -571,7 +572,6 @@ export const EntityTableColumnTitle: ( | 'Name' | 'Description' | 'Targets' - | 'Title' | 'Label'; // @alpha (undocumented) diff --git a/plugins/catalog-unprocessed-entities/report-alpha.api.md b/plugins/catalog-unprocessed-entities/report-alpha.api.md index 2d254d15ac..7408831f87 100644 --- a/plugins/catalog-unprocessed-entities/report-alpha.api.md +++ b/plugins/catalog-unprocessed-entities/report-alpha.api.md @@ -70,8 +70,8 @@ const _default: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - path?: string | undefined; title?: string | undefined; + path?: string | undefined; }; output: | ExtensionDataRef @@ -151,8 +151,8 @@ export const unprocessedEntitiesDevToolsContent: OverridableExtensionDefinition< title: string | undefined; }; configInput: { - path?: string | undefined; title?: string | undefined; + path?: string | undefined; }; output: | ExtensionDataRef diff --git a/plugins/catalog/report-alpha.api.md b/plugins/catalog/report-alpha.api.md index d77b673744..a0b092a453 100644 --- a/plugins/catalog/report-alpha.api.md +++ b/plugins/catalog/report-alpha.api.md @@ -46,8 +46,8 @@ export const catalogTranslationRef: TranslationRef< readonly 'indexPage.supportButtonContent': 'All your software catalog entities'; readonly 'entityPage.notFoundMessage': 'There is no {{kind}} with the requested {{link}}.'; readonly 'entityPage.notFoundLinkText': 'kind, namespace, and name'; - readonly 'aboutCard.unknown': 'unknown'; readonly 'aboutCard.title': 'About'; + readonly 'aboutCard.unknown': 'unknown'; readonly 'aboutCard.refreshButtonTitle': 'Schedule entity refresh'; readonly 'aboutCard.editButtonTitle': 'Edit Metadata'; readonly 'aboutCard.editButtonAriaLabel': 'Edit'; @@ -72,8 +72,8 @@ export const catalogTranslationRef: TranslationRef< readonly 'aboutCard.tagsField.value': 'No Tags'; readonly 'aboutCard.tagsField.label': 'Tags'; readonly 'aboutCard.targetsField.label': 'Targets'; - readonly 'searchResultItem.kind': 'Kind'; readonly 'searchResultItem.type': 'Type'; + readonly 'searchResultItem.kind': 'Kind'; readonly 'searchResultItem.owner': 'Owner'; readonly 'searchResultItem.lifecycle': 'Lifecycle'; readonly 'catalogTable.allFilters': 'All'; @@ -308,11 +308,11 @@ const _default: OverridableFrontendPlugin< 'entity-card:catalog/about': OverridableExtensionDefinition<{ config: { filter: FilterPredicate | undefined; - type: 'info' | 'content' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'info' | 'content' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -378,11 +378,11 @@ const _default: OverridableFrontendPlugin< name: 'depends-on-components'; config: { filter: FilterPredicate | undefined; - type: 'info' | 'content' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'info' | 'content' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -419,11 +419,11 @@ const _default: OverridableFrontendPlugin< name: 'depends-on-resources'; config: { filter: FilterPredicate | undefined; - type: 'info' | 'content' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'info' | 'content' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -460,11 +460,11 @@ const _default: OverridableFrontendPlugin< name: 'has-components'; config: { filter: FilterPredicate | undefined; - type: 'info' | 'content' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'info' | 'content' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -501,11 +501,11 @@ const _default: OverridableFrontendPlugin< name: 'has-resources'; config: { filter: FilterPredicate | undefined; - type: 'info' | 'content' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'info' | 'content' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -542,11 +542,11 @@ const _default: OverridableFrontendPlugin< name: 'has-subcomponents'; config: { filter: FilterPredicate | undefined; - type: 'info' | 'content' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'info' | 'content' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -583,11 +583,11 @@ const _default: OverridableFrontendPlugin< name: 'has-subdomains'; config: { filter: FilterPredicate | undefined; - type: 'info' | 'content' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'info' | 'content' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -624,11 +624,11 @@ const _default: OverridableFrontendPlugin< name: 'has-systems'; config: { filter: FilterPredicate | undefined; - type: 'info' | 'content' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'info' | 'content' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -665,11 +665,11 @@ const _default: OverridableFrontendPlugin< name: 'labels'; config: { filter: FilterPredicate | undefined; - type: 'info' | 'content' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'info' | 'content' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -706,11 +706,11 @@ const _default: OverridableFrontendPlugin< name: 'links'; config: { filter: FilterPredicate | undefined; - type: 'info' | 'content' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'info' | 'content' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -752,10 +752,10 @@ const _default: OverridableFrontendPlugin< }; configInput: { filter?: FilterPredicate | undefined; - path?: string | undefined; title?: string | undefined; - icon?: string | undefined; + path?: string | undefined; group?: string | false | undefined; + icon?: string | undefined; }; output: | ExtensionDataRef @@ -941,8 +941,8 @@ const _default: OverridableFrontendPlugin< }; configInput: { filter?: FilterPredicate | undefined; - title?: string | undefined; label?: string | undefined; + title?: string | undefined; }; output: | ExtensionDataRef< @@ -996,7 +996,7 @@ const _default: OverridableFrontendPlugin< pagination: | boolean | { - mode: 'cursor' | 'offset'; + mode: 'offset' | 'cursor'; offset?: number | undefined; limit?: number | undefined; }; @@ -1007,13 +1007,13 @@ const _default: OverridableFrontendPlugin< pagination?: | boolean | { - mode: 'cursor' | 'offset'; + mode: 'offset' | 'cursor'; offset?: number | undefined; limit?: number | undefined; } | undefined; - path?: string | undefined; title?: string | undefined; + path?: string | undefined; }; output: | ExtensionDataRef @@ -1122,8 +1122,8 @@ const _default: OverridableFrontendPlugin< | undefined; defaultContentOrder?: 'title' | 'natural' | undefined; showNavItemIcons?: boolean | undefined; - path?: string | undefined; title?: string | undefined; + path?: string | undefined; }; output: | ExtensionDataRef diff --git a/plugins/catalog/report.api.md b/plugins/catalog/report.api.md index 6d482004bf..48e3f53de2 100644 --- a/plugins/catalog/report.api.md +++ b/plugins/catalog/report.api.md @@ -455,7 +455,7 @@ export function EntityRelationWarning(): JSX_2.Element | null; // @public (undocumented) export const EntitySwitch: { - (props: EntitySwitchProps): JSX_2.Element; + (props: EntitySwitchProps): JSX.Element; Case: (_props: EntitySwitchCaseProps) => null; }; diff --git a/plugins/devtools-react/report.api.md b/plugins/devtools-react/report.api.md index 5fb187ee6a..6916afed84 100644 --- a/plugins/devtools-react/report.api.md +++ b/plugins/devtools-react/report.api.md @@ -30,8 +30,8 @@ export const DevToolsContentBlueprint: ExtensionBlueprint<{ title: string | undefined; }; configInput: { - path?: string | undefined; title?: string | undefined; + path?: string | undefined; }; dataRefs: never; }>; diff --git a/plugins/devtools/report-alpha.api.md b/plugins/devtools/report-alpha.api.md index 7be1867d5d..753875eaaa 100644 --- a/plugins/devtools/report-alpha.api.md +++ b/plugins/devtools/report-alpha.api.md @@ -67,8 +67,8 @@ const _default: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - path?: string | undefined; title?: string | undefined; + path?: string | undefined; }; output: | ExtensionDataRef diff --git a/plugins/home/report-alpha.api.md b/plugins/home/report-alpha.api.md index e1cc4f8f62..0269f471fe 100644 --- a/plugins/home/report-alpha.api.md +++ b/plugins/home/report-alpha.api.md @@ -108,8 +108,8 @@ const _default: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - path?: string | undefined; title?: string | undefined; + path?: string | undefined; }; output: | ExtensionDataRef @@ -224,9 +224,9 @@ export const homeTranslationRef: TranslationRef< readonly 'widgetSettingsOverlay.deleteWidgetTooltip': 'Delete widget'; readonly 'widgetSettingsOverlay.submitButtonTitle': 'Submit'; readonly 'starredEntityListItem.removeFavoriteEntityTitle': 'Remove entity from favorites'; - readonly 'visitList.few.title': 'The more pages you visit, the more pages will appear here.'; readonly 'visitList.empty.title': 'There are no visits to show yet.'; readonly 'visitList.empty.description': 'Once you start using Backstage, your visits will appear here as a quick link to carry on where you left off.'; + readonly 'visitList.few.title': 'The more pages you visit, the more pages will appear here.'; readonly 'quickStart.title': 'Onboarding'; readonly 'quickStart.description': 'Get started with Backstage'; readonly 'quickStart.learnMoreLinkTitle': 'Learn more'; diff --git a/plugins/kubernetes-react/report-alpha.api.md b/plugins/kubernetes-react/report-alpha.api.md index adb92a772b..f638bf6789 100644 --- a/plugins/kubernetes-react/report-alpha.api.md +++ b/plugins/kubernetes-react/report-alpha.api.md @@ -24,9 +24,6 @@ export const kubernetesReactTranslationRef: TranslationRef< readonly 'cluster.noPodsWithErrors': 'No pods with errors'; readonly 'pods.pods_one': '{{count}} pod'; readonly 'pods.pods_other': '{{count}} pods'; - readonly 'podsTable.unknown': 'unknown'; - readonly 'podsTable.status.running': 'Running'; - readonly 'podsTable.status.ok': 'OK'; readonly 'podsTable.columns.name': 'name'; readonly 'podsTable.columns.id': 'ID'; readonly 'podsTable.columns.status': 'status'; @@ -35,6 +32,9 @@ export const kubernetesReactTranslationRef: TranslationRef< readonly 'podsTable.columns.totalRestarts': 'total restarts'; readonly 'podsTable.columns.cpuUsage': 'CPU usage %'; readonly 'podsTable.columns.memoryUsage': 'Memory usage %'; + readonly 'podsTable.unknown': 'unknown'; + readonly 'podsTable.status.running': 'Running'; + readonly 'podsTable.status.ok': 'OK'; readonly 'errorPanel.message': 'There was a problem retrieving some Kubernetes resources for the entity: {{entityName}}. This could mean that the Error Reporting card is not completely accurate.'; readonly 'errorPanel.title': 'There was a problem retrieving Kubernetes objects'; readonly 'errorPanel.errorsLabel': 'Errors'; @@ -65,12 +65,12 @@ export const kubernetesReactTranslationRef: TranslationRef< readonly 'hpa.currentCpuUsageLabel': 'current CPU usage: {{value}}%'; readonly 'hpa.targetCpuUsage': 'target CPU usage:'; readonly 'hpa.targetCpuUsageLabel': 'target CPU usage: {{value}}%'; - readonly 'errorReporting.title': 'Error Reporting'; readonly 'errorReporting.columns.name': 'name'; readonly 'errorReporting.columns.kind': 'kind'; readonly 'errorReporting.columns.namespace': 'namespace'; readonly 'errorReporting.columns.messages': 'messages'; readonly 'errorReporting.columns.cluster': 'cluster'; + readonly 'errorReporting.title': 'Error Reporting'; readonly 'podLogs.title': 'No logs emitted'; readonly 'podLogs.description': 'No logs were emitted by the container'; readonly 'podLogs.buttonText': 'Logs'; diff --git a/plugins/kubernetes/report-alpha.api.md b/plugins/kubernetes/report-alpha.api.md index 25090f7431..7086976724 100644 --- a/plugins/kubernetes/report-alpha.api.md +++ b/plugins/kubernetes/report-alpha.api.md @@ -102,10 +102,10 @@ const _default: OverridableFrontendPlugin< }; configInput: { filter?: FilterPredicate | undefined; - path?: string | undefined; title?: string | undefined; - icon?: string | undefined; + path?: string | undefined; group?: string | false | undefined; + icon?: string | undefined; }; output: | ExtensionDataRef @@ -168,8 +168,8 @@ const _default: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - path?: string | undefined; title?: string | undefined; + path?: string | undefined; }; output: | ExtensionDataRef diff --git a/plugins/mui-to-bui/report.api.md b/plugins/mui-to-bui/report.api.md index c1c97a49a2..f4bf566c9e 100644 --- a/plugins/mui-to-bui/report.api.md +++ b/plugins/mui-to-bui/report.api.md @@ -42,8 +42,8 @@ const _default: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - path?: string | undefined; title?: string | undefined; + path?: string | undefined; }; output: | ExtensionDataRef diff --git a/plugins/notifications/report-alpha.api.md b/plugins/notifications/report-alpha.api.md index ae826a05a1..e1feed0cde 100644 --- a/plugins/notifications/report-alpha.api.md +++ b/plugins/notifications/report-alpha.api.md @@ -48,8 +48,8 @@ const _default: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - path?: string | undefined; title?: string | undefined; + path?: string | undefined; }; output: | ExtensionDataRef @@ -124,13 +124,13 @@ export default _default; export const notificationsTranslationRef: TranslationRef< 'plugin.notifications', { + readonly 'table.errors.markAllReadFailed': 'Failed to mark all notifications as read'; readonly 'table.pagination.labelDisplayedRows': '{from}-{to} of {count}'; readonly 'table.pagination.firstTooltip': 'First Page'; readonly 'table.pagination.labelRowsSelect': 'rows'; readonly 'table.pagination.lastTooltip': 'Last Page'; readonly 'table.pagination.nextTooltip': 'Next Page'; readonly 'table.pagination.previousTooltip': 'Previous Page'; - readonly 'table.errors.markAllReadFailed': 'Failed to mark all notifications as read'; readonly 'table.emptyMessage': 'No records to display'; readonly 'table.bulkActions.markAllRead': 'Mark all read'; readonly 'table.bulkActions.markSelectedAsRead': 'Mark selected as read'; @@ -140,16 +140,16 @@ export const notificationsTranslationRef: TranslationRef< readonly 'table.confirmDialog.title': 'Are you sure?'; readonly 'table.confirmDialog.markAllReadDescription': 'Mark all notifications as read.'; readonly 'table.confirmDialog.markAllReadConfirmation': 'Mark All'; - readonly 'filters.title': 'Filters'; - readonly 'filters.view.label': 'View'; readonly 'filters.view.all': 'All'; + readonly 'filters.view.label': 'View'; readonly 'filters.view.read': 'Read notifications'; readonly 'filters.view.saved': 'Saved'; readonly 'filters.view.unread': 'Unread notifications'; + readonly 'filters.title': 'Filters'; readonly 'filters.severity.normal': 'Normal'; - readonly 'filters.severity.label': 'Min severity'; readonly 'filters.severity.high': 'High'; readonly 'filters.severity.low': 'Low'; + readonly 'filters.severity.label': 'Min severity'; readonly 'filters.severity.critical': 'Critical'; readonly 'filters.topic.label': 'Topic'; readonly 'filters.topic.anyTopic': 'Any topic'; @@ -161,12 +161,12 @@ export const notificationsTranslationRef: TranslationRef< readonly 'filters.sortBy.origin': 'Origin'; readonly 'filters.sortBy.label': 'Sort by'; readonly 'filters.sortBy.placeholder': 'Field to sort by'; - readonly 'filters.sortBy.topic': 'Topic'; readonly 'filters.sortBy.newest': 'Newest on top'; readonly 'filters.sortBy.oldest': 'Oldest on top'; - readonly 'settings.title': 'Notification settings'; + readonly 'filters.sortBy.topic': 'Topic'; readonly 'settings.table.origin': 'Origin'; readonly 'settings.table.topic': 'Topic'; + readonly 'settings.title': 'Notification settings'; readonly 'settings.errors.useNotificationFormat': 'useNotificationFormat must be used within a NotificationFormatProvider'; readonly 'settings.errorTitle': 'Failed to load settings'; readonly 'settings.noSettingsAvailable': 'No notification settings available, check back later'; diff --git a/plugins/org/report-alpha.api.md b/plugins/org/report-alpha.api.md index 76bbc52da2..44fd429bfa 100644 --- a/plugins/org/report-alpha.api.md +++ b/plugins/org/report-alpha.api.md @@ -25,11 +25,11 @@ const _default: OverridableFrontendPlugin< name: 'group-profile'; config: { filter: FilterPredicate | undefined; - type: 'info' | 'content' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { filter?: FilterPredicate | undefined; - type?: 'info' | 'content' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -66,13 +66,13 @@ const _default: OverridableFrontendPlugin< initialRelationAggregation: 'direct' | 'aggregated' | undefined; showAggregateMembersToggle: boolean | undefined; filter: FilterPredicate | undefined; - type: 'info' | 'content' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { showAggregateMembersToggle?: boolean | undefined; initialRelationAggregation?: 'direct' | 'aggregated' | undefined; filter?: FilterPredicate | undefined; - type?: 'info' | 'content' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -112,14 +112,14 @@ const _default: OverridableFrontendPlugin< showAggregateMembersToggle: boolean | undefined; ownedKinds: string[] | undefined; filter: FilterPredicate | undefined; - type: 'info' | 'content' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { showAggregateMembersToggle?: boolean | undefined; initialRelationAggregation?: 'direct' | 'aggregated' | undefined; ownedKinds?: string[] | undefined; filter?: FilterPredicate | undefined; - type?: 'info' | 'content' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef @@ -158,13 +158,13 @@ const _default: OverridableFrontendPlugin< maxRelations: number | undefined; hideIcons: boolean; filter: FilterPredicate | undefined; - type: 'info' | 'content' | undefined; + type: 'content' | 'info' | undefined; }; configInput: { hideIcons?: boolean | undefined; maxRelations?: number | undefined; filter?: FilterPredicate | undefined; - type?: 'info' | 'content' | undefined; + type?: 'content' | 'info' | undefined; }; output: | ExtensionDataRef diff --git a/plugins/scaffolder-backend-module-bitbucket-cloud/report.api.md b/plugins/scaffolder-backend-module-bitbucket-cloud/report.api.md index a7050aa68c..af34609213 100644 --- a/plugins/scaffolder-backend-module-bitbucket-cloud/report.api.md +++ b/plugins/scaffolder-backend-module-bitbucket-cloud/report.api.md @@ -25,25 +25,25 @@ export const createBitbucketPipelinesRunAction: (options: { | { type?: string | undefined; source?: string | undefined; - commit?: - | { - type: string; - hash: string; - } - | undefined; selector?: | { type: string; pattern: string; } | undefined; - ref_name?: string | undefined; - destination?: string | undefined; pull_request?: | { id: string; } | undefined; + commit?: + | { + type: string; + hash: string; + } + | undefined; + destination?: string | undefined; + ref_name?: string | undefined; ref_type?: string | undefined; destination_commit?: | { @@ -54,8 +54,8 @@ export const createBitbucketPipelinesRunAction: (options: { | undefined; variables?: | { - value: string; key: string; + value: string; secured: boolean; }[] | undefined; @@ -80,7 +80,7 @@ export function createPublishBitbucketCloudAction(options: { repoUrl: string; description?: string | undefined; defaultBranch?: string | undefined; - repoVisibility?: 'public' | 'private' | undefined; + repoVisibility?: 'private' | 'public' | undefined; gitCommitMessage?: string | undefined; sourcePath?: string | undefined; token?: string | undefined; diff --git a/plugins/scaffolder-backend-module-bitbucket-server/report.api.md b/plugins/scaffolder-backend-module-bitbucket-server/report.api.md index a52bee490e..929eb165c4 100644 --- a/plugins/scaffolder-backend-module-bitbucket-server/report.api.md +++ b/plugins/scaffolder-backend-module-bitbucket-server/report.api.md @@ -20,7 +20,7 @@ export function createPublishBitbucketServerAction(options: { { repoUrl: string; description?: string | undefined; - repoVisibility?: 'public' | 'private' | undefined; + repoVisibility?: 'private' | 'public' | undefined; defaultBranch?: string | undefined; sourcePath?: string | undefined; enableLFS?: boolean | undefined; diff --git a/plugins/scaffolder-backend-module-gitea/report.api.md b/plugins/scaffolder-backend-module-gitea/report.api.md index 8a0393abef..afc8286365 100644 --- a/plugins/scaffolder-backend-module-gitea/report.api.md +++ b/plugins/scaffolder-backend-module-gitea/report.api.md @@ -17,7 +17,7 @@ export function createPublishGiteaAction(options: { repoUrl: string; description: string; defaultBranch?: string | undefined; - repoVisibility?: 'public' | 'private' | undefined; + repoVisibility?: 'private' | 'public' | undefined; gitCommitMessage?: string | undefined; gitAuthorName?: string | undefined; gitAuthorEmail?: string | undefined; diff --git a/plugins/scaffolder-backend-module-github/report.api.md b/plugins/scaffolder-backend-module-github/report.api.md index 3dbc72b57b..9e930a7866 100644 --- a/plugins/scaffolder-backend-module-github/report.api.md +++ b/plugins/scaffolder-backend-module-github/report.api.md @@ -67,14 +67,14 @@ export function createGithubBranchProtectionAction(options: { bypassPullRequestAllowances?: | { apps?: string[] | undefined; - users?: string[] | undefined; teams?: string[] | undefined; + users?: string[] | undefined; } | undefined; restrictions?: | { - users: string[]; teams: string[]; + users: string[]; apps?: string[] | undefined; } | undefined; @@ -242,8 +242,8 @@ export function createGithubRepoCreateAction(options: { bypassPullRequestAllowances?: | { apps?: string[] | undefined; - users?: string[] | undefined; teams?: string[] | undefined; + users?: string[] | undefined; } | undefined; collaborators?: @@ -279,7 +279,7 @@ export function createGithubRepoCreateAction(options: { protectDefaultBranch?: boolean | undefined; protectEnforceAdmins?: boolean | undefined; repoVariables?: Record | undefined; - repoVisibility?: 'public' | 'internal' | 'private' | undefined; + repoVisibility?: 'internal' | 'private' | 'public' | undefined; requireBranchesToBeUpToDate?: boolean | undefined; requireCodeOwnerReviews?: boolean | undefined; requiredApprovingReviewCount?: number | undefined; @@ -290,8 +290,8 @@ export function createGithubRepoCreateAction(options: { requireLastPushApproval?: boolean | undefined; restrictions?: | { - users: string[]; teams: string[]; + users: string[]; apps?: string[] | undefined; } | undefined; @@ -306,7 +306,7 @@ export function createGithubRepoCreateAction(options: { subscribe?: boolean | undefined; token?: string | undefined; topics?: string[] | undefined; - workflowAccess?: 'none' | 'user' | 'organization' | undefined; + workflowAccess?: 'none' | 'organization' | 'user' | undefined; }, { remoteUrl: string; @@ -329,15 +329,15 @@ export function createGithubRepoPushAction(options: { bypassPullRequestAllowances?: | { apps?: string[] | undefined; - users?: string[] | undefined; teams?: string[] | undefined; + users?: string[] | undefined; } | undefined; requiredApprovingReviewCount?: number | undefined; restrictions?: | { - users: string[]; teams: string[]; + users: string[]; apps?: string[] | undefined; } | undefined; @@ -399,15 +399,15 @@ export function createPublishGithubAction(options: { bypassPullRequestAllowances?: | { apps?: string[] | undefined; - users?: string[] | undefined; teams?: string[] | undefined; + users?: string[] | undefined; } | undefined; requiredApprovingReviewCount?: number | undefined; restrictions?: | { - users: string[]; teams: string[]; + users: string[]; apps?: string[] | undefined; } | undefined; @@ -417,7 +417,7 @@ export function createPublishGithubAction(options: { requireBranchesToBeUpToDate?: boolean | undefined; requiredConversationResolution?: boolean | undefined; requireLastPushApproval?: boolean | undefined; - repoVisibility?: 'public' | 'internal' | 'private' | undefined; + repoVisibility?: 'internal' | 'private' | 'public' | undefined; defaultBranch?: string | undefined; protectDefaultBranch?: boolean | undefined; protectEnforceAdmins?: boolean | undefined; diff --git a/plugins/scaffolder-backend-module-gitlab/report.api.md b/plugins/scaffolder-backend-module-gitlab/report.api.md index 5f119024b7..cbe31b02f3 100644 --- a/plugins/scaffolder-backend-module-gitlab/report.api.md +++ b/plugins/scaffolder-backend-module-gitlab/report.api.md @@ -154,7 +154,7 @@ export const createGitlabRepoPushAction: (options: { sourcePath?: string | undefined; targetPath?: string | undefined; token?: string | undefined; - commitAction?: 'auto' | 'create' | 'update' | 'delete' | undefined; + commitAction?: 'auto' | 'update' | 'delete' | 'create' | undefined; }, { projectid: string; @@ -193,7 +193,7 @@ export function createPublishGitlabAction(options: { }): TemplateAction< { repoUrl: string; - repoVisibility?: 'public' | 'internal' | 'private' | undefined; + repoVisibility?: 'internal' | 'private' | 'public' | undefined; defaultBranch?: string | undefined; gitCommitMessage?: string | undefined; gitAuthorName?: string | undefined; @@ -206,24 +206,24 @@ export function createPublishGitlabAction(options: { topics?: string[] | undefined; settings?: | { + visibility?: 'internal' | 'private' | 'public' | undefined; path?: string | undefined; description?: string | undefined; - visibility?: 'public' | 'internal' | 'private' | undefined; - topics?: string[] | undefined; merge_method?: 'merge' | 'rebase_merge' | 'ff' | undefined; + topics?: string[] | undefined; auto_devops_enabled?: boolean | undefined; - ci_config_path?: string | undefined; - squash_option?: - | 'never' - | 'always' - | 'default_off' - | 'default_on' - | undefined; + only_allow_merge_if_pipeline_succeeds?: boolean | undefined; + allow_merge_on_skipped_pipeline?: boolean | undefined; only_allow_merge_if_all_discussions_are_resolved?: | boolean | undefined; - only_allow_merge_if_pipeline_succeeds?: boolean | undefined; - allow_merge_on_skipped_pipeline?: boolean | undefined; + squash_option?: + | 'always' + | 'never' + | 'default_on' + | 'default_off' + | undefined; + ci_config_path?: string | undefined; } | undefined; branches?: @@ -236,15 +236,15 @@ export function createPublishGitlabAction(options: { | undefined; projectVariables?: | { - value: string; key: string; + value: string; + raw?: boolean | undefined; description?: string | undefined; protected?: boolean | undefined; - raw?: boolean | undefined; variable_type?: 'file' | 'env_var' | undefined; masked?: boolean | undefined; - masked_and_hidden?: boolean | undefined; environment_scope?: string | undefined; + masked_and_hidden?: boolean | undefined; }[] | undefined; }, @@ -271,7 +271,7 @@ export const createPublishGitlabMergeRequestAction: (options: { sourcePath?: string | undefined; targetPath?: string | undefined; token?: string | undefined; - commitAction?: 'auto' | 'create' | 'update' | 'delete' | 'skip' | undefined; + commitAction?: 'auto' | 'update' | 'delete' | 'create' | 'skip' | undefined; projectid?: string | undefined; removeSourceBranch?: boolean | undefined; assignee?: string | undefined; diff --git a/plugins/scaffolder-backend-module-rails/report.api.md b/plugins/scaffolder-backend-module-rails/report.api.md index 8efc166c97..b09b75591b 100644 --- a/plugins/scaffolder-backend-module-rails/report.api.md +++ b/plugins/scaffolder-backend-module-rails/report.api.md @@ -47,8 +47,9 @@ export function createFetchRailsAction(options: { values: { railsArguments?: | { - api?: boolean | undefined; template?: string | undefined; + api?: boolean | undefined; + force?: boolean | undefined; database?: | 'sqlite3' | 'mysql' @@ -60,7 +61,6 @@ export function createFetchRailsAction(options: { | 'jdbcpostgresql' | 'jdbc' | undefined; - force?: boolean | undefined; minimal?: boolean | undefined; railsVersion?: 'edge' | 'master' | 'dev' | 'fromImage' | undefined; skipActionCable?: boolean | undefined; diff --git a/plugins/scaffolder-backend/report.api.md b/plugins/scaffolder-backend/report.api.md index f203dd2faa..8f9249cc5e 100644 --- a/plugins/scaffolder-backend/report.api.md +++ b/plugins/scaffolder-backend/report.api.md @@ -217,8 +217,8 @@ export const createFilesystemReadDirAction: () => TemplateAction< export const createFilesystemRenameAction: () => TemplateAction< { files: { - to: string; from: string; + to: string; overwrite?: boolean | undefined; }[]; }, diff --git a/plugins/scaffolder-react/report-alpha.api.md b/plugins/scaffolder-react/report-alpha.api.md index 609debaca2..9e01257c5c 100644 --- a/plugins/scaffolder-react/report-alpha.api.md +++ b/plugins/scaffolder-react/report-alpha.api.md @@ -318,8 +318,8 @@ export const scaffolderReactTranslationRef: TranslationRef< readonly 'stepper.reviewButtonText': 'Review'; readonly 'stepper.stepIndexLabel': 'Step {{index, number}}'; readonly 'passwordWidget.content': 'This widget is insecure. Please use [`ui:field: Secret`](https://backstage.io/docs/features/software-templates/writing-templates/#using-secrets) instead of `ui:widget: password`'; - readonly 'scaffolderPageContextMenu.moreLabel': 'more'; readonly 'scaffolderPageContextMenu.createLabel': 'Create'; + readonly 'scaffolderPageContextMenu.moreLabel': 'more'; readonly 'scaffolderPageContextMenu.editorLabel': 'Manage Templates'; readonly 'scaffolderPageContextMenu.actionsLabel': 'Installed Actions'; readonly 'scaffolderPageContextMenu.tasksLabel': 'Task List'; diff --git a/plugins/scaffolder/report-alpha.api.md b/plugins/scaffolder/report-alpha.api.md index 87cb54d687..b2cd1bbcbe 100644 --- a/plugins/scaffolder/report-alpha.api.md +++ b/plugins/scaffolder/report-alpha.api.md @@ -144,8 +144,8 @@ const _default: OverridableFrontendPlugin< }; configInput: { filter?: FilterPredicate | undefined; - title?: string | undefined; label?: string | undefined; + title?: string | undefined; }; output: | ExtensionDataRef< @@ -200,8 +200,8 @@ const _default: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - path?: string | undefined; title?: string | undefined; + path?: string | undefined; }; output: | ExtensionDataRef @@ -572,24 +572,24 @@ export const scaffolderTranslationRef: TranslationRef< readonly 'fields.repoOwnerPicker.title': 'Owner'; readonly 'fields.repoOwnerPicker.description': 'The owner of the repository'; readonly 'aboutCard.launchTemplate': 'Launch Template'; - readonly 'actionsPage.title': 'Installed actions'; - readonly 'actionsPage.action.output': 'Output'; - readonly 'actionsPage.action.input': 'Input'; - readonly 'actionsPage.action.examples': 'Examples'; readonly 'actionsPage.content.emptyState.title': 'No information to display'; readonly 'actionsPage.content.emptyState.description': 'There are no actions installed or there was an issue communicating with backend.'; readonly 'actionsPage.content.searchFieldPlaceholder': 'Search for an action'; + readonly 'actionsPage.title': 'Installed actions'; + readonly 'actionsPage.action.input': 'Input'; + readonly 'actionsPage.action.output': 'Output'; + readonly 'actionsPage.action.examples': 'Examples'; readonly 'actionsPage.subtitle': 'This is the collection of all installed actions'; readonly 'actionsPage.pageTitle': 'Create a New Component'; - readonly 'listTaskPage.title': 'List template tasks'; readonly 'listTaskPage.content.emptyState.title': 'No information to display'; readonly 'listTaskPage.content.emptyState.description': 'There are no tasks or there was an issue communicating with backend.'; - readonly 'listTaskPage.content.tableTitle': 'Tasks'; - readonly 'listTaskPage.content.tableCell.status': 'Status'; readonly 'listTaskPage.content.tableCell.template': 'Template'; + readonly 'listTaskPage.content.tableCell.status': 'Status'; readonly 'listTaskPage.content.tableCell.owner': 'Owner'; readonly 'listTaskPage.content.tableCell.created': 'Created'; readonly 'listTaskPage.content.tableCell.taskID': 'Task ID'; + readonly 'listTaskPage.content.tableTitle': 'Tasks'; + readonly 'listTaskPage.title': 'List template tasks'; readonly 'listTaskPage.subtitle': 'All tasks that have been started'; readonly 'listTaskPage.pageTitle': 'Templates Tasks'; readonly 'ownerListPicker.title': 'Task Owner'; @@ -614,28 +614,28 @@ export const scaffolderTranslationRef: TranslationRef< readonly 'templateEditorForm.stepper.emptyText': 'There are no spec parameters in the template to preview.'; readonly 'renderSchema.undefined': 'No schema defined'; readonly 'renderSchema.tableCell.name': 'Name'; + readonly 'renderSchema.tableCell.type': 'Type'; readonly 'renderSchema.tableCell.title': 'Title'; readonly 'renderSchema.tableCell.description': 'Description'; - readonly 'renderSchema.tableCell.type': 'Type'; - readonly 'templatingExtensions.title': 'Templating Extensions'; readonly 'templatingExtensions.content.values.title': 'Values'; readonly 'templatingExtensions.content.values.notAvailable': 'There are no global template values defined.'; readonly 'templatingExtensions.content.emptyState.title': 'No information to display'; readonly 'templatingExtensions.content.emptyState.description': 'There are no templating extensions available or there was an issue communicating with the backend.'; readonly 'templatingExtensions.content.filters.title': 'Filters'; - readonly 'templatingExtensions.content.filters.schema.output': 'Output'; readonly 'templatingExtensions.content.filters.schema.input': 'Input'; + readonly 'templatingExtensions.content.filters.schema.output': 'Output'; readonly 'templatingExtensions.content.filters.schema.arguments': 'Arguments'; readonly 'templatingExtensions.content.filters.examples': 'Examples'; readonly 'templatingExtensions.content.filters.notAvailable': 'There are no template filters defined.'; readonly 'templatingExtensions.content.filters.metadataAbsent': 'Filter metadata unavailable'; - readonly 'templatingExtensions.content.searchFieldPlaceholder': 'Search for an extension'; readonly 'templatingExtensions.content.functions.title': 'Functions'; readonly 'templatingExtensions.content.functions.schema.output': 'Output'; readonly 'templatingExtensions.content.functions.schema.arguments': 'Arguments'; readonly 'templatingExtensions.content.functions.examples': 'Examples'; readonly 'templatingExtensions.content.functions.notAvailable': 'There are no global template functions defined.'; readonly 'templatingExtensions.content.functions.metadataAbsent': 'Function metadata unavailable'; + readonly 'templatingExtensions.content.searchFieldPlaceholder': 'Search for an extension'; + readonly 'templatingExtensions.title': 'Templating Extensions'; readonly 'templatingExtensions.subtitle': 'This is the collection of available templating extensions'; readonly 'templatingExtensions.pageTitle': 'Templating Extensions'; readonly 'templateTypePicker.title': 'Categories'; @@ -699,12 +699,12 @@ export const scaffolderTranslationRef: TranslationRef< readonly 'templateEditorToolbar.addToCatalogDialogTitle': 'Publish changes'; readonly 'templateEditorToolbar.addToCatalogDialogContent.stepsIntroduction': 'Follow the instructions below to create or update a template:'; readonly 'templateEditorToolbar.addToCatalogDialogContent.stepsListItems': 'Save the template files in a local directory\nCreate a pull request to a new or existing git repository\nIf the template already exists, the changes will be reflected in the software catalog once the pull request gets merged\nBut if you are creating a new template, follow the documentation linked below to register the new template repository in software catalog'; - readonly 'templateEditorToolbar.addToCatalogDialogActions.documentationButton': 'Go to the documentation'; readonly 'templateEditorToolbar.addToCatalogDialogActions.documentationUrl': 'https://backstage.io/docs/features/software-templates/adding-templates/'; + readonly 'templateEditorToolbar.addToCatalogDialogActions.documentationButton': 'Go to the documentation'; + readonly 'templateEditorToolbarFileMenu.button': 'File'; readonly 'templateEditorToolbarFileMenu.options.openDirectory': 'Open template directory'; readonly 'templateEditorToolbarFileMenu.options.createDirectory': 'Create template directory'; readonly 'templateEditorToolbarFileMenu.options.closeEditor': 'Close template editor'; - readonly 'templateEditorToolbarFileMenu.button': 'File'; readonly 'templateEditorToolbarTemplatesMenu.button': 'Templates'; } >; diff --git a/plugins/search-backend-module-elasticsearch/report.api.md b/plugins/search-backend-module-elasticsearch/report.api.md index f90dc2c0d9..afe06dd45e 100644 --- a/plugins/search-backend-module-elasticsearch/report.api.md +++ b/plugins/search-backend-module-elasticsearch/report.api.md @@ -7,8 +7,8 @@ import { ApiResponse } from '@opensearch-project/opensearch'; import { ApiResponse as ApiResponse_2 } from '@elastic/elasticsearch'; import { BackendFeature } from '@backstage/backend-plugin-api'; import { BatchSearchEngineIndexer } from '@backstage/plugin-search-backend-node'; -import { BulkHelper } from '@opensearch-project/opensearch/lib/Helpers.js'; -import { BulkStats } from '@opensearch-project/opensearch/lib/Helpers.js'; +import { BulkHelper } from '@elastic/elasticsearch/lib/Helpers'; +import { BulkStats } from '@elastic/elasticsearch/lib/Helpers'; import { Config } from '@backstage/config'; import type { ConnectionOptions } from 'node:tls'; import { ExtensionPoint } from '@backstage/backend-plugin-api'; diff --git a/plugins/search/report-alpha.api.md b/plugins/search/report-alpha.api.md index 9a31942231..e3f2d6108a 100644 --- a/plugins/search/report-alpha.api.md +++ b/plugins/search/report-alpha.api.md @@ -73,8 +73,8 @@ const _default: OverridableFrontendPlugin< }; configInput: { noTrack?: boolean | undefined; - path?: string | undefined; title?: string | undefined; + path?: string | undefined; }; output: | ExtensionDataRef @@ -242,8 +242,8 @@ export const searchPage: OverridableExtensionDefinition<{ }; configInput: { noTrack?: boolean | undefined; - path?: string | undefined; title?: string | undefined; + path?: string | undefined; }; output: | ExtensionDataRef diff --git a/plugins/techdocs/report-alpha.api.md b/plugins/techdocs/report-alpha.api.md index dc3b144665..aa14098288 100644 --- a/plugins/techdocs/report-alpha.api.md +++ b/plugins/techdocs/report-alpha.api.md @@ -133,10 +133,10 @@ const _default: OverridableFrontendPlugin< }; configInput: { filter?: FilterPredicate | undefined; - path?: string | undefined; title?: string | undefined; - icon?: string | undefined; + path?: string | undefined; group?: string | false | undefined; + icon?: string | undefined; }; output: | ExtensionDataRef @@ -230,8 +230,8 @@ const _default: OverridableFrontendPlugin< }; configInput: { filter?: FilterPredicate | undefined; - title?: string | undefined; label?: string | undefined; + title?: string | undefined; }; output: | ExtensionDataRef< @@ -288,8 +288,8 @@ const _default: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - path?: string | undefined; title?: string | undefined; + path?: string | undefined; }; output: | ExtensionDataRef @@ -366,8 +366,8 @@ const _default: OverridableFrontendPlugin< configInput: { withoutSearch?: boolean | undefined; withoutHeader?: boolean | undefined; - path?: string | undefined; title?: string | undefined; + path?: string | undefined; }; output: | ExtensionDataRef diff --git a/plugins/user-settings/report-alpha.api.md b/plugins/user-settings/report-alpha.api.md index 35f7f1a262..c99709d777 100644 --- a/plugins/user-settings/report-alpha.api.md +++ b/plugins/user-settings/report-alpha.api.md @@ -50,8 +50,8 @@ const _default: OverridableFrontendPlugin< title: string | undefined; }; configInput: { - path?: string | undefined; title?: string | undefined; + path?: string | undefined; }; output: | ExtensionDataRef @@ -164,22 +164,22 @@ export const userSettingsTranslationRef: TranslationRef< readonly 'featureFlags.filterTitle': 'Filter'; readonly 'featureFlags.clearFilter': 'Clear filter'; readonly 'featureFlags.emptyFlags.title': 'No Feature Flags'; - readonly 'featureFlags.emptyFlags.description': 'Feature Flags make it possible for plugins to register features in Backstage for users to opt into. You can use this to split out logic in your code for manual A/B testing, etc.'; readonly 'featureFlags.emptyFlags.action.title': 'An example for how to add a feature flag is highlighted below:'; readonly 'featureFlags.emptyFlags.action.readMoreButtonTitle': 'Read More'; + readonly 'featureFlags.emptyFlags.description': 'Feature Flags make it possible for plugins to register features in Backstage for users to opt into. You can use this to split out logic in your code for manual A/B testing, etc.'; readonly 'featureFlags.flagItem.title.disable': 'Disable'; readonly 'featureFlags.flagItem.title.enable': 'Enable'; readonly 'featureFlags.flagItem.subtitle.registeredInApplication': 'Registered in the application'; readonly 'featureFlags.flagItem.subtitle.registeredInPlugin': 'Registered in {{pluginId}} plugin'; + readonly 'languageToggle.select': 'Select language {{language}}'; readonly 'languageToggle.title': 'Language'; readonly 'languageToggle.description': 'Change the language'; - readonly 'languageToggle.select': 'Select language {{language}}'; + readonly 'themeToggle.select': 'Select {{theme}}'; readonly 'themeToggle.title': 'Theme'; readonly 'themeToggle.description': 'Change the theme mode'; - readonly 'themeToggle.select': 'Select {{theme}}'; readonly 'themeToggle.names.auto': 'Auto'; - readonly 'themeToggle.names.light': 'Light'; readonly 'themeToggle.names.dark': 'Dark'; + readonly 'themeToggle.names.light': 'Light'; readonly 'themeToggle.selectAuto': 'Select Auto Theme'; readonly 'signOutMenu.title': 'Sign Out'; readonly 'signOutMenu.moreIconTitle': 'more'; @@ -194,9 +194,9 @@ export const userSettingsTranslationRef: TranslationRef< readonly 'identityCard.ownershipEntities': 'Ownership Entities'; readonly 'defaultProviderSettings.description': 'Provides authentication towards {{provider}} APIs and identities'; readonly 'emptyProviders.title': 'No Authentication Providers'; - readonly 'emptyProviders.description': 'You can add Authentication Providers to Backstage which allows you to use these providers to authenticate yourself.'; readonly 'emptyProviders.action.title': 'Open app-config.yaml and make the changes as highlighted below:'; readonly 'emptyProviders.action.readMoreButtonTitle': 'Read More'; + readonly 'emptyProviders.description': 'You can add Authentication Providers to Backstage which allows you to use these providers to authenticate yourself.'; readonly 'providerSettingsItem.title.signOut': 'Sign out from {{title}}'; readonly 'providerSettingsItem.title.signIn': 'Sign in to {{title}}'; readonly 'providerSettingsItem.buttonTitle.signOut': 'Sign out'; From cb8a487bde14788c5ce8a99f9c7ca9e096820c9d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Mar 2026 19:04:34 +0100 Subject: [PATCH 06/13] frontend-plugin-api: rely on ApiRef inference Remove explicit ApiRef constant annotations from frontend API ref declarations and rely on the createApiRef type argument for inference instead. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .../src/apis/definitions/AlertApi.ts | 4 +- .../src/apis/definitions/AnalyticsApi.ts | 11 ++- .../src/apis/definitions/AppLanguageApi.ts | 11 ++- .../src/apis/definitions/AppThemeApi.ts | 11 ++- .../src/apis/definitions/ConfigApi.ts | 4 +- .../src/apis/definitions/DiscoveryApi.ts | 11 ++- .../src/apis/definitions/ErrorApi.ts | 4 +- .../src/apis/definitions/FeatureFlagsApi.ts | 11 ++- .../src/apis/definitions/FetchApi.ts | 4 +- .../src/apis/definitions/IdentityApi.ts | 11 ++- .../src/apis/definitions/OAuthRequestApi.ts | 11 ++- .../src/apis/definitions/StorageApi.ts | 11 ++- .../src/apis/definitions/TranslationApi.ts | 11 ++- .../src/apis/definitions/auth.ts | 70 ++++--------------- 14 files changed, 65 insertions(+), 120 deletions(-) diff --git a/packages/frontend-plugin-api/src/apis/definitions/AlertApi.ts b/packages/frontend-plugin-api/src/apis/definitions/AlertApi.ts index 09d979ad9a..3dd7c8e443 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/AlertApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/AlertApi.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { createApiRef, ApiRef } from '../system'; +import { createApiRef } from '../system'; import { Observable } from '@backstage/types'; /** @@ -51,7 +51,7 @@ export type AlertApi = { * * @public */ -export const alertApiRef: ApiRef = createApiRef().with({ +export const alertApiRef = createApiRef().with({ id: 'core.alert', pluginId: 'app', }); diff --git a/packages/frontend-plugin-api/src/apis/definitions/AnalyticsApi.ts b/packages/frontend-plugin-api/src/apis/definitions/AnalyticsApi.ts index 51acc1851d..bd5d9a4394 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/AnalyticsApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/AnalyticsApi.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { ApiRef, createApiRef } from '../system'; +import { createApiRef } from '../system'; import { AnalyticsContextValue } from '../../analytics/types'; /** @@ -151,8 +151,7 @@ export type AnalyticsApi = { * * @public */ -export const analyticsApiRef: ApiRef = - createApiRef().with({ - id: 'core.analytics', - pluginId: 'app', - }); +export const analyticsApiRef = createApiRef().with({ + id: 'core.analytics', + pluginId: 'app', +}); diff --git a/packages/frontend-plugin-api/src/apis/definitions/AppLanguageApi.ts b/packages/frontend-plugin-api/src/apis/definitions/AppLanguageApi.ts index c4a1c8be73..1b1b7437b5 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/AppLanguageApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/AppLanguageApi.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { ApiRef, createApiRef } from '../system'; +import { createApiRef } from '../system'; import { Observable } from '@backstage/types'; /** @public */ @@ -31,8 +31,7 @@ export type AppLanguageApi = { /** * @public */ -export const appLanguageApiRef: ApiRef = - createApiRef().with({ - id: 'core.applanguage', - pluginId: 'app', - }); +export const appLanguageApiRef = createApiRef().with({ + id: 'core.applanguage', + pluginId: 'app', +}); diff --git a/packages/frontend-plugin-api/src/apis/definitions/AppThemeApi.ts b/packages/frontend-plugin-api/src/apis/definitions/AppThemeApi.ts index 39561f5f96..66669e8cab 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/AppThemeApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/AppThemeApi.ts @@ -15,7 +15,7 @@ */ import { ReactNode } from 'react'; -import { ApiRef, createApiRef } from '../system'; +import { createApiRef } from '../system'; import { Observable } from '@backstage/types'; /** @@ -82,8 +82,7 @@ export type AppThemeApi = { * * @public */ -export const appThemeApiRef: ApiRef = - createApiRef().with({ - id: 'core.apptheme', - pluginId: 'app', - }); +export const appThemeApiRef = createApiRef().with({ + id: 'core.apptheme', + pluginId: 'app', +}); diff --git a/packages/frontend-plugin-api/src/apis/definitions/ConfigApi.ts b/packages/frontend-plugin-api/src/apis/definitions/ConfigApi.ts index eb52c1cbca..8cc1638d90 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/ConfigApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/ConfigApi.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ApiRef, createApiRef } from '../system'; +import { createApiRef } from '../system'; import type { Config } from '@backstage/config'; /** @@ -29,7 +29,7 @@ export type ConfigApi = Config; * * @public */ -export const configApiRef: ApiRef = createApiRef().with({ +export const configApiRef = createApiRef().with({ id: 'core.config', pluginId: 'app', }); diff --git a/packages/frontend-plugin-api/src/apis/definitions/DiscoveryApi.ts b/packages/frontend-plugin-api/src/apis/definitions/DiscoveryApi.ts index fb348c156d..824174c8f6 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/DiscoveryApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/DiscoveryApi.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ApiRef, createApiRef } from '../system'; +import { createApiRef } from '../system'; /** * The discovery API is used to provide a mechanism for plugins to @@ -50,8 +50,7 @@ export type DiscoveryApi = { * * @public */ -export const discoveryApiRef: ApiRef = - createApiRef().with({ - id: 'core.discovery', - pluginId: 'app', - }); +export const discoveryApiRef = createApiRef().with({ + id: 'core.discovery', + pluginId: 'app', +}); diff --git a/packages/frontend-plugin-api/src/apis/definitions/ErrorApi.ts b/packages/frontend-plugin-api/src/apis/definitions/ErrorApi.ts index d106ccc05c..e7be718326 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/ErrorApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/ErrorApi.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { ApiRef, createApiRef } from '../system'; +import { createApiRef } from '../system'; import { Observable } from '@backstage/types'; /** @@ -86,7 +86,7 @@ export type ErrorApi = { * * @public */ -export const errorApiRef: ApiRef = createApiRef().with({ +export const errorApiRef = createApiRef().with({ id: 'core.error', pluginId: 'app', }); diff --git a/packages/frontend-plugin-api/src/apis/definitions/FeatureFlagsApi.ts b/packages/frontend-plugin-api/src/apis/definitions/FeatureFlagsApi.ts index 7206dd9900..b7d1c4ccaa 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/FeatureFlagsApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/FeatureFlagsApi.ts @@ -16,7 +16,7 @@ /* We want to maintain the same information as an enum, so we disable the redeclaration warning */ /* eslint-disable @typescript-eslint/no-redeclare */ -import { ApiRef, createApiRef } from '../system'; +import { createApiRef } from '../system'; /** * Feature flag descriptor. @@ -121,8 +121,7 @@ export interface FeatureFlagsApi { * * @public */ -export const featureFlagsApiRef: ApiRef = - createApiRef().with({ - id: 'core.featureflags', - pluginId: 'app', - }); +export const featureFlagsApiRef = createApiRef().with({ + id: 'core.featureflags', + pluginId: 'app', +}); diff --git a/packages/frontend-plugin-api/src/apis/definitions/FetchApi.ts b/packages/frontend-plugin-api/src/apis/definitions/FetchApi.ts index 4e4909b7d4..5299878c34 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/FetchApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/FetchApi.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { ApiRef, createApiRef } from '../system'; +import { createApiRef } from '../system'; /** * A wrapper for the fetch API, that has additional behaviors such as the @@ -46,7 +46,7 @@ export type FetchApi = { * * @public */ -export const fetchApiRef: ApiRef = createApiRef().with({ +export const fetchApiRef = createApiRef().with({ id: 'core.fetch', pluginId: 'app', }); diff --git a/packages/frontend-plugin-api/src/apis/definitions/IdentityApi.ts b/packages/frontend-plugin-api/src/apis/definitions/IdentityApi.ts index dc23202c2e..70b6ebf56a 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/IdentityApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/IdentityApi.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ApiRef, createApiRef } from '../system'; +import { createApiRef } from '../system'; import { BackstageUserIdentity, ProfileInfo } from './auth'; /** @@ -51,8 +51,7 @@ export type IdentityApi = { * * @public */ -export const identityApiRef: ApiRef = - createApiRef().with({ - id: 'core.identity', - pluginId: 'app', - }); +export const identityApiRef = createApiRef().with({ + id: 'core.identity', + pluginId: 'app', +}); diff --git a/packages/frontend-plugin-api/src/apis/definitions/OAuthRequestApi.ts b/packages/frontend-plugin-api/src/apis/definitions/OAuthRequestApi.ts index 0c199948af..d94ab44d15 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/OAuthRequestApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/OAuthRequestApi.ts @@ -15,7 +15,7 @@ */ import { Observable } from '@backstage/types'; -import { ApiRef, createApiRef } from '../system'; +import { createApiRef } from '../system'; import { AuthProviderInfo } from './auth'; /** @@ -126,8 +126,7 @@ export type OAuthRequestApi = { * * @public */ -export const oauthRequestApiRef: ApiRef = - createApiRef().with({ - id: 'core.oauthrequest', - pluginId: 'app', - }); +export const oauthRequestApiRef = createApiRef().with({ + id: 'core.oauthrequest', + pluginId: 'app', +}); diff --git a/packages/frontend-plugin-api/src/apis/definitions/StorageApi.ts b/packages/frontend-plugin-api/src/apis/definitions/StorageApi.ts index 7e8372b6fb..1624f8402c 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/StorageApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/StorageApi.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { ApiRef, createApiRef } from '../system'; +import { createApiRef } from '../system'; import { JsonValue, Observable } from '@backstage/types'; /** @@ -105,8 +105,7 @@ export interface StorageApi { * * @public */ -export const storageApiRef: ApiRef = - createApiRef().with({ - id: 'core.storage', - pluginId: 'app', - }); +export const storageApiRef = createApiRef().with({ + id: 'core.storage', + pluginId: 'app', +}); diff --git a/packages/frontend-plugin-api/src/apis/definitions/TranslationApi.ts b/packages/frontend-plugin-api/src/apis/definitions/TranslationApi.ts index 6997269484..ab50baf5e1 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/TranslationApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/TranslationApi.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { ApiRef, createApiRef } from '../system'; +import { createApiRef } from '../system'; import { Expand, ExpandRecursive, Observable } from '@backstage/types'; import { TranslationRef } from '../../translation'; import { JSX } from 'react'; @@ -358,8 +358,7 @@ export type TranslationApi = { /** * @public */ -export const translationApiRef: ApiRef = - createApiRef().with({ - id: 'core.translation', - pluginId: 'app', - }); +export const translationApiRef = createApiRef().with({ + id: 'core.translation', + pluginId: 'app', +}); diff --git a/packages/frontend-plugin-api/src/apis/definitions/auth.ts b/packages/frontend-plugin-api/src/apis/definitions/auth.ts index 0c05047f24..d686ed5d08 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/auth.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/auth.ts @@ -16,7 +16,7 @@ /* We want to maintain the same information as an enum, so we disable the redeclaration warning */ /* eslint-disable @typescript-eslint/no-redeclare */ -import { ApiRef, createApiRef } from '../system'; +import { createApiRef } from '../system'; import { IconComponent, IconElement } from '../../icons/types'; import { Observable } from '@backstage/types'; @@ -336,13 +336,7 @@ export type SessionApi = { * Note that the ID token payload is only guaranteed to contain the user's numerical Google ID, * email and expiration information. Do not rely on any other fields, as they might not be present. */ -export const googleAuthApiRef: ApiRef< - OAuthApi & - OpenIdConnectApi & - ProfileInfoApi & - BackstageIdentityApi & - SessionApi -> = createApiRef< +export const googleAuthApiRef = createApiRef< OAuthApi & OpenIdConnectApi & ProfileInfoApi & @@ -362,9 +356,7 @@ export const googleAuthApiRef: ApiRef< * See {@link https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/} * for a full list of supported scopes. */ -export const githubAuthApiRef: ApiRef< - OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi -> = createApiRef< +export const githubAuthApiRef = createApiRef< OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi >().with({ id: 'core.auth.github', @@ -380,13 +372,7 @@ export const githubAuthApiRef: ApiRef< * See {@link https://developer.okta.com/docs/guides/implement-oauth-for-okta/scopes/} * for a full list of supported scopes. */ -export const oktaAuthApiRef: ApiRef< - OAuthApi & - OpenIdConnectApi & - ProfileInfoApi & - BackstageIdentityApi & - SessionApi -> = createApiRef< +export const oktaAuthApiRef = createApiRef< OAuthApi & OpenIdConnectApi & ProfileInfoApi & @@ -406,13 +392,7 @@ export const oktaAuthApiRef: ApiRef< * See {@link https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#limiting-scopes-of-a-personal-access-token} * for a full list of supported scopes. */ -export const gitlabAuthApiRef: ApiRef< - OAuthApi & - OpenIdConnectApi & - ProfileInfoApi & - BackstageIdentityApi & - SessionApi -> = createApiRef< +export const gitlabAuthApiRef = createApiRef< OAuthApi & OpenIdConnectApi & ProfileInfoApi & @@ -433,13 +413,7 @@ export const gitlabAuthApiRef: ApiRef< * - {@link https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-permissions-and-consent} * - {@link https://docs.microsoft.com/en-us/graph/permissions-reference} */ -export const microsoftAuthApiRef: ApiRef< - OAuthApi & - OpenIdConnectApi & - ProfileInfoApi & - BackstageIdentityApi & - SessionApi -> = createApiRef< +export const microsoftAuthApiRef = createApiRef< OAuthApi & OpenIdConnectApi & ProfileInfoApi & @@ -455,13 +429,7 @@ export const microsoftAuthApiRef: ApiRef< * * @public */ -export const oneloginAuthApiRef: ApiRef< - OAuthApi & - OpenIdConnectApi & - ProfileInfoApi & - BackstageIdentityApi & - SessionApi -> = createApiRef< +export const oneloginAuthApiRef = createApiRef< OAuthApi & OpenIdConnectApi & ProfileInfoApi & @@ -481,9 +449,7 @@ export const oneloginAuthApiRef: ApiRef< * See {@link https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/} * for a full list of supported scopes. */ -export const bitbucketAuthApiRef: ApiRef< - OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi -> = createApiRef< +export const bitbucketAuthApiRef = createApiRef< OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi >().with({ id: 'core.auth.bitbucket', @@ -499,9 +465,7 @@ export const bitbucketAuthApiRef: ApiRef< * See {@link https://confluence.atlassian.com/bitbucketserver/bitbucket-oauth-2-0-provider-api-1108483661.html#BitbucketOAuth2.0providerAPI-scopes} * for a full list of supported scopes. */ -export const bitbucketServerAuthApiRef: ApiRef< - OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi -> = createApiRef< +export const bitbucketServerAuthApiRef = createApiRef< OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi >().with({ id: 'core.auth.bitbucket-server', @@ -517,9 +481,7 @@ export const bitbucketServerAuthApiRef: ApiRef< * See {@link https://developer.atlassian.com/cloud/jira/platform/scopes-for-connect-and-oauth-2-3LO-apps/} * for a full list of supported scopes. */ -export const atlassianAuthApiRef: ApiRef< - OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi -> = createApiRef< +export const atlassianAuthApiRef = createApiRef< OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi >().with({ id: 'core.auth.atlassian', @@ -535,13 +497,7 @@ export const atlassianAuthApiRef: ApiRef< * For more info about VMware Cloud identity and access management: * - {@link https://docs.vmware.com/en/VMware-Cloud-services/services/Using-VMware-Cloud-Services/GUID-53D39337-D93A-4B84-BD18-DDF43C21479A.html} */ -export const vmwareCloudAuthApiRef: ApiRef< - OAuthApi & - OpenIdConnectApi & - ProfileInfoApi & - BackstageIdentityApi & - SessionApi -> = createApiRef< +export const vmwareCloudAuthApiRef = createApiRef< OAuthApi & OpenIdConnectApi & ProfileInfoApi & @@ -563,9 +519,7 @@ export const vmwareCloudAuthApiRef: ApiRef< * {@link https://docs.redhat.com/en/documentation/openshift_container_platform/latest/html-single/authentication_and_authorization/index#tokens-scoping-about_configuring-internal-oauth} * for available scopes. */ -export const openshiftAuthApiRef: ApiRef< - OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi -> = createApiRef< +export const openshiftAuthApiRef = createApiRef< OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi >().with({ id: 'core.auth.openshift', From 7a960a0d75d8df7778073fd64fc11497f9c69eba Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Mar 2026 19:48:41 +0100 Subject: [PATCH 07/13] Regenerate API reports Update the frontend plugin API report after removing explicit ApiRef constant annotations from the frontend API ref declarations. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- packages/frontend-plugin-api/report.api.md | 118 +++++++++++++++------ 1 file changed, 83 insertions(+), 35 deletions(-) diff --git a/packages/frontend-plugin-api/report.api.md b/packages/frontend-plugin-api/report.api.md index f17ca670ea..52ee10a6ac 100644 --- a/packages/frontend-plugin-api/report.api.md +++ b/packages/frontend-plugin-api/report.api.md @@ -31,7 +31,9 @@ export type AlertApi = { }; // @public -export const alertApiRef: ApiRef; +export const alertApiRef: ApiRef_2 & { + readonly $$type: '@backstage/ApiRef'; +}; // @public export type AlertMessage = { @@ -46,7 +48,9 @@ export type AnalyticsApi = { }; // @public -export const analyticsApiRef: ApiRef; +export const analyticsApiRef: ApiRef_2 & { + readonly $$type: '@backstage/ApiRef'; +}; // @public export const AnalyticsContext: (options: { @@ -215,7 +219,9 @@ export type AppLanguageApi = { }; // @public (undocumented) -export const appLanguageApiRef: ApiRef; +export const appLanguageApiRef: ApiRef_2 & { + readonly $$type: '@backstage/ApiRef'; +}; // @public export interface AppNode { @@ -288,7 +294,9 @@ export type AppThemeApi = { }; // @public -export const appThemeApiRef: ApiRef; +export const appThemeApiRef: ApiRef_2 & { + readonly $$type: '@backstage/ApiRef'; +}; // @public export interface AppTree { @@ -313,9 +321,11 @@ export const appTreeApiRef: ApiRef_2 & { }; // @public -export const atlassianAuthApiRef: ApiRef< +export const atlassianAuthApiRef: ApiRef_2< OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi ->; +> & { + readonly $$type: '@backstage/ApiRef'; +}; // @public export type AuthProviderInfo = { @@ -353,20 +363,26 @@ export type BackstageUserIdentity = { }; // @public -export const bitbucketAuthApiRef: ApiRef< +export const bitbucketAuthApiRef: ApiRef_2< OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi ->; +> & { + readonly $$type: '@backstage/ApiRef'; +}; // @public -export const bitbucketServerAuthApiRef: ApiRef< +export const bitbucketServerAuthApiRef: ApiRef_2< OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi ->; +> & { + readonly $$type: '@backstage/ApiRef'; +}; // @public export type ConfigApi = Config; // @public -export const configApiRef: ApiRef; +export const configApiRef: ApiRef_2 & { + readonly $$type: '@backstage/ApiRef'; +}; // @public (undocumented) export interface ConfigurableExtensionDataRef< @@ -893,7 +909,9 @@ export type DiscoveryApi = { }; // @public -export const discoveryApiRef: ApiRef; +export const discoveryApiRef: ApiRef_2 & { + readonly $$type: '@backstage/ApiRef'; +}; // @public export type ErrorApi = { @@ -917,7 +935,9 @@ export type ErrorApiErrorContext = { }; // @public -export const errorApiRef: ApiRef; +export const errorApiRef: ApiRef_2 & { + readonly $$type: '@backstage/ApiRef'; +}; // @public (undocumented) export const ErrorDisplay: { @@ -1301,7 +1321,9 @@ export interface FeatureFlagsApi { } // @public -export const featureFlagsApiRef: ApiRef; +export const featureFlagsApiRef: ApiRef_2 & { + readonly $$type: '@backstage/ApiRef'; +}; // @public export type FeatureFlagsSaveOptions = { @@ -1333,7 +1355,9 @@ export type FetchApi = { }; // @public -export const fetchApiRef: ApiRef; +export const fetchApiRef: ApiRef_2 & { + readonly $$type: '@backstage/ApiRef'; +}; // @public (undocumented) export type FrontendFeature = @@ -1406,27 +1430,33 @@ export type FrontendPluginInfoOptions = { }; // @public -export const githubAuthApiRef: ApiRef< +export const githubAuthApiRef: ApiRef_2< OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi ->; +> & { + readonly $$type: '@backstage/ApiRef'; +}; // @public -export const gitlabAuthApiRef: ApiRef< +export const gitlabAuthApiRef: ApiRef_2< OAuthApi & OpenIdConnectApi & ProfileInfoApi & BackstageIdentityApi & SessionApi ->; +> & { + readonly $$type: '@backstage/ApiRef'; +}; // @public -export const googleAuthApiRef: ApiRef< +export const googleAuthApiRef: ApiRef_2< OAuthApi & OpenIdConnectApi & ProfileInfoApi & BackstageIdentityApi & SessionApi ->; +> & { + readonly $$type: '@backstage/ApiRef'; +}; // @public @deprecated export type IconComponent = ComponentType<{ @@ -1461,16 +1491,20 @@ export type IdentityApi = { }; // @public -export const identityApiRef: ApiRef; +export const identityApiRef: ApiRef_2 & { + readonly $$type: '@backstage/ApiRef'; +}; // @public -export const microsoftAuthApiRef: ApiRef< +export const microsoftAuthApiRef: ApiRef_2< OAuthApi & OpenIdConnectApi & ProfileInfoApi & BackstageIdentityApi & SessionApi ->; +> & { + readonly $$type: '@backstage/ApiRef'; +}; // @public @deprecated export const NavItemBlueprint: ExtensionBlueprint_2<{ @@ -1533,7 +1567,9 @@ export type OAuthRequestApi = { }; // @public -export const oauthRequestApiRef: ApiRef; +export const oauthRequestApiRef: ApiRef_2 & { + readonly $$type: '@backstage/ApiRef'; +}; // @public export type OAuthRequester = ( @@ -1550,22 +1586,26 @@ export type OAuthRequesterOptions = { export type OAuthScope = string | string[]; // @public -export const oktaAuthApiRef: ApiRef< +export const oktaAuthApiRef: ApiRef_2< OAuthApi & OpenIdConnectApi & ProfileInfoApi & BackstageIdentityApi & SessionApi ->; +> & { + readonly $$type: '@backstage/ApiRef'; +}; // @public -export const oneloginAuthApiRef: ApiRef< +export const oneloginAuthApiRef: ApiRef_2< OAuthApi & OpenIdConnectApi & ProfileInfoApi & BackstageIdentityApi & SessionApi ->; +> & { + readonly $$type: '@backstage/ApiRef'; +}; // @public export type OpenIdConnectApi = { @@ -1573,9 +1613,11 @@ export type OpenIdConnectApi = { }; // @public -export const openshiftAuthApiRef: ApiRef< +export const openshiftAuthApiRef: ApiRef_2< OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi ->; +> & { + readonly $$type: '@backstage/ApiRef'; +}; // @public (undocumented) export interface OverridableExtensionDefinition< @@ -2055,7 +2097,9 @@ export interface StorageApi { } // @public -export const storageApiRef: ApiRef; +export const storageApiRef: ApiRef_2 & { + readonly $$type: '@backstage/ApiRef'; +}; // @public export type StorageValueSnapshot = @@ -2168,7 +2212,9 @@ export type TranslationApi = { }; // @public (undocumented) -export const translationApiRef: ApiRef; +export const translationApiRef: ApiRef_2 & { + readonly $$type: '@backstage/ApiRef'; +}; // @public (undocumented) export type TranslationFunction< @@ -2358,13 +2404,15 @@ export const useTranslationRef: ( }; // @public -export const vmwareCloudAuthApiRef: ApiRef< +export const vmwareCloudAuthApiRef: ApiRef_2< OAuthApi & OpenIdConnectApi & ProfileInfoApi & BackstageIdentityApi & SessionApi ->; +> & { + readonly $$type: '@backstage/ApiRef'; +}; // @public @deprecated export function withApis( From 76b89c743702b061c1e2cf120be606f095d16542 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Mar 2026 20:52:41 +0100 Subject: [PATCH 08/13] api-ref: infer builder ids and plugin ownership Preserve literal API ref ids in the builder form while keeping the deprecated constructor compatible, and rely on explicit ownership metadata instead of the old core id fallback. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .changeset/opaque-api-ref-type.md | 4 +- .../src/apis/system/ApiRef.test.ts | 7 +- .../src/wiring/createSpecializedApp.test.tsx | 45 ++++++++ .../src/wiring/createSpecializedApp.tsx | 7 +- .../frontend-plugin-api/report-alpha.api.md | 5 +- packages/frontend-plugin-api/report.api.md | 103 ++++++++++++------ .../src/apis/system/ApiRef.test.ts | 30 ++++- .../src/apis/system/ApiRef.ts | 47 ++++---- .../src/apis/system/types.ts | 4 +- 9 files changed, 181 insertions(+), 71 deletions(-) diff --git a/.changeset/opaque-api-ref-type.md b/.changeset/opaque-api-ref-type.md index 81f365b578..a2862e30bc 100644 --- a/.changeset/opaque-api-ref-type.md +++ b/.changeset/opaque-api-ref-type.md @@ -2,6 +2,6 @@ '@backstage/frontend-plugin-api': patch --- -Added a builder form for `createApiRef` in the new frontend system and deprecated the direct `createApiRef({ ... })` call in favor of `createApiRef().with({ ... })`. +Added a builder form for `createApiRef` in the new frontend system and deprecated the direct `createApiRef({ ... })` call in favor of `createApiRef().with({ ... })`. The builder form now also preserves literal API ref IDs in the resulting `ApiRef` type. -`ApiRef` and `ApiRefConfig` now also support an explicit `pluginId`, making it possible to declare API ownership without encoding the plugin ID into the API ref ID. +`ApiRef` now also supports an explicit `pluginId`, and the `createApiRef().with({ ... })` form can use it to declare API ownership without encoding the plugin ID into the API ref ID. diff --git a/packages/core-plugin-api/src/apis/system/ApiRef.test.ts b/packages/core-plugin-api/src/apis/system/ApiRef.test.ts index 994cde44c6..5bfb83ce3e 100644 --- a/packages/core-plugin-api/src/apis/system/ApiRef.test.ts +++ b/packages/core-plugin-api/src/apis/system/ApiRef.test.ts @@ -22,7 +22,12 @@ describe('ApiRef', () => { expect(ref.$$type).toBe('@backstage/ApiRef'); expect(ref.id).toBe('abc'); expect(String(ref)).toBe('apiRef{abc}'); - expect(() => ref.T).toThrow('tried to read ApiRef.T of apiRef{abc}'); + expect(ref.T).toBeNull(); + }); + + it('should not accept pluginId in the core createApiRef config', () => { + // @ts-expect-error pluginId is not supported in core-plugin-api + createApiRef({ id: 'abc', pluginId: 'test' }); }); it('should reject invalid ids', () => { diff --git a/packages/frontend-app-api/src/wiring/createSpecializedApp.test.tsx b/packages/frontend-app-api/src/wiring/createSpecializedApp.test.tsx index d01bc4fe9c..36f6ff250d 100644 --- a/packages/frontend-app-api/src/wiring/createSpecializedApp.test.tsx +++ b/packages/frontend-app-api/src/wiring/createSpecializedApp.test.tsx @@ -417,6 +417,51 @@ describe('createSpecializedApp', () => { expect(app.apis.get(testApiRef)).toEqual({ value: 'owner' }); }); + it('should not infer app ownership from core-prefixed API ids', () => { + const testApiRef = createApiRef<{ value: string }>({ id: 'core.shared' }); + + const app = createSpecializedApp({ + features: [ + makeAppPlugin(), + createFrontendPlugin({ + pluginId: 'other-before', + extensions: [ + ApiBlueprint.make({ + params: defineParams => + defineParams({ + api: testApiRef, + deps: {}, + factory: () => ({ value: 'other' }), + }), + }), + ], + }), + createFrontendModule({ + pluginId: 'app', + extensions: [ + ApiBlueprint.make({ + params: defineParams => + defineParams({ + api: testApiRef, + deps: {}, + factory: () => ({ value: 'app' }), + }), + }), + ], + }), + ], + }); + + expect(app.errors).toEqual([ + expect.objectContaining({ + code: 'API_FACTORY_CONFLICT', + message: expect.stringContaining("API 'core.shared'"), + }), + ]); + + expect(app.apis.get(testApiRef)).toEqual({ value: 'other' }); + }); + it('should allow API overrides within the same plugin', () => { const testApiRef = createApiRef<{ value: string }>({ id: 'test.api' }); diff --git a/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx b/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx index 7ab36f2fad..da77e31103 100644 --- a/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx +++ b/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx @@ -407,8 +407,8 @@ function createApiFactories(options: { // This allows modules to override factories provided by the plugin, but // it rejects API overrides from other plugins. In the event of a - // conflict, the owning plugin is attempted to be inferred from the API - // reference ID. + // conflict, the owning plugin is inferred from the explicit pluginId or + // legacy plugin-prefixed API reference ID. if (existingFactory && existingFactory.pluginId !== pluginId) { const shouldReplace = ownerId === pluginId && existingFactory.pluginId !== ownerId; @@ -465,9 +465,6 @@ function getApiOwnerId(apiRef: { id: string; pluginId?: string }): string { if (!prefix) { return apiRefId; } - if (prefix === 'core') { - return 'app'; - } if (prefix === 'plugin' && rest[0]) { return rest[0]; } diff --git a/packages/frontend-plugin-api/report-alpha.api.md b/packages/frontend-plugin-api/report-alpha.api.md index c1a3c71a21..921ad1039c 100644 --- a/packages/frontend-plugin-api/report-alpha.api.md +++ b/packages/frontend-plugin-api/report-alpha.api.md @@ -24,7 +24,10 @@ export type PluginWrapperApi = { }; // @public -export const pluginWrapperApiRef: ApiRef & { +export const pluginWrapperApiRef: ApiRef< + PluginWrapperApi, + 'core.plugin-wrapper' +> & { readonly $$type: '@backstage/ApiRef'; }; diff --git a/packages/frontend-plugin-api/report.api.md b/packages/frontend-plugin-api/report.api.md index 52ee10a6ac..2534d83eed 100644 --- a/packages/frontend-plugin-api/report.api.md +++ b/packages/frontend-plugin-api/report.api.md @@ -31,7 +31,7 @@ export type AlertApi = { }; // @public -export const alertApiRef: ApiRef_2 & { +export const alertApiRef: ApiRef_2 & { readonly $$type: '@backstage/ApiRef'; }; @@ -48,7 +48,7 @@ export type AnalyticsApi = { }; // @public -export const analyticsApiRef: ApiRef_2 & { +export const analyticsApiRef: ApiRef_2 & { readonly $$type: '@backstage/ApiRef'; }; @@ -191,9 +191,9 @@ export type ApiHolder = { }; // @public -export type ApiRef = { +export type ApiRef = { readonly $$type?: '@backstage/ApiRef'; - readonly id: string; + readonly id: TId; readonly pluginId?: string; readonly T: T; }; @@ -201,7 +201,6 @@ export type ApiRef = { // @public export type ApiRefConfig = { id: string; - pluginId?: string; }; // @public (undocumented) @@ -219,7 +218,7 @@ export type AppLanguageApi = { }; // @public (undocumented) -export const appLanguageApiRef: ApiRef_2 & { +export const appLanguageApiRef: ApiRef_2 & { readonly $$type: '@backstage/ApiRef'; }; @@ -294,7 +293,7 @@ export type AppThemeApi = { }; // @public -export const appThemeApiRef: ApiRef_2 & { +export const appThemeApiRef: ApiRef_2 & { readonly $$type: '@backstage/ApiRef'; }; @@ -316,13 +315,14 @@ export interface AppTreeApi { } // @public -export const appTreeApiRef: ApiRef_2 & { +export const appTreeApiRef: ApiRef_2 & { readonly $$type: '@backstage/ApiRef'; }; // @public export const atlassianAuthApiRef: ApiRef_2< - OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi + OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi, + 'core.auth.atlassian' > & { readonly $$type: '@backstage/ApiRef'; }; @@ -364,14 +364,16 @@ export type BackstageUserIdentity = { // @public export const bitbucketAuthApiRef: ApiRef_2< - OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi + OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi, + 'core.auth.bitbucket' > & { readonly $$type: '@backstage/ApiRef'; }; // @public export const bitbucketServerAuthApiRef: ApiRef_2< - OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi + OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi, + 'core.auth.bitbucket-server' > & { readonly $$type: '@backstage/ApiRef'; }; @@ -380,7 +382,7 @@ export const bitbucketServerAuthApiRef: ApiRef_2< export type ConfigApi = Config; // @public -export const configApiRef: ApiRef_2 & { +export const configApiRef: ApiRef_2 & { readonly $$type: '@backstage/ApiRef'; }; @@ -443,7 +445,12 @@ export function createApiRef(config: ApiRefConfig): ApiRef & { // @public export function createApiRef(): { - with(config: ApiRefConfig): ApiRef & { + with( + config: ApiRefConfig & { + id: TId; + pluginId?: string; + }, + ): ApiRef & { readonly $$type: '@backstage/ApiRef'; }; }; @@ -899,7 +906,7 @@ export interface DialogApiDialog { } // @public -export const dialogApiRef: ApiRef_2 & { +export const dialogApiRef: ApiRef_2 & { readonly $$type: '@backstage/ApiRef'; }; @@ -909,7 +916,7 @@ export type DiscoveryApi = { }; // @public -export const discoveryApiRef: ApiRef_2 & { +export const discoveryApiRef: ApiRef_2 & { readonly $$type: '@backstage/ApiRef'; }; @@ -935,7 +942,7 @@ export type ErrorApiErrorContext = { }; // @public -export const errorApiRef: ApiRef_2 & { +export const errorApiRef: ApiRef_2 & { readonly $$type: '@backstage/ApiRef'; }; @@ -1321,7 +1328,10 @@ export interface FeatureFlagsApi { } // @public -export const featureFlagsApiRef: ApiRef_2 & { +export const featureFlagsApiRef: ApiRef_2< + FeatureFlagsApi, + 'core.featureflags' +> & { readonly $$type: '@backstage/ApiRef'; }; @@ -1355,7 +1365,7 @@ export type FetchApi = { }; // @public -export const fetchApiRef: ApiRef_2 & { +export const fetchApiRef: ApiRef_2 & { readonly $$type: '@backstage/ApiRef'; }; @@ -1431,7 +1441,8 @@ export type FrontendPluginInfoOptions = { // @public export const githubAuthApiRef: ApiRef_2< - OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi + OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi, + 'core.auth.github' > & { readonly $$type: '@backstage/ApiRef'; }; @@ -1442,7 +1453,8 @@ export const gitlabAuthApiRef: ApiRef_2< OpenIdConnectApi & ProfileInfoApi & BackstageIdentityApi & - SessionApi + SessionApi, + 'core.auth.gitlab' > & { readonly $$type: '@backstage/ApiRef'; }; @@ -1453,7 +1465,8 @@ export const googleAuthApiRef: ApiRef_2< OpenIdConnectApi & ProfileInfoApi & BackstageIdentityApi & - SessionApi + SessionApi, + 'core.auth.google' > & { readonly $$type: '@backstage/ApiRef'; }; @@ -1476,7 +1489,7 @@ export interface IconsApi { } // @public -export const iconsApiRef: ApiRef_2 & { +export const iconsApiRef: ApiRef_2 & { readonly $$type: '@backstage/ApiRef'; }; @@ -1491,7 +1504,7 @@ export type IdentityApi = { }; // @public -export const identityApiRef: ApiRef_2 & { +export const identityApiRef: ApiRef_2 & { readonly $$type: '@backstage/ApiRef'; }; @@ -1501,7 +1514,8 @@ export const microsoftAuthApiRef: ApiRef_2< OpenIdConnectApi & ProfileInfoApi & BackstageIdentityApi & - SessionApi + SessionApi, + 'core.auth.microsoft' > & { readonly $$type: '@backstage/ApiRef'; }; @@ -1567,7 +1581,10 @@ export type OAuthRequestApi = { }; // @public -export const oauthRequestApiRef: ApiRef_2 & { +export const oauthRequestApiRef: ApiRef_2< + OAuthRequestApi, + 'core.oauthrequest' +> & { readonly $$type: '@backstage/ApiRef'; }; @@ -1591,7 +1608,8 @@ export const oktaAuthApiRef: ApiRef_2< OpenIdConnectApi & ProfileInfoApi & BackstageIdentityApi & - SessionApi + SessionApi, + 'core.auth.okta' > & { readonly $$type: '@backstage/ApiRef'; }; @@ -1602,7 +1620,8 @@ export const oneloginAuthApiRef: ApiRef_2< OpenIdConnectApi & ProfileInfoApi & BackstageIdentityApi & - SessionApi + SessionApi, + 'core.auth.onelogin' > & { readonly $$type: '@backstage/ApiRef'; }; @@ -1614,7 +1633,8 @@ export type OpenIdConnectApi = { // @public export const openshiftAuthApiRef: ApiRef_2< - OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi + OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi, + 'core.auth.openshift' > & { readonly $$type: '@backstage/ApiRef'; }; @@ -1905,7 +1925,10 @@ export type PluginHeaderActionsApi = { }; // @public -export const pluginHeaderActionsApiRef: ApiRef_2 & { +export const pluginHeaderActionsApiRef: ApiRef_2< + PluginHeaderActionsApi, + 'core.plugin-header-actions' +> & { readonly $$type: '@backstage/ApiRef'; }; @@ -1949,7 +1972,10 @@ export type PluginWrapperApi = { }; // @public -export const pluginWrapperApiRef: ApiRef_2 & { +export const pluginWrapperApiRef: ApiRef_2< + PluginWrapperApi, + 'core.plugin-wrapper' +> & { readonly $$type: '@backstage/ApiRef'; }; @@ -2057,7 +2083,10 @@ export interface RouteResolutionApi { } // @public -export const routeResolutionApiRef: ApiRef_2 & { +export const routeResolutionApiRef: ApiRef_2< + RouteResolutionApi, + 'core.route-resolution' +> & { readonly $$type: '@backstage/ApiRef'; }; @@ -2097,7 +2126,7 @@ export interface StorageApi { } // @public -export const storageApiRef: ApiRef_2 & { +export const storageApiRef: ApiRef_2 & { readonly $$type: '@backstage/ApiRef'; }; @@ -2189,7 +2218,10 @@ export interface SwappableComponentsApi { } // @public -export const swappableComponentsApiRef: ApiRef_2 & { +export const swappableComponentsApiRef: ApiRef_2< + SwappableComponentsApi, + 'core.swappable-components' +> & { readonly $$type: '@backstage/ApiRef'; }; @@ -2212,7 +2244,7 @@ export type TranslationApi = { }; // @public (undocumented) -export const translationApiRef: ApiRef_2 & { +export const translationApiRef: ApiRef_2 & { readonly $$type: '@backstage/ApiRef'; }; @@ -2409,7 +2441,8 @@ export const vmwareCloudAuthApiRef: ApiRef_2< OpenIdConnectApi & ProfileInfoApi & BackstageIdentityApi & - SessionApi + SessionApi, + 'core.auth.vmware-cloud' > & { readonly $$type: '@backstage/ApiRef'; }; diff --git a/packages/frontend-plugin-api/src/apis/system/ApiRef.test.ts b/packages/frontend-plugin-api/src/apis/system/ApiRef.test.ts index b20134cc2a..ff4b83b978 100644 --- a/packages/frontend-plugin-api/src/apis/system/ApiRef.test.ts +++ b/packages/frontend-plugin-api/src/apis/system/ApiRef.test.ts @@ -15,6 +15,7 @@ */ import { createApiRef } from './ApiRef'; +import type { ApiRef as ApiRefType } from './types'; describe('ApiRef', () => { it('should be created with config', () => { @@ -22,7 +23,22 @@ describe('ApiRef', () => { expect(ref.$$type).toBe('@backstage/ApiRef'); expect(ref.id).toBe('abc'); expect(String(ref)).toBe('apiRef{abc}'); - expect(() => ref.T).toThrow('tried to read ApiRef.T of apiRef{abc}'); + expect(ref.T).toBeNull(); + }); + + it('should not accept pluginId with deprecated config form', () => { + // @ts-expect-error pluginId is only supported through .with(...) + createApiRef({ id: 'abc', pluginId: 'test' }); + }); + + it('should keep the deprecated config form id wide', () => { + const ref = createApiRef({ id: 'abc' }); + const wideRef: ApiRefType = ref; + expect(wideRef.id).toBe('abc'); + + // @ts-expect-error deprecated config form should not infer literal ids + const literalRef: ApiRefType = ref; + expect(literalRef.id).toBe('abc'); }); it('should be created with builder pattern', () => { @@ -31,7 +47,17 @@ describe('ApiRef', () => { expect(ref.id).toBe('abc'); expect(ref.pluginId).toBe('test'); expect(String(ref)).toBe('apiRef{abc}'); - expect(() => ref.T).toThrow('tried to read ApiRef.T of apiRef{abc}'); + expect(ref.T).toBeNull(); + }); + + it('should infer literal ids with builder pattern', () => { + const ref = createApiRef().with({ id: 'abc', pluginId: 'test' }); + const literalRef: ApiRefType = ref; + expect(literalRef.id).toBe('abc'); + + // @ts-expect-error builder pattern should preserve literal ids + const wrongLiteralRef: ApiRefType = ref; + expect(wrongLiteralRef.id).toBe('abc'); }); it('should reject invalid ids', () => { diff --git a/packages/frontend-plugin-api/src/apis/system/ApiRef.ts b/packages/frontend-plugin-api/src/apis/system/ApiRef.ts index 3cc7fc6649..15f10874fc 100644 --- a/packages/frontend-plugin-api/src/apis/system/ApiRef.ts +++ b/packages/frontend-plugin-api/src/apis/system/ApiRef.ts @@ -24,6 +24,10 @@ import type { ApiRef } from './types'; */ export type ApiRefConfig = { id: string; +}; + +type ApiRefBuilderConfig = { + id: TId; pluginId?: string; }; @@ -51,24 +55,17 @@ function validateId(id: string): void { } } -function makeApiRef( - config: ApiRefConfig, -): ApiRef & { readonly $$type: '@backstage/ApiRef' } { - const ref = OpaqueApiRef.createInstance('v1', { +function makeApiRef( + config: ApiRefBuilderConfig, +): ApiRef & { readonly $$type: '@backstage/ApiRef' } { + return OpaqueApiRef.createInstance('v1', { id: config.id, ...(config.pluginId ? { pluginId: config.pluginId } : {}), - T: undefined as T, + T: null as unknown as T, toString() { return `apiRef{${config.id}}`; }, - }) as ApiRef & { readonly $$type: '@backstage/ApiRef' }; - Object.defineProperty(ref, 'T', { - get(): T { - throw new Error(`tried to read ApiRef.T of ${this}`); - }, - enumerable: false, - }); - return ref; + }) as ApiRef & { readonly $$type: '@backstage/ApiRef' }; } /** @@ -77,9 +74,9 @@ function makeApiRef( * @remarks * * The `id` is a stable identifier for the API implementation. The frontend - * system infers the owning plugin for an API from the `id`, unless you provide - * a `pluginId` explicitly. The recommended pattern is `plugin..*` - * (for example, + * system infers the owning plugin for an API from the `id`. When using the + * builder form, you can instead provide a `pluginId` explicitly. The + * recommended pattern is `plugin..*` (for example, * `plugin.catalog.entity-presentation`). This ensures that other plugins can't * mistakenly override your API implementation. * @@ -120,27 +117,31 @@ export function createApiRef( * @public */ export function createApiRef(): { - with(config: ApiRefConfig): ApiRef & { + with( + config: ApiRefConfig & { id: TId; pluginId?: string }, + ): ApiRef & { readonly $$type: '@backstage/ApiRef'; }; }; export function createApiRef(config?: ApiRefConfig): | (ApiRef & { readonly $$type: '@backstage/ApiRef' }) | { - with(config: ApiRefConfig): ApiRef & { + with( + config: ApiRefConfig & { id: TId; pluginId?: string }, + ): ApiRef & { readonly $$type: '@backstage/ApiRef'; }; } { if (config) { validateId(config.id); - return makeApiRef(config); + return makeApiRef(config); } return { - with(withConfig: ApiRefConfig): ApiRef & { - readonly $$type: '@backstage/ApiRef'; - } { + with( + withConfig: ApiRefConfig & { id: TId; pluginId?: string }, + ): ApiRef & { readonly $$type: '@backstage/ApiRef' } { validateId(withConfig.id); - return makeApiRef(withConfig); + return makeApiRef(withConfig); }, }; } diff --git a/packages/frontend-plugin-api/src/apis/system/types.ts b/packages/frontend-plugin-api/src/apis/system/types.ts index 90e7365164..50911ded1e 100644 --- a/packages/frontend-plugin-api/src/apis/system/types.ts +++ b/packages/frontend-plugin-api/src/apis/system/types.ts @@ -19,9 +19,9 @@ * * @public */ -export type ApiRef = { +export type ApiRef = { readonly $$type?: '@backstage/ApiRef'; - readonly id: string; + readonly id: TId; readonly pluginId?: string; readonly T: T; }; From ccc6b25f879b8b640a51b2a151061302a7a43a17 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 17 Mar 2026 09:34:48 +0100 Subject: [PATCH 09/13] api-ref: keep plugin ownership metadata internal Hide plugin ownership metadata from the public ApiRef type while preserving internal ownership resolution for the builder-based API ref flow. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .changeset/opaque-api-ref-type.md | 2 +- .../src/wiring/createSpecializedApp.test.tsx | 5 +++++ .../frontend-app-api/src/wiring/createSpecializedApp.tsx | 7 ++++--- packages/frontend-plugin-api/report.api.md | 1 - .../frontend-plugin-api/src/apis/system/ApiRef.test.ts | 7 ++++++- packages/frontend-plugin-api/src/apis/system/types.ts | 1 - 6 files changed, 16 insertions(+), 7 deletions(-) diff --git a/.changeset/opaque-api-ref-type.md b/.changeset/opaque-api-ref-type.md index a2862e30bc..6ae300f556 100644 --- a/.changeset/opaque-api-ref-type.md +++ b/.changeset/opaque-api-ref-type.md @@ -4,4 +4,4 @@ Added a builder form for `createApiRef` in the new frontend system and deprecated the direct `createApiRef({ ... })` call in favor of `createApiRef().with({ ... })`. The builder form now also preserves literal API ref IDs in the resulting `ApiRef` type. -`ApiRef` now also supports an explicit `pluginId`, and the `createApiRef().with({ ... })` form can use it to declare API ownership without encoding the plugin ID into the API ref ID. +The `createApiRef().with({ ... })` form can also use an explicit `pluginId` to declare API ownership without encoding the plugin ID into the API ref ID, while keeping that metadata internal to runtime handling. diff --git a/packages/frontend-app-api/src/wiring/createSpecializedApp.test.tsx b/packages/frontend-app-api/src/wiring/createSpecializedApp.test.tsx index 36f6ff250d..f954ba5750 100644 --- a/packages/frontend-app-api/src/wiring/createSpecializedApp.test.tsx +++ b/packages/frontend-app-api/src/wiring/createSpecializedApp.test.tsx @@ -168,6 +168,7 @@ describe('createSpecializedApp', () => { "factory": { "api": { "$$type": "@backstage/ApiRef", + "T": null, "id": "core.featureflags", "pluginId": "app", "toString": [Function], @@ -182,6 +183,7 @@ describe('createSpecializedApp', () => { "factory": { "api": { "$$type": "@backstage/ApiRef", + "T": null, "id": "core.app-tree", "pluginId": "app", "toString": [Function], @@ -196,6 +198,7 @@ describe('createSpecializedApp', () => { "factory": { "api": { "$$type": "@backstage/ApiRef", + "T": null, "id": "core.config", "pluginId": "app", "toString": [Function], @@ -210,6 +213,7 @@ describe('createSpecializedApp', () => { "factory": { "api": { "$$type": "@backstage/ApiRef", + "T": null, "id": "core.route-resolution", "pluginId": "app", "toString": [Function], @@ -224,6 +228,7 @@ describe('createSpecializedApp', () => { "factory": { "api": { "$$type": "@backstage/ApiRef", + "T": null, "id": "core.identity", "pluginId": "app", "toString": [Function], diff --git a/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx b/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx index da77e31103..fd009db479 100644 --- a/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx +++ b/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx @@ -455,9 +455,10 @@ function createApiFactories(options: { // TODO(Rugvip): It would be good if this was more explicit, but I think that // might need to wait for some future update for API factories. -function getApiOwnerId(apiRef: { id: string; pluginId?: string }): string { - if (apiRef.pluginId) { - return apiRef.pluginId; +function getApiOwnerId(apiRef: { id: string }): string { + const pluginId = (apiRef as { pluginId?: string }).pluginId; + if (pluginId) { + return pluginId; } const apiRefId = apiRef.id; diff --git a/packages/frontend-plugin-api/report.api.md b/packages/frontend-plugin-api/report.api.md index 2534d83eed..ae36baf2a6 100644 --- a/packages/frontend-plugin-api/report.api.md +++ b/packages/frontend-plugin-api/report.api.md @@ -194,7 +194,6 @@ export type ApiHolder = { export type ApiRef = { readonly $$type?: '@backstage/ApiRef'; readonly id: TId; - readonly pluginId?: string; readonly T: T; }; diff --git a/packages/frontend-plugin-api/src/apis/system/ApiRef.test.ts b/packages/frontend-plugin-api/src/apis/system/ApiRef.test.ts index ff4b83b978..37bf0205be 100644 --- a/packages/frontend-plugin-api/src/apis/system/ApiRef.test.ts +++ b/packages/frontend-plugin-api/src/apis/system/ApiRef.test.ts @@ -27,6 +27,8 @@ describe('ApiRef', () => { }); it('should not accept pluginId with deprecated config form', () => { + expect(createApiRef({ id: 'abc' }).id).toBe('abc'); + // @ts-expect-error pluginId is only supported through .with(...) createApiRef({ id: 'abc', pluginId: 'test' }); }); @@ -45,9 +47,12 @@ describe('ApiRef', () => { const ref = createApiRef().with({ id: 'abc', pluginId: 'test' }); expect(ref.$$type).toBe('@backstage/ApiRef'); expect(ref.id).toBe('abc'); - expect(ref.pluginId).toBe('test'); expect(String(ref)).toBe('apiRef{abc}'); expect(ref.T).toBeNull(); + expect((ref as { pluginId?: string }).pluginId).toBe('test'); + + // @ts-expect-error pluginId is internal runtime metadata + expect(ref.pluginId).toBe('test'); }); it('should infer literal ids with builder pattern', () => { diff --git a/packages/frontend-plugin-api/src/apis/system/types.ts b/packages/frontend-plugin-api/src/apis/system/types.ts index 50911ded1e..5bc6136bdf 100644 --- a/packages/frontend-plugin-api/src/apis/system/types.ts +++ b/packages/frontend-plugin-api/src/apis/system/types.ts @@ -22,7 +22,6 @@ export type ApiRef = { readonly $$type?: '@backstage/ApiRef'; readonly id: TId; - readonly pluginId?: string; readonly T: T; }; From 4690f20880a8174c77d106d9372b66a5e6454b00 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 17 Mar 2026 10:30:59 +0100 Subject: [PATCH 10/13] api-ref: use opaque metadata for owner lookup Read ApiRef plugin ownership through the internal opaque type helper and gracefully fall back to legacy ID inference for unsupported ref shapes. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .../src/wiring/createSpecializedApp.test.tsx | 59 +++++++++++++++++++ .../src/wiring/createSpecializedApp.tsx | 14 ++++- .../src/apis/system/ApiRef.ts | 4 +- 3 files changed, 73 insertions(+), 4 deletions(-) diff --git a/packages/frontend-app-api/src/wiring/createSpecializedApp.test.tsx b/packages/frontend-app-api/src/wiring/createSpecializedApp.test.tsx index f954ba5750..8a4e2b5c9b 100644 --- a/packages/frontend-app-api/src/wiring/createSpecializedApp.test.tsx +++ b/packages/frontend-app-api/src/wiring/createSpecializedApp.test.tsx @@ -16,6 +16,7 @@ import { AppTreeApi, + type ApiRef, appTreeApiRef, coreExtensionData, createExtension, @@ -422,6 +423,64 @@ describe('createSpecializedApp', () => { expect(app.apis.get(testApiRef)).toEqual({ value: 'owner' }); }); + it('should ignore plugin ownership metadata from unsupported opaque ApiRefs', () => { + const testApiRef = { + $$type: '@backstage/ApiRef', + version: 'v0', + id: 'shared.api', + pluginId: 'owner', + T: null as unknown as { value: string }, + toString() { + return 'apiRef{shared.api}'; + }, + } as ApiRef<{ value: string }, 'shared.api'> & { + readonly $$type: '@backstage/ApiRef'; + readonly version: 'v0'; + readonly pluginId: 'owner'; + }; + + const app = createSpecializedApp({ + features: [ + makeAppPlugin(), + createFrontendPlugin({ + pluginId: 'other-before', + extensions: [ + ApiBlueprint.make({ + params: defineParams => + defineParams({ + api: testApiRef, + deps: {}, + factory: () => ({ value: 'other' }), + }), + }), + ], + }), + createFrontendPlugin({ + pluginId: 'owner', + extensions: [ + ApiBlueprint.make({ + params: defineParams => + defineParams({ + api: testApiRef, + deps: {}, + factory: () => ({ value: 'owner' }), + }), + }), + ], + }), + ], + }); + + expect(app.errors).toEqual([ + expect.objectContaining({ + code: 'API_FACTORY_CONFLICT', + message: expect.stringContaining("API 'shared.api'"), + }), + ]); + + expect(app.apis.get(testApiRef)).toEqual({ value: 'other' }); + }); + it('should not infer app ownership from core-prefixed API ids', () => { const testApiRef = createApiRef<{ value: string }>({ id: 'core.shared' }); diff --git a/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx b/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx index fd009db479..20c00c8929 100644 --- a/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx +++ b/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx @@ -51,6 +51,8 @@ import { resolveExtensionDefinition, toInternalExtension, } from '../../../frontend-plugin-api/src/wiring/resolveExtensionDefinition'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { OpaqueApiRef } from '../../../frontend-plugin-api/src/apis/system/ApiRef'; import { extractRouteInfoFromAppNode, @@ -456,9 +458,15 @@ function createApiFactories(options: { // TODO(Rugvip): It would be good if this was more explicit, but I think that // might need to wait for some future update for API factories. function getApiOwnerId(apiRef: { id: string }): string { - const pluginId = (apiRef as { pluginId?: string }).pluginId; - if (pluginId) { - return pluginId; + if (OpaqueApiRef.isType(apiRef)) { + try { + const { pluginId } = OpaqueApiRef.toInternal(apiRef); + if (pluginId) { + return pluginId; + } + } catch { + // Fall back to legacy ID inference for unsupported opaque ApiRef versions. + } } const apiRefId = apiRef.id; diff --git a/packages/frontend-plugin-api/src/apis/system/ApiRef.ts b/packages/frontend-plugin-api/src/apis/system/ApiRef.ts index 15f10874fc..2d86f0a8ad 100644 --- a/packages/frontend-plugin-api/src/apis/system/ApiRef.ts +++ b/packages/frontend-plugin-api/src/apis/system/ApiRef.ts @@ -31,12 +31,14 @@ type ApiRefBuilderConfig = { pluginId?: string; }; -const OpaqueApiRef = OpaqueType.create<{ +/** @internal */ +export const OpaqueApiRef = OpaqueType.create<{ public: ApiRef & { readonly $$type: '@backstage/ApiRef'; }; versions: { readonly version: 'v1'; + readonly pluginId?: string; }; }>({ type: '@backstage/ApiRef', From 90c3a9d1c074c409268fdc7b39f449c491e43c78 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 17 Mar 2026 10:46:42 +0100 Subject: [PATCH 11/13] api-ref: preserve const ids in builder types Use a const type parameter for createApiRef().with(...) so literal API ref ids stay narrow instead of widening to string. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- packages/frontend-plugin-api/report.api.md | 2 +- packages/frontend-plugin-api/src/apis/system/ApiRef.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/frontend-plugin-api/report.api.md b/packages/frontend-plugin-api/report.api.md index ae36baf2a6..e3113e1d9b 100644 --- a/packages/frontend-plugin-api/report.api.md +++ b/packages/frontend-plugin-api/report.api.md @@ -444,7 +444,7 @@ export function createApiRef(config: ApiRefConfig): ApiRef & { // @public export function createApiRef(): { - with( + with( config: ApiRefConfig & { id: TId; pluginId?: string; diff --git a/packages/frontend-plugin-api/src/apis/system/ApiRef.ts b/packages/frontend-plugin-api/src/apis/system/ApiRef.ts index 2d86f0a8ad..2327cb0631 100644 --- a/packages/frontend-plugin-api/src/apis/system/ApiRef.ts +++ b/packages/frontend-plugin-api/src/apis/system/ApiRef.ts @@ -119,7 +119,7 @@ export function createApiRef( * @public */ export function createApiRef(): { - with( + with( config: ApiRefConfig & { id: TId; pluginId?: string }, ): ApiRef & { readonly $$type: '@backstage/ApiRef'; @@ -128,7 +128,7 @@ export function createApiRef(): { export function createApiRef(config?: ApiRefConfig): | (ApiRef & { readonly $$type: '@backstage/ApiRef' }) | { - with( + with( config: ApiRefConfig & { id: TId; pluginId?: string }, ): ApiRef & { readonly $$type: '@backstage/ApiRef'; @@ -139,7 +139,7 @@ export function createApiRef(config?: ApiRefConfig): return makeApiRef(config); } return { - with( + with( withConfig: ApiRefConfig & { id: TId; pluginId?: string }, ): ApiRef & { readonly $$type: '@backstage/ApiRef' } { validateId(withConfig.id); From cc0693ec40f9e0416b2152d6a22f20ab77f1f463 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 17 Mar 2026 11:05:00 +0100 Subject: [PATCH 12/13] api-ref: move opaque helper to frontend-internal Share the internal ApiRef opaque helper through frontend-internal and fail fast when ApiRef-shaped values have an unsupported opaque version. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .../src/wiring/createSpecializedApp.test.tsx | 73 +++++++++---------- .../src/wiring/createSpecializedApp.tsx | 13 +--- .../src/apis/OpaqueApiRef.ts | 31 ++++++++ packages/frontend-internal/src/apis/index.ts | 17 +++++ packages/frontend-internal/src/index.ts | 1 + .../src/apis/system/ApiRef.ts | 16 +--- 6 files changed, 87 insertions(+), 64 deletions(-) create mode 100644 packages/frontend-internal/src/apis/OpaqueApiRef.ts create mode 100644 packages/frontend-internal/src/apis/index.ts diff --git a/packages/frontend-app-api/src/wiring/createSpecializedApp.test.tsx b/packages/frontend-app-api/src/wiring/createSpecializedApp.test.tsx index 8a4e2b5c9b..5a011c058e 100644 --- a/packages/frontend-app-api/src/wiring/createSpecializedApp.test.tsx +++ b/packages/frontend-app-api/src/wiring/createSpecializedApp.test.tsx @@ -423,7 +423,7 @@ describe('createSpecializedApp', () => { expect(app.apis.get(testApiRef)).toEqual({ value: 'owner' }); }); - it('should ignore plugin ownership metadata from unsupported opaque ApiRefs', () => { + it('should reject unsupported opaque ApiRef versions', () => { const testApiRef = { $$type: '@backstage/ApiRef', version: 'v0', @@ -439,46 +439,39 @@ describe('createSpecializedApp', () => { readonly pluginId: 'owner'; }; - const app = createSpecializedApp({ - features: [ - makeAppPlugin(), - createFrontendPlugin({ - pluginId: 'other-before', - extensions: [ - ApiBlueprint.make({ - params: defineParams => - defineParams({ - api: testApiRef, - deps: {}, - factory: () => ({ value: 'other' }), - }), - }), - ], - }), - createFrontendPlugin({ - pluginId: 'owner', - extensions: [ - ApiBlueprint.make({ - params: defineParams => - defineParams({ - api: testApiRef, - deps: {}, - factory: () => ({ value: 'owner' }), - }), - }), - ], - }), - ], - }); - - expect(app.errors).toEqual([ - expect.objectContaining({ - code: 'API_FACTORY_CONFLICT', - message: expect.stringContaining("API 'shared.api'"), + expect(() => + createSpecializedApp({ + features: [ + makeAppPlugin(), + createFrontendPlugin({ + pluginId: 'other-before', + extensions: [ + ApiBlueprint.make({ + params: defineParams => + defineParams({ + api: testApiRef, + deps: {}, + factory: () => ({ value: 'other' }), + }), + }), + ], + }), + createFrontendPlugin({ + pluginId: 'owner', + extensions: [ + ApiBlueprint.make({ + params: defineParams => + defineParams({ + api: testApiRef, + deps: {}, + factory: () => ({ value: 'owner' }), + }), + }), + ], + }), + ], }), - ]); - - expect(app.apis.get(testApiRef)).toEqual({ value: 'other' }); + ).toThrow("Invalid opaque type instance, got version 'v0', expected 'v1'"); }); it('should not infer app ownership from core-prefixed API ids', () => { diff --git a/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx b/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx index 20c00c8929..0c47dca6f6 100644 --- a/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx +++ b/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx @@ -43,6 +43,7 @@ import { import { ApiFactoryRegistry, ApiResolver } from '@backstage/core-app-api'; import { createExtensionDataContainer, + OpaqueApiRef, OpaqueFrontendPlugin, } from '@internal/frontend'; @@ -51,8 +52,6 @@ import { resolveExtensionDefinition, toInternalExtension, } from '../../../frontend-plugin-api/src/wiring/resolveExtensionDefinition'; -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { OpaqueApiRef } from '../../../frontend-plugin-api/src/apis/system/ApiRef'; import { extractRouteInfoFromAppNode, @@ -459,13 +458,9 @@ function createApiFactories(options: { // might need to wait for some future update for API factories. function getApiOwnerId(apiRef: { id: string }): string { if (OpaqueApiRef.isType(apiRef)) { - try { - const { pluginId } = OpaqueApiRef.toInternal(apiRef); - if (pluginId) { - return pluginId; - } - } catch { - // Fall back to legacy ID inference for unsupported opaque ApiRef versions. + const { pluginId } = OpaqueApiRef.toInternal(apiRef); + if (pluginId) { + return pluginId; } } diff --git a/packages/frontend-internal/src/apis/OpaqueApiRef.ts b/packages/frontend-internal/src/apis/OpaqueApiRef.ts new file mode 100644 index 0000000000..8a1b058641 --- /dev/null +++ b/packages/frontend-internal/src/apis/OpaqueApiRef.ts @@ -0,0 +1,31 @@ +/* + * Copyright 2024 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 type { ApiRef } from '@backstage/frontend-plugin-api'; +import { OpaqueType } from '@internal/opaque'; + +export const OpaqueApiRef = OpaqueType.create<{ + public: ApiRef & { + readonly $$type: '@backstage/ApiRef'; + }; + versions: { + readonly version: 'v1'; + readonly pluginId?: string; + }; +}>({ + type: '@backstage/ApiRef', + versions: ['v1'], +}); diff --git a/packages/frontend-internal/src/apis/index.ts b/packages/frontend-internal/src/apis/index.ts new file mode 100644 index 0000000000..f445683652 --- /dev/null +++ b/packages/frontend-internal/src/apis/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2024 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. + */ + +export * from './OpaqueApiRef'; diff --git a/packages/frontend-internal/src/index.ts b/packages/frontend-internal/src/index.ts index 38bfdc53f8..447b488fca 100644 --- a/packages/frontend-internal/src/index.ts +++ b/packages/frontend-internal/src/index.ts @@ -15,4 +15,5 @@ */ export * from './routing'; +export * from './apis'; export * from './wiring'; diff --git a/packages/frontend-plugin-api/src/apis/system/ApiRef.ts b/packages/frontend-plugin-api/src/apis/system/ApiRef.ts index 2327cb0631..557341d98a 100644 --- a/packages/frontend-plugin-api/src/apis/system/ApiRef.ts +++ b/packages/frontend-plugin-api/src/apis/system/ApiRef.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { OpaqueType } from '@internal/opaque'; +import { OpaqueApiRef } from '@internal/frontend'; import type { ApiRef } from './types'; /** @@ -31,20 +31,6 @@ type ApiRefBuilderConfig = { pluginId?: string; }; -/** @internal */ -export const OpaqueApiRef = OpaqueType.create<{ - public: ApiRef & { - readonly $$type: '@backstage/ApiRef'; - }; - versions: { - readonly version: 'v1'; - readonly pluginId?: string; - }; -}>({ - type: '@backstage/ApiRef', - versions: ['v1'], -}); - function validateId(id: string): void { const valid = id .split('.') From ac560a24cb0941f5dd1cf74af28d5d3380c35cf2 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 17 Mar 2026 11:27:46 +0100 Subject: [PATCH 13/13] Regenerate API reports Update downstream app plugin API reports after the ApiRef type changes affected generated union output. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- plugins/app-react/report.api.md | 4 ++-- plugins/app/report.api.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/app-react/report.api.md b/plugins/app-react/report.api.md index a4e63e254b..4e3fff6e42 100644 --- a/plugins/app-react/report.api.md +++ b/plugins/app-react/report.api.md @@ -86,7 +86,7 @@ export const IconBundleBlueprint: ExtensionBlueprint<{ }; output: ExtensionDataRef< { - [x: string]: IconComponent | IconElement; + [x: string]: IconElement | IconComponent; }, 'core.icons', {} @@ -97,7 +97,7 @@ export const IconBundleBlueprint: ExtensionBlueprint<{ dataRefs: { icons: ConfigurableExtensionDataRef< { - [x: string]: IconComponent | IconElement; + [x: string]: IconElement | IconComponent; }, 'core.icons', {} diff --git a/plugins/app/report.api.md b/plugins/app/report.api.md index 0262c4c1ef..8347e5f447 100644 --- a/plugins/app/report.api.md +++ b/plugins/app/report.api.md @@ -478,7 +478,7 @@ const appPlugin: OverridableFrontendPlugin< icons: ExtensionInput< ConfigurableExtensionDataRef< { - [x: string]: IconComponent | IconElement; + [x: string]: IconElement | IconComponent; }, 'core.icons', {}