@@ -0,0 +1,9 @@
|
||||
---
|
||||
'@backstage/frontend-plugin-api': minor
|
||||
---
|
||||
|
||||
Removed deprecated `namespace` option from `createExtension` and `createExtensionBlueprint`, including `.make` and `.makeWithOverides`, it's no longer necessary and will use the `pluginId` instead.
|
||||
|
||||
Removed deprecated `createExtensionOverrides` this should be replaced with `createFrontendModule` instead.
|
||||
|
||||
Removed deprecated `BackstagePlugin` type, use `FrontendPlugin` type instead from this same package.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/frontend-app-api': minor
|
||||
---
|
||||
|
||||
Removed deprecated `createApp` and `CreateAppFeatureLoader` from `@backstage/frontend-app-api`, use the same `createApp` and `CreateAppFeatureLoader` import from `@backstage/frontend-defaults` instead.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/core-compat-api': patch
|
||||
---
|
||||
|
||||
Internal update to remove deprecated `BackstagePlugin` type and move to `FrontendPlugin`
|
||||
@@ -17,7 +17,6 @@ const examplePlugin: FrontendPlugin<
|
||||
{
|
||||
'page:example': ExtensionDefinition<{
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {
|
||||
path: string | undefined;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { createApp } from '@backstage/frontend-app-api';
|
||||
import { createApp } from '@backstage/frontend-defaults';
|
||||
import { pagesPlugin } from './examples/pagesPlugin';
|
||||
import notFoundErrorPage from './examples/notFoundErrorPageExtension';
|
||||
import userSettingsPlugin from '@backstage/plugin-user-settings/alpha';
|
||||
|
||||
@@ -46,9 +46,11 @@
|
||||
"@backstage/frontend-test-utils": "workspace:^",
|
||||
"@backstage/plugin-catalog": "workspace:^",
|
||||
"@backstage/test-utils": "workspace:^",
|
||||
"@backstage/types": "workspace:^",
|
||||
"@oriflame/backstage-plugin-score-card": "^0.8.0",
|
||||
"@testing-library/jest-dom": "^6.0.0",
|
||||
"@testing-library/react": "^16.0.0"
|
||||
"@testing-library/react": "^16.0.0",
|
||||
"zod": "^3.22.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.13.1 || ^17.0.0 || ^18.0.0",
|
||||
|
||||
@@ -27,11 +27,12 @@ import { PuppetDbPage } from '@backstage-community/plugin-puppetdb';
|
||||
import { StackstormPage } from '@backstage-community/plugin-stackstorm';
|
||||
import { ScoreBoardPage } from '@oriflame/backstage-plugin-score-card';
|
||||
import React, { Fragment } from 'react';
|
||||
// TODO(rugvip): this should take into account that this is a test file, so these deps don't need to be in the dependencies
|
||||
// eslint-disable-next-line @backstage/no-undeclared-imports
|
||||
import { OpaqueFrontendPlugin } from '@internal/frontend';
|
||||
import { Navigate, Route, Routes } from 'react-router-dom';
|
||||
|
||||
import { collectLegacyRoutes } from './collectLegacyRoutes';
|
||||
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
|
||||
import { toInternalFrontendPlugin } from '../../frontend-plugin-api/src/wiring/createFrontendPlugin';
|
||||
import {
|
||||
createPlugin,
|
||||
createRoutableExtension,
|
||||
@@ -55,7 +56,7 @@ describe('collectLegacyRoutes', () => {
|
||||
expect(
|
||||
collected.map(p => ({
|
||||
id: p.id,
|
||||
extensions: toInternalFrontendPlugin(p).extensions.map(e => ({
|
||||
extensions: OpaqueFrontendPlugin.toInternal(p).extensions.map(e => ({
|
||||
id: e.id,
|
||||
attachTo: e.attachTo,
|
||||
disabled: e.disabled,
|
||||
@@ -158,7 +159,7 @@ describe('collectLegacyRoutes', () => {
|
||||
expect(
|
||||
collected.map(p => ({
|
||||
id: p.id,
|
||||
extensions: toInternalFrontendPlugin(p).extensions.map(e => ({
|
||||
extensions: OpaqueFrontendPlugin.toInternal(p).extensions.map(e => ({
|
||||
id: e.id,
|
||||
attachTo: e.attachTo,
|
||||
disabled: e.disabled,
|
||||
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
getComponentData,
|
||||
} from '@backstage/core-plugin-api';
|
||||
import {
|
||||
BackstagePlugin,
|
||||
FrontendPlugin,
|
||||
ExtensionDefinition,
|
||||
coreExtensionData,
|
||||
createExtension,
|
||||
@@ -156,7 +156,7 @@ function visitRouteChildren(options: {
|
||||
/** @internal */
|
||||
export function collectLegacyRoutes(
|
||||
flatRoutesElement: JSX.Element,
|
||||
): BackstagePlugin[] {
|
||||
): FrontendPlugin[] {
|
||||
const pluginExtensions = new Map<
|
||||
LegacyBackstagePlugin,
|
||||
ExtensionDefinition[]
|
||||
|
||||
@@ -23,8 +23,9 @@ import {
|
||||
} from '@backstage/core-plugin-api';
|
||||
import { convertLegacyPlugin } from './convertLegacyPlugin';
|
||||
import { PageBlueprint } from '@backstage/frontend-plugin-api';
|
||||
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
|
||||
import { toInternalFrontendPlugin } from '../../frontend-plugin-api/src/wiring/createFrontendPlugin';
|
||||
// TODO(rugvip): this should take into account that this is a test file, so these deps don't need to be in the dependencies
|
||||
// eslint-disable-next-line @backstage/no-undeclared-imports
|
||||
import { OpaqueFrontendPlugin } from '@internal/frontend';
|
||||
|
||||
describe('convertLegacyPlugin', () => {
|
||||
it('should convert a plain legacy plugin to a new plugin', () => {
|
||||
@@ -73,7 +74,7 @@ describe('convertLegacyPlugin', () => {
|
||||
},
|
||||
);
|
||||
|
||||
const internalConverted = toInternalFrontendPlugin(converted);
|
||||
const internalConverted = OpaqueFrontendPlugin.toInternal(converted);
|
||||
|
||||
expect(internalConverted.id).toBe('test');
|
||||
expect(internalConverted.routes).toEqual({
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
```ts
|
||||
import { ConfigApi } from '@backstage/core-plugin-api';
|
||||
import { createApp as createApp_2 } from '@backstage/frontend-defaults';
|
||||
import { CreateAppFeatureLoader as CreateAppFeatureLoader_2 } from '@backstage/frontend-defaults';
|
||||
import { ExternalRouteRef } from '@backstage/frontend-plugin-api';
|
||||
import { FrontendModule } from '@backstage/frontend-plugin-api';
|
||||
import { FrontendPlugin } from '@backstage/frontend-plugin-api';
|
||||
@@ -13,12 +11,6 @@ import { JSX as JSX_2 } from 'react';
|
||||
import { RouteRef } from '@backstage/frontend-plugin-api';
|
||||
import { SubRouteRef } from '@backstage/frontend-plugin-api';
|
||||
|
||||
// @public @deprecated (undocumented)
|
||||
export const createApp: typeof createApp_2;
|
||||
|
||||
// @public @deprecated (undocumented)
|
||||
export type CreateAppFeatureLoader = CreateAppFeatureLoader_2;
|
||||
|
||||
// @public
|
||||
export type CreateAppRouteBinder = <
|
||||
TExternalRoutes extends {
|
||||
|
||||
@@ -41,7 +41,8 @@
|
||||
"@backstage/types": "workspace:^",
|
||||
"@backstage/version-bridge": "workspace:^",
|
||||
"@types/react": "^16.13.1 || ^17.0.0 || ^18.0.0",
|
||||
"lodash": "^4.17.21"
|
||||
"lodash": "^4.17.21",
|
||||
"zod": "^3.22.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "workspace:^",
|
||||
|
||||
@@ -28,8 +28,7 @@ import {
|
||||
import { toInternalExternalRouteRef } from '../../../frontend-plugin-api/src/routing/ExternalRouteRef';
|
||||
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
|
||||
import { toInternalSubRouteRef } from '../../../frontend-plugin-api/src/routing/SubRouteRef';
|
||||
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
|
||||
import { isInternalFrontendPlugin } from '../../../frontend-plugin-api/src/wiring/createFrontendPlugin';
|
||||
import { OpaqueFrontendPlugin } from '@internal/frontend';
|
||||
import { FrontendFeature } from '../wiring';
|
||||
|
||||
/** @internal */
|
||||
@@ -44,7 +43,7 @@ export function collectRouteIds(features: FrontendFeature[]): RouteRefsById {
|
||||
const externalRoutesById = new Map<string, ExternalRouteRef>();
|
||||
|
||||
for (const feature of features) {
|
||||
if (!isInternalFrontendPlugin(feature)) {
|
||||
if (!OpaqueFrontendPlugin.isType(feature)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ type TargetRouteMap<
|
||||
|
||||
/**
|
||||
* A function that can bind from external routes of a given plugin, to concrete
|
||||
* routes of other plugins. See {@link createApp}.
|
||||
* routes of other plugins. See {@link @backstage/frontend-defaults#createApp}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
|
||||
@@ -14,17 +14,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { BackstagePlugin } from '@backstage/frontend-plugin-api';
|
||||
import { FrontendPlugin } from '@backstage/frontend-plugin-api';
|
||||
import { BackstagePlugin as LegacyBackstagePlugin } from '@backstage/core-plugin-api';
|
||||
import { getOrCreateGlobalSingleton } from '@backstage/version-bridge';
|
||||
|
||||
// Make sure that we only convert each new plugin instance to its legacy equivalent once
|
||||
const legacyPluginStore = getOrCreateGlobalSingleton(
|
||||
'legacy-plugin-compatibility-store',
|
||||
() => new WeakMap<BackstagePlugin, LegacyBackstagePlugin>(),
|
||||
() => new WeakMap<FrontendPlugin, LegacyBackstagePlugin>(),
|
||||
);
|
||||
|
||||
export function toLegacyPlugin(plugin: BackstagePlugin): LegacyBackstagePlugin {
|
||||
export function toLegacyPlugin(plugin: FrontendPlugin): LegacyBackstagePlugin {
|
||||
let legacy = legacyPluginStore.get(plugin);
|
||||
if (legacy) {
|
||||
return legacy;
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
createExtensionOverrides,
|
||||
createFrontendModule,
|
||||
createFrontendPlugin,
|
||||
Extension,
|
||||
@@ -276,55 +275,6 @@ describe('resolveAppNodeSpecs', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('should apply extension overrides', () => {
|
||||
const plugin = createFrontendPlugin({
|
||||
id: 'test',
|
||||
extensions: [makeExtDef('a'), makeExtDef('b')],
|
||||
});
|
||||
const aOverride = makeExt('test/a', 'enabled', 'other');
|
||||
const bOverride = makeExt('test/b', 'disabled', 'other');
|
||||
const cOverride = makeExt('c');
|
||||
|
||||
expect(
|
||||
resolveAppNodeSpecs({
|
||||
features: [
|
||||
plugin,
|
||||
createExtensionOverrides({
|
||||
extensions: [
|
||||
makeExtDef('test/a', 'enabled', 'other'),
|
||||
makeExtDef('test/b', 'disabled', 'other'),
|
||||
makeExtDef('c'),
|
||||
],
|
||||
}),
|
||||
],
|
||||
builtinExtensions: [],
|
||||
parameters: [],
|
||||
}),
|
||||
).toEqual([
|
||||
{
|
||||
id: 'test/a',
|
||||
extension: aOverride,
|
||||
attachTo: { id: 'other', input: 'default' },
|
||||
source: plugin,
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
id: 'test/b',
|
||||
extension: bOverride,
|
||||
attachTo: { id: 'other', input: 'default' },
|
||||
source: plugin,
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
id: 'c',
|
||||
extension: cOverride,
|
||||
attachTo: { id: 'root', input: 'default' },
|
||||
source: undefined,
|
||||
disabled: false,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should apply module overrides', () => {
|
||||
const plugin = createFrontendPlugin({
|
||||
id: 'test',
|
||||
@@ -375,39 +325,6 @@ describe('resolveAppNodeSpecs', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('should use order from configuration when rather than overrides', () => {
|
||||
const result = resolveAppNodeSpecs({
|
||||
features: [
|
||||
createFrontendPlugin({
|
||||
id: 'test',
|
||||
extensions: [
|
||||
makeExtDef('a', 'disabled'),
|
||||
makeExtDef('b', 'disabled'),
|
||||
makeExtDef('c', 'disabled'),
|
||||
],
|
||||
}),
|
||||
createExtensionOverrides({
|
||||
extensions: [
|
||||
makeExtDef('test/c', 'disabled'),
|
||||
makeExtDef('test/b', 'disabled'),
|
||||
makeExtDef('test/a', 'disabled'),
|
||||
],
|
||||
}),
|
||||
],
|
||||
builtinExtensions: [],
|
||||
parameters: ['test/b', 'test/c', 'test/a'].map(id => ({
|
||||
id,
|
||||
disabled: false,
|
||||
})),
|
||||
});
|
||||
|
||||
expect(result.map(r => r.extension.id)).toEqual([
|
||||
'test/b',
|
||||
'test/c',
|
||||
'test/a',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should use order from configuration when rather than modules', () => {
|
||||
const result = resolveAppNodeSpecs({
|
||||
features: [
|
||||
@@ -460,21 +377,6 @@ describe('resolveAppNodeSpecs', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('throws an error when a forbidden extension is overridden by overrides', () => {
|
||||
expect(() =>
|
||||
resolveAppNodeSpecs({
|
||||
features: [
|
||||
createExtensionOverrides({ extensions: [makeExtDef('forbidden')] }),
|
||||
],
|
||||
builtinExtensions: [],
|
||||
parameters: [],
|
||||
forbidden: new Set(['forbidden']),
|
||||
}),
|
||||
).toThrow(
|
||||
"It is forbidden to override the following extension(s): 'forbidden', which is done by one or more extension overrides",
|
||||
);
|
||||
});
|
||||
|
||||
it('throws an error when a forbidden extension is overridden by module', () => {
|
||||
expect(() =>
|
||||
resolveAppNodeSpecs({
|
||||
|
||||
@@ -14,16 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Extension, ExtensionOverrides } from '@backstage/frontend-plugin-api';
|
||||
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
|
||||
import { toInternalExtensionOverrides } from '../../../frontend-plugin-api/src/wiring/createExtensionOverrides';
|
||||
import { Extension } from '@backstage/frontend-plugin-api';
|
||||
import { ExtensionParameters } from './readAppExtensionsConfig';
|
||||
import { AppNodeSpec } from '@backstage/frontend-plugin-api';
|
||||
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
|
||||
import {
|
||||
isInternalFrontendPlugin,
|
||||
toInternalFrontendPlugin,
|
||||
} from '../../../frontend-plugin-api/src/wiring/createFrontendPlugin';
|
||||
import { OpaqueFrontendPlugin } from '@internal/frontend';
|
||||
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
|
||||
import {
|
||||
isInternalFrontendModule,
|
||||
@@ -47,18 +41,16 @@ export function resolveAppNodeSpecs(options: {
|
||||
features = [],
|
||||
} = options;
|
||||
|
||||
const plugins = features.filter(isInternalFrontendPlugin);
|
||||
const overrides = features.filter(
|
||||
(f): f is ExtensionOverrides =>
|
||||
f.$$type === '@backstage/ExtensionOverrides',
|
||||
);
|
||||
const plugins = features.filter(OpaqueFrontendPlugin.isType);
|
||||
const modules = features.filter(isInternalFrontendModule);
|
||||
|
||||
const pluginExtensions = plugins.flatMap(source => {
|
||||
return toInternalFrontendPlugin(source).extensions.map(extension => ({
|
||||
...extension,
|
||||
source,
|
||||
}));
|
||||
return OpaqueFrontendPlugin.toInternal(source).extensions.map(
|
||||
extension => ({
|
||||
...extension,
|
||||
source,
|
||||
}),
|
||||
);
|
||||
});
|
||||
const moduleExtensions = modules.flatMap(mod =>
|
||||
toInternalFrontendModule(mod).extensions.flatMap(extension => {
|
||||
@@ -71,9 +63,6 @@ export function resolveAppNodeSpecs(options: {
|
||||
return [{ ...extension, source }];
|
||||
}),
|
||||
);
|
||||
const overrideExtensions = overrides.flatMap(
|
||||
override => toInternalExtensionOverrides(override).extensions,
|
||||
);
|
||||
|
||||
// Prevent core override
|
||||
if (pluginExtensions.some(({ id }) => forbidden.has(id))) {
|
||||
@@ -96,28 +85,6 @@ export function resolveAppNodeSpecs(options: {
|
||||
`It is forbidden to override the following extension(s): ${forbiddenStr}, which is done by a module for the following plugin(s): ${pluginsStr}`,
|
||||
);
|
||||
}
|
||||
if (overrideExtensions.some(({ id }) => forbidden.has(id))) {
|
||||
const forbiddenStr = [...forbidden].map(id => `'${id}'`).join(', ');
|
||||
throw new Error(
|
||||
`It is forbidden to override the following extension(s): ${forbiddenStr}, which is done by one or more extension overrides`,
|
||||
);
|
||||
}
|
||||
|
||||
const overrideExtensionIds = overrideExtensions.map(({ id }) => id);
|
||||
if (overrideExtensionIds.length !== new Set(overrideExtensionIds).size) {
|
||||
const counts = new Map<string, number>();
|
||||
for (const id of overrideExtensionIds) {
|
||||
counts.set(id, (counts.get(id) ?? 0) + 1);
|
||||
}
|
||||
const duplicated = Array.from(counts.entries())
|
||||
.filter(([, count]) => count > 1)
|
||||
.map(([id]) => id);
|
||||
throw new Error(
|
||||
`The following extensions had duplicate overrides: ${duplicated.join(
|
||||
', ',
|
||||
)}`,
|
||||
);
|
||||
}
|
||||
|
||||
const configuredExtensions = [
|
||||
...pluginExtensions.map(({ source, ...extension }) => {
|
||||
@@ -146,33 +113,6 @@ export function resolveAppNodeSpecs(options: {
|
||||
}),
|
||||
];
|
||||
|
||||
// Install all extension overrides
|
||||
for (const extension of overrideExtensions) {
|
||||
const internalExtension = toInternalExtension(extension);
|
||||
|
||||
// Check if our override is overriding an extension that already exists
|
||||
const index = configuredExtensions.findIndex(
|
||||
e => e.extension.id === extension.id,
|
||||
);
|
||||
if (index !== -1) {
|
||||
// Only implementation, attachment point and default disabled status are overridden, the source is kept
|
||||
configuredExtensions[index].extension = internalExtension;
|
||||
configuredExtensions[index].params.attachTo = internalExtension.attachTo;
|
||||
configuredExtensions[index].params.disabled = internalExtension.disabled;
|
||||
} else {
|
||||
// Add the extension as a new one when not overriding an existing one
|
||||
configuredExtensions.push({
|
||||
extension: internalExtension,
|
||||
params: {
|
||||
source: undefined,
|
||||
attachTo: internalExtension.attachTo,
|
||||
disabled: internalExtension.disabled,
|
||||
config: undefined,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Install all module overrides
|
||||
for (const extension of moduleExtensions) {
|
||||
const internalExtension = toInternalExtension(extension);
|
||||
|
||||
@@ -41,13 +41,8 @@ import {
|
||||
identityApiRef,
|
||||
} from '@backstage/core-plugin-api';
|
||||
import { ApiFactoryRegistry, ApiResolver } from '@backstage/core-app-api';
|
||||
import { OpaqueFrontendPlugin } from '@internal/frontend';
|
||||
|
||||
// TODO: Get rid of all of these
|
||||
|
||||
import {
|
||||
createApp as _createApp,
|
||||
CreateAppFeatureLoader as _CreateAppFeatureLoader,
|
||||
} from '@backstage/frontend-defaults';
|
||||
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
|
||||
import { resolveExtensionDefinition } from '../../../frontend-plugin-api/src/wiring/resolveExtensionDefinition';
|
||||
|
||||
@@ -58,17 +53,10 @@ import { RouteResolver } from '../routing/RouteResolver';
|
||||
import { resolveRouteBindings } from '../routing/resolveRouteBindings';
|
||||
import { collectRouteIds } from '../routing/collectRouteIds';
|
||||
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
|
||||
import {
|
||||
toInternalFrontendPlugin,
|
||||
isInternalFrontendPlugin,
|
||||
} from '../../../frontend-plugin-api/src/wiring/createFrontendPlugin';
|
||||
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
|
||||
import {
|
||||
toInternalFrontendModule,
|
||||
isInternalFrontendModule,
|
||||
} from '../../../frontend-plugin-api/src/wiring/createFrontendModule';
|
||||
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
|
||||
import { toInternalExtensionOverrides } from '../../../frontend-plugin-api/src/wiring/createExtensionOverrides';
|
||||
import { getBasePath } from '../routing/getBasePath';
|
||||
import { Root } from '../extensions/Root';
|
||||
import { resolveAppTree } from '../tree/resolveAppTree';
|
||||
@@ -93,7 +81,7 @@ function deduplicateFeatures(
|
||||
return features
|
||||
.reverse()
|
||||
.filter(feature => {
|
||||
if (!isInternalFrontendPlugin(feature)) {
|
||||
if (!OpaqueFrontendPlugin.isType(feature)) {
|
||||
return true;
|
||||
}
|
||||
if (seenIds.has(feature.id)) {
|
||||
@@ -174,19 +162,6 @@ class RouteResolutionApiProxy implements RouteResolutionApi {
|
||||
return this.#routeObjects;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @deprecated Import from `@backstage/frontend-defaults` instead.
|
||||
*/
|
||||
export const createApp = _createApp;
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @deprecated Import from `@backstage/frontend-defaults` instead.
|
||||
*/
|
||||
export type CreateAppFeatureLoader = _CreateAppFeatureLoader;
|
||||
|
||||
/**
|
||||
* Creates an empty app without any default features. This is a low-level API is
|
||||
* intended for use in tests or specialized setups. Typically wou want to use
|
||||
@@ -240,8 +215,8 @@ export function createSpecializedApp(options?: {
|
||||
const featureFlagApi = apiHolder.get(featureFlagsApiRef);
|
||||
if (featureFlagApi) {
|
||||
for (const feature of features) {
|
||||
if (isInternalFrontendPlugin(feature)) {
|
||||
toInternalFrontendPlugin(feature).featureFlags.forEach(flag =>
|
||||
if (OpaqueFrontendPlugin.isType(feature)) {
|
||||
OpaqueFrontendPlugin.toInternal(feature).featureFlags.forEach(flag =>
|
||||
featureFlagApi.registerFlag({
|
||||
name: flag.name,
|
||||
pluginId: feature.id,
|
||||
@@ -256,11 +231,6 @@ export function createSpecializedApp(options?: {
|
||||
}),
|
||||
);
|
||||
}
|
||||
if (feature.$$type === '@backstage/ExtensionOverrides') {
|
||||
toInternalExtensionOverrides(feature).featureFlags.forEach(flag =>
|
||||
featureFlagApi.registerFlag({ name: flag.name, pluginId: '' }),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,9 +14,5 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export {
|
||||
createApp,
|
||||
createSpecializedApp,
|
||||
type CreateAppFeatureLoader,
|
||||
} from './createSpecializedApp';
|
||||
export { createSpecializedApp } from './createSpecializedApp';
|
||||
export * from './types';
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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 {
|
||||
Extension,
|
||||
FeatureFlagConfig,
|
||||
FrontendPlugin,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
import { OpaqueType } from './OpaqueType';
|
||||
|
||||
export const OpaqueFrontendPlugin = OpaqueType.create<{
|
||||
public: FrontendPlugin;
|
||||
versions: {
|
||||
readonly version: 'v1';
|
||||
readonly extensions: Extension<unknown>[];
|
||||
readonly featureFlags: FeatureFlagConfig[];
|
||||
};
|
||||
}>({
|
||||
type: '@backstage/FrontendPlugin',
|
||||
versions: ['v1'],
|
||||
});
|
||||
@@ -80,16 +80,16 @@ export class OpaqueType<
|
||||
* @param value Input value expected to be an instance of this opaque type
|
||||
* @returns True if the value matches this opaque type
|
||||
*/
|
||||
isType(value: unknown): value is T['public'] {
|
||||
isType = (value: unknown): value is T['public'] => {
|
||||
return this.#isThisInternalType(value);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param value Input value expected to be an instance of this opaque type
|
||||
* @throws If the value is not an instance of this opaque type or is of an unsupported version
|
||||
* @returns The internal version of the opaque type
|
||||
*/
|
||||
toInternal(value: unknown): T['public'] & T['versions'] {
|
||||
toInternal = (value: unknown): T['public'] & T['versions'] => {
|
||||
if (!this.#isThisInternalType(value)) {
|
||||
throw new TypeError(
|
||||
`Invalid opaque type, expected '${
|
||||
@@ -113,7 +113,7 @@ export class OpaqueType<
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an instance of the opaque type, returning the public type.
|
||||
|
||||
@@ -15,3 +15,4 @@
|
||||
*/
|
||||
|
||||
export { OpaqueExtensionDefinition } from './InternalExtensionDefinition';
|
||||
export { OpaqueFrontendPlugin } from './InternalFrontendPlugin';
|
||||
|
||||
@@ -174,7 +174,6 @@ export type AnyRoutes = {
|
||||
// @public
|
||||
export const ApiBlueprint: ExtensionBlueprint<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
params: {
|
||||
factory: AnyApiFactory;
|
||||
@@ -240,13 +239,12 @@ export interface AppNodeSpec {
|
||||
// (undocumented)
|
||||
readonly id: string;
|
||||
// (undocumented)
|
||||
readonly source?: BackstagePlugin;
|
||||
readonly source?: FrontendPlugin;
|
||||
}
|
||||
|
||||
// @public
|
||||
export const AppRootElementBlueprint: ExtensionBlueprint<{
|
||||
kind: 'app-root-element';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
params: {
|
||||
element: JSX.Element | (() => JSX.Element);
|
||||
@@ -261,7 +259,6 @@ export const AppRootElementBlueprint: ExtensionBlueprint<{
|
||||
// @public
|
||||
export const AppRootWrapperBlueprint: ExtensionBlueprint<{
|
||||
kind: 'app-root-wrapper';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
params: {
|
||||
Component: ComponentType<PropsWithChildren<{}>>;
|
||||
@@ -320,15 +317,6 @@ export { BackstageIdentityApi };
|
||||
|
||||
export { BackstageIdentityResponse };
|
||||
|
||||
// @public @deprecated (undocumented)
|
||||
export type BackstagePlugin<
|
||||
TRoutes extends AnyRoutes = AnyRoutes,
|
||||
TExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes,
|
||||
TExtensionMap extends {
|
||||
[id in string]: ExtensionDefinition;
|
||||
} = {},
|
||||
> = FrontendPlugin<TRoutes, TExternalRoutes, TExtensionMap>;
|
||||
|
||||
export { BackstageUserIdentity };
|
||||
|
||||
export { bitbucketAuthApiRef };
|
||||
@@ -389,7 +377,7 @@ export const coreComponentRefs: {
|
||||
|
||||
// @public (undocumented)
|
||||
export type CoreErrorBoundaryFallbackProps = {
|
||||
plugin?: BackstagePlugin;
|
||||
plugin?: FrontendPlugin;
|
||||
error: Error;
|
||||
resetError: () => void;
|
||||
};
|
||||
@@ -455,7 +443,6 @@ export function createComponentExtension<TProps extends {}>(options: {
|
||||
};
|
||||
params: never;
|
||||
kind: 'component';
|
||||
namespace: undefined;
|
||||
name: string;
|
||||
}>;
|
||||
|
||||
@@ -494,12 +481,10 @@ export function createExtension<
|
||||
},
|
||||
UFactoryOutput extends ExtensionDataValue<any, any>,
|
||||
const TKind extends string | undefined = undefined,
|
||||
const TNamespace extends string | undefined = undefined,
|
||||
const TName extends string | undefined = undefined,
|
||||
>(
|
||||
options: CreateExtensionOptions<
|
||||
TKind,
|
||||
undefined,
|
||||
TName,
|
||||
UOutput,
|
||||
TInputs,
|
||||
@@ -523,57 +508,6 @@ export function createExtension<
|
||||
inputs: TInputs;
|
||||
params: never;
|
||||
kind: string | undefined extends TKind ? undefined : TKind;
|
||||
namespace: string | undefined extends TNamespace ? undefined : TNamespace;
|
||||
name: string | undefined extends TName ? undefined : TName;
|
||||
}>;
|
||||
|
||||
// @public @deprecated (undocumented)
|
||||
export function createExtension<
|
||||
UOutput extends AnyExtensionDataRef,
|
||||
TInputs extends {
|
||||
[inputName in string]: ExtensionInput<
|
||||
AnyExtensionDataRef,
|
||||
{
|
||||
optional: boolean;
|
||||
singleton: boolean;
|
||||
}
|
||||
>;
|
||||
},
|
||||
TConfigSchema extends {
|
||||
[key: string]: (zImpl: typeof z) => z.ZodType;
|
||||
},
|
||||
UFactoryOutput extends ExtensionDataValue<any, any>,
|
||||
const TKind extends string | undefined = undefined,
|
||||
const TNamespace extends string | undefined = undefined,
|
||||
const TName extends string | undefined = undefined,
|
||||
>(
|
||||
options: CreateExtensionOptions<
|
||||
TKind,
|
||||
TNamespace,
|
||||
TName,
|
||||
UOutput,
|
||||
TInputs,
|
||||
TConfigSchema,
|
||||
UFactoryOutput
|
||||
>,
|
||||
): ExtensionDefinition<{
|
||||
config: string extends keyof TConfigSchema
|
||||
? {}
|
||||
: {
|
||||
[key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>>;
|
||||
};
|
||||
configInput: string extends keyof TConfigSchema
|
||||
? {}
|
||||
: z.input<
|
||||
z.ZodObject<{
|
||||
[key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;
|
||||
}>
|
||||
>;
|
||||
output: UOutput;
|
||||
inputs: TInputs;
|
||||
params: never;
|
||||
kind: string | undefined extends TKind ? undefined : TKind;
|
||||
namespace: string | undefined extends TNamespace ? undefined : TNamespace;
|
||||
name: string | undefined extends TName ? undefined : TName;
|
||||
}>;
|
||||
|
||||
@@ -595,7 +529,6 @@ export function createExtensionBlueprint<
|
||||
},
|
||||
UFactoryOutput extends ExtensionDataValue<any, any>,
|
||||
TKind extends string,
|
||||
TNamespace extends undefined = undefined,
|
||||
TName extends string | undefined = undefined,
|
||||
TDataRefs extends {
|
||||
[name in string]: AnyExtensionDataRef;
|
||||
@@ -603,7 +536,6 @@ export function createExtensionBlueprint<
|
||||
>(
|
||||
options: CreateExtensionBlueprintOptions<
|
||||
TKind,
|
||||
undefined,
|
||||
TName,
|
||||
TParams,
|
||||
UOutput,
|
||||
@@ -614,64 +546,6 @@ export function createExtensionBlueprint<
|
||||
>,
|
||||
): ExtensionBlueprint<{
|
||||
kind: TKind;
|
||||
namespace: undefined;
|
||||
name: TName;
|
||||
params: TParams;
|
||||
output: UOutput;
|
||||
inputs: string extends keyof TInputs ? {} : TInputs;
|
||||
config: string extends keyof TConfigSchema
|
||||
? {}
|
||||
: {
|
||||
[key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>>;
|
||||
};
|
||||
configInput: string extends keyof TConfigSchema
|
||||
? {}
|
||||
: z.input<
|
||||
z.ZodObject<{
|
||||
[key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;
|
||||
}>
|
||||
>;
|
||||
dataRefs: TDataRefs;
|
||||
}>;
|
||||
|
||||
// @public @deprecated (undocumented)
|
||||
export function createExtensionBlueprint<
|
||||
TParams extends object,
|
||||
UOutput extends AnyExtensionDataRef,
|
||||
TInputs extends {
|
||||
[inputName in string]: ExtensionInput<
|
||||
AnyExtensionDataRef,
|
||||
{
|
||||
optional: boolean;
|
||||
singleton: boolean;
|
||||
}
|
||||
>;
|
||||
},
|
||||
TConfigSchema extends {
|
||||
[key in string]: (zImpl: typeof z) => z.ZodType;
|
||||
},
|
||||
UFactoryOutput extends ExtensionDataValue<any, any>,
|
||||
TKind extends string,
|
||||
TNamespace extends string | undefined = undefined,
|
||||
TName extends string | undefined = undefined,
|
||||
TDataRefs extends {
|
||||
[name in string]: AnyExtensionDataRef;
|
||||
} = never,
|
||||
>(
|
||||
options: CreateExtensionBlueprintOptions<
|
||||
TKind,
|
||||
TNamespace,
|
||||
TName,
|
||||
TParams,
|
||||
UOutput,
|
||||
TInputs,
|
||||
TConfigSchema,
|
||||
UFactoryOutput,
|
||||
TDataRefs
|
||||
>,
|
||||
): ExtensionBlueprint<{
|
||||
kind: TKind;
|
||||
namespace: TNamespace;
|
||||
name: TName;
|
||||
params: TParams;
|
||||
output: UOutput;
|
||||
@@ -694,7 +568,6 @@ export function createExtensionBlueprint<
|
||||
// @public (undocumented)
|
||||
export type CreateExtensionBlueprintOptions<
|
||||
TKind extends string,
|
||||
TNamespace extends string | undefined,
|
||||
TName extends string | undefined,
|
||||
TParams,
|
||||
UOutput extends AnyExtensionDataRef,
|
||||
@@ -716,7 +589,6 @@ export type CreateExtensionBlueprintOptions<
|
||||
},
|
||||
> = {
|
||||
kind: TKind;
|
||||
namespace?: TNamespace;
|
||||
attachTo: {
|
||||
id: string;
|
||||
input: string;
|
||||
@@ -786,7 +658,6 @@ export function createExtensionInput<
|
||||
// @public (undocumented)
|
||||
export type CreateExtensionOptions<
|
||||
TKind extends string | undefined,
|
||||
TNamespace extends string | undefined,
|
||||
TName extends string | undefined,
|
||||
UOutput extends AnyExtensionDataRef,
|
||||
TInputs extends {
|
||||
@@ -804,7 +675,6 @@ export type CreateExtensionOptions<
|
||||
UFactoryOutput extends ExtensionDataValue<any, any>,
|
||||
> = {
|
||||
kind?: TKind;
|
||||
namespace?: TNamespace;
|
||||
name?: TName;
|
||||
attachTo: {
|
||||
id: string;
|
||||
@@ -826,11 +696,6 @@ export type CreateExtensionOptions<
|
||||
}): Iterable<UFactoryOutput>;
|
||||
} & VerifyExtensionFactoryOutput<UOutput, UFactoryOutput>;
|
||||
|
||||
// @public @deprecated (undocumented)
|
||||
export function createExtensionOverrides(
|
||||
options: ExtensionOverridesOptions,
|
||||
): ExtensionOverrides;
|
||||
|
||||
// @public
|
||||
export function createExternalRouteRef<
|
||||
TParams extends
|
||||
@@ -892,9 +757,6 @@ export function createFrontendPlugin<
|
||||
}
|
||||
>;
|
||||
|
||||
// @public @deprecated (undocumented)
|
||||
export const createPlugin: typeof createFrontendPlugin;
|
||||
|
||||
// @public
|
||||
export function createRouteRef<
|
||||
TParams extends
|
||||
@@ -966,11 +828,7 @@ export interface ExtensionBlueprint<
|
||||
// (undocumented)
|
||||
dataRefs: T['dataRefs'];
|
||||
// (undocumented)
|
||||
make<
|
||||
TNewNamespace extends string | undefined,
|
||||
TNewName extends string | undefined,
|
||||
>(args: {
|
||||
namespace?: undefined;
|
||||
make<TNewName extends string | undefined>(args: {
|
||||
name?: TNewName;
|
||||
attachTo?: {
|
||||
id: string;
|
||||
@@ -980,7 +838,6 @@ export interface ExtensionBlueprint<
|
||||
params: T['params'];
|
||||
}): ExtensionDefinition<{
|
||||
kind: T['kind'];
|
||||
namespace: undefined;
|
||||
name: string | undefined extends TNewName ? T['name'] : TNewName;
|
||||
config: T['config'];
|
||||
configInput: T['configInput'];
|
||||
@@ -988,32 +845,7 @@ export interface ExtensionBlueprint<
|
||||
inputs: T['inputs'];
|
||||
params: T['params'];
|
||||
}>;
|
||||
// @deprecated (undocumented)
|
||||
make<
|
||||
TNewNamespace extends string | undefined,
|
||||
TNewName extends string | undefined,
|
||||
>(args: {
|
||||
namespace?: TNewNamespace;
|
||||
name?: TNewName;
|
||||
attachTo?: {
|
||||
id: string;
|
||||
input: string;
|
||||
};
|
||||
disabled?: boolean;
|
||||
params: T['params'];
|
||||
}): ExtensionDefinition<{
|
||||
kind: T['kind'];
|
||||
namespace: string | undefined extends TNewNamespace
|
||||
? T['namespace']
|
||||
: TNewNamespace;
|
||||
name: string | undefined extends TNewName ? T['name'] : TNewName;
|
||||
config: T['config'];
|
||||
configInput: T['configInput'];
|
||||
output: T['output'];
|
||||
inputs: T['inputs'];
|
||||
}>;
|
||||
makeWithOverrides<
|
||||
TNewNamespace extends string | undefined,
|
||||
TNewName extends string | undefined,
|
||||
TExtensionConfigSchema extends {
|
||||
[key in string]: (zImpl: typeof z) => z.ZodType;
|
||||
@@ -1030,7 +862,6 @@ export interface ExtensionBlueprint<
|
||||
>;
|
||||
},
|
||||
>(args: {
|
||||
namespace?: undefined;
|
||||
name?: TNewName;
|
||||
attachTo?: {
|
||||
id: string;
|
||||
@@ -1095,105 +926,14 @@ export interface ExtensionBlueprint<
|
||||
output: AnyExtensionDataRef extends UNewOutput ? T['output'] : UNewOutput;
|
||||
inputs: T['inputs'] & TExtraInputs;
|
||||
kind: T['kind'];
|
||||
namespace: undefined;
|
||||
name: string | undefined extends TNewName ? T['name'] : TNewName;
|
||||
params: T['params'];
|
||||
}>;
|
||||
// @deprecated (undocumented)
|
||||
makeWithOverrides<
|
||||
TNewNamespace extends string | undefined,
|
||||
TNewName extends string | undefined,
|
||||
TExtensionConfigSchema extends {
|
||||
[key in string]: (zImpl: typeof z) => z.ZodType;
|
||||
},
|
||||
UFactoryOutput extends ExtensionDataValue<any, any>,
|
||||
UNewOutput extends AnyExtensionDataRef,
|
||||
TExtraInputs extends {
|
||||
[inputName in string]: ExtensionInput<
|
||||
AnyExtensionDataRef,
|
||||
{
|
||||
optional: boolean;
|
||||
singleton: boolean;
|
||||
}
|
||||
>;
|
||||
},
|
||||
>(args: {
|
||||
namespace: TNewNamespace;
|
||||
name?: TNewName;
|
||||
attachTo?: {
|
||||
id: string;
|
||||
input: string;
|
||||
};
|
||||
disabled?: boolean;
|
||||
inputs?: TExtraInputs & {
|
||||
[KName in keyof T['inputs']]?: `Error: Input '${KName &
|
||||
string}' is already defined in parent definition`;
|
||||
};
|
||||
output?: Array<UNewOutput>;
|
||||
config?: {
|
||||
schema: TExtensionConfigSchema & {
|
||||
[KName in keyof T['config']]?: `Error: Config key '${KName &
|
||||
string}' is already defined in parent schema`;
|
||||
};
|
||||
};
|
||||
factory(
|
||||
originalFactory: (
|
||||
params: T['params'],
|
||||
context?: {
|
||||
config?: T['config'];
|
||||
inputs?: ResolveInputValueOverrides<NonNullable<T['inputs']>>;
|
||||
},
|
||||
) => ExtensionDataContainer<NonNullable<T['output']>>,
|
||||
context: {
|
||||
node: AppNode;
|
||||
apis: ApiHolder;
|
||||
config: T['config'] & {
|
||||
[key in keyof TExtensionConfigSchema]: z.infer<
|
||||
ReturnType<TExtensionConfigSchema[key]>
|
||||
>;
|
||||
};
|
||||
inputs: Expand<ResolvedExtensionInputs<T['inputs'] & TExtraInputs>>;
|
||||
},
|
||||
): Iterable<UFactoryOutput> &
|
||||
VerifyExtensionFactoryOutput<
|
||||
AnyExtensionDataRef extends UNewOutput
|
||||
? NonNullable<T['output']>
|
||||
: UNewOutput,
|
||||
UFactoryOutput
|
||||
>;
|
||||
}): ExtensionDefinition<{
|
||||
config: (string extends keyof TExtensionConfigSchema
|
||||
? {}
|
||||
: {
|
||||
[key in keyof TExtensionConfigSchema]: z.infer<
|
||||
ReturnType<TExtensionConfigSchema[key]>
|
||||
>;
|
||||
}) &
|
||||
T['config'];
|
||||
configInput: (string extends keyof TExtensionConfigSchema
|
||||
? {}
|
||||
: z.input<
|
||||
z.ZodObject<{
|
||||
[key in keyof TExtensionConfigSchema]: ReturnType<
|
||||
TExtensionConfigSchema[key]
|
||||
>;
|
||||
}>
|
||||
>) &
|
||||
T['configInput'];
|
||||
output: AnyExtensionDataRef extends UNewOutput ? T['output'] : UNewOutput;
|
||||
inputs: T['inputs'] & TExtraInputs;
|
||||
kind: T['kind'];
|
||||
namespace: string | undefined extends TNewNamespace
|
||||
? T['namespace']
|
||||
: TNewNamespace;
|
||||
name: string | undefined extends TNewName ? T['name'] : TNewName;
|
||||
}>;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export type ExtensionBlueprintParameters = {
|
||||
kind: string;
|
||||
namespace?: string;
|
||||
name?: string;
|
||||
params?: object;
|
||||
configInput?: {
|
||||
@@ -1367,7 +1107,6 @@ export type ExtensionDefinition<
|
||||
>,
|
||||
): ExtensionDefinition<{
|
||||
kind: T['kind'];
|
||||
namespace: T['namespace'];
|
||||
name: T['name'];
|
||||
output: AnyExtensionDataRef extends UNewOutput ? T['output'] : UNewOutput;
|
||||
inputs: T['inputs'] & TExtraInputs;
|
||||
@@ -1390,7 +1129,6 @@ export type ExtensionDefinition<
|
||||
// @public (undocumented)
|
||||
export type ExtensionDefinitionParameters = {
|
||||
kind?: string;
|
||||
namespace?: string;
|
||||
name?: string;
|
||||
configInput?: {
|
||||
[K in string]: any;
|
||||
@@ -1444,14 +1182,6 @@ export interface ExtensionOverrides {
|
||||
readonly $$type: '@backstage/ExtensionOverrides';
|
||||
}
|
||||
|
||||
// @public @deprecated (undocumented)
|
||||
export interface ExtensionOverridesOptions {
|
||||
// (undocumented)
|
||||
extensions: ExtensionDefinition[];
|
||||
// (undocumented)
|
||||
featureFlags?: FeatureFlagConfig[];
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface ExternalRouteRef<
|
||||
TParams extends AnyRouteRefParams = AnyRouteRefParams,
|
||||
@@ -1498,7 +1228,9 @@ export interface FrontendPlugin<
|
||||
TExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes,
|
||||
TExtensionMap extends {
|
||||
[id in string]: ExtensionDefinition;
|
||||
} = {},
|
||||
} = {
|
||||
[id in string]: ExtensionDefinition;
|
||||
},
|
||||
> {
|
||||
// (undocumented)
|
||||
readonly $$type: '@backstage/FrontendPlugin';
|
||||
@@ -1525,7 +1257,6 @@ export { googleAuthApiRef };
|
||||
// @public (undocumented)
|
||||
export const IconBundleBlueprint: ExtensionBlueprint<{
|
||||
kind: 'icon-bundle';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
params: {
|
||||
icons: {
|
||||
@@ -1583,7 +1314,6 @@ export { microsoftAuthApiRef };
|
||||
// @public
|
||||
export const NavItemBlueprint: ExtensionBlueprint<{
|
||||
kind: 'nav-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
params: {
|
||||
title: string;
|
||||
@@ -1618,7 +1348,6 @@ export const NavItemBlueprint: ExtensionBlueprint<{
|
||||
// @public
|
||||
export const NavLogoBlueprint: ExtensionBlueprint<{
|
||||
kind: 'nav-logo';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
params: {
|
||||
logoIcon: JSX.Element;
|
||||
@@ -1668,7 +1397,6 @@ export { OpenIdConnectApi };
|
||||
// @public
|
||||
export const PageBlueprint: ExtensionBlueprint<{
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
params: {
|
||||
defaultPath: string;
|
||||
@@ -1825,7 +1553,6 @@ export type RouteFunc<TParams extends AnyRouteRefParams> = (
|
||||
// @public (undocumented)
|
||||
export const RouterBlueprint: ExtensionBlueprint<{
|
||||
kind: 'app-router-component';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
params: {
|
||||
Component: ComponentType<PropsWithChildren<{}>>;
|
||||
@@ -1888,7 +1615,6 @@ export { SessionState };
|
||||
// @public
|
||||
export const SignInPageBlueprint: ExtensionBlueprint<{
|
||||
kind: 'sign-in-page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
params: {
|
||||
loader: () => Promise<ComponentType<SignInPageProps>>;
|
||||
@@ -1931,7 +1657,6 @@ export interface SubRouteRef<
|
||||
// @public
|
||||
export const ThemeBlueprint: ExtensionBlueprint<{
|
||||
kind: 'theme';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
params: {
|
||||
theme: AppTheme;
|
||||
@@ -1948,7 +1673,6 @@ export const ThemeBlueprint: ExtensionBlueprint<{
|
||||
// @public
|
||||
export const TranslationBlueprint: ExtensionBlueprint<{
|
||||
kind: 'translation';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
params: {
|
||||
resource: TranslationResource | TranslationMessages;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
import { createApiRef } from '@backstage/core-plugin-api';
|
||||
import { BackstagePlugin, Extension, ExtensionDataRef } from '../../wiring';
|
||||
import { FrontendPlugin, Extension, ExtensionDataRef } from '../../wiring';
|
||||
|
||||
/**
|
||||
* The specification for this {@link AppNode} in the {@link AppTree}.
|
||||
@@ -32,7 +32,7 @@ export interface AppNodeSpec {
|
||||
readonly extension: Extension<unknown, unknown>;
|
||||
readonly disabled: boolean;
|
||||
readonly config?: unknown;
|
||||
readonly source?: BackstagePlugin;
|
||||
readonly source?: FrontendPlugin;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -48,7 +48,6 @@ describe('ApiBlueprint', () => {
|
||||
"inputs": {},
|
||||
"kind": "api",
|
||||
"name": "test",
|
||||
"namespace": undefined,
|
||||
"output": [
|
||||
[Function],
|
||||
],
|
||||
@@ -123,7 +122,6 @@ describe('ApiBlueprint', () => {
|
||||
},
|
||||
"kind": "api",
|
||||
"name": "test",
|
||||
"namespace": undefined,
|
||||
"output": [
|
||||
[Function],
|
||||
],
|
||||
|
||||
@@ -38,7 +38,6 @@ describe('AppRootElementBlueprint', () => {
|
||||
"inputs": {},
|
||||
"kind": "app-root-element",
|
||||
"name": undefined,
|
||||
"namespace": undefined,
|
||||
"output": [
|
||||
[Function],
|
||||
],
|
||||
|
||||
@@ -46,7 +46,6 @@ describe('AppRootWrapperBlueprint', () => {
|
||||
"inputs": {},
|
||||
"kind": "app-root-wrapper",
|
||||
"name": undefined,
|
||||
"namespace": undefined,
|
||||
"output": [
|
||||
[Function],
|
||||
],
|
||||
|
||||
@@ -56,7 +56,6 @@ describe('NavItemBlueprint', () => {
|
||||
"inputs": {},
|
||||
"kind": "nav-item",
|
||||
"name": undefined,
|
||||
"namespace": undefined,
|
||||
"output": [
|
||||
[Function],
|
||||
],
|
||||
|
||||
@@ -41,7 +41,6 @@ describe('NavLogoBlueprint', () => {
|
||||
"inputs": {},
|
||||
"kind": "nav-logo",
|
||||
"name": undefined,
|
||||
"namespace": undefined,
|
||||
"output": [
|
||||
[Function],
|
||||
],
|
||||
|
||||
@@ -66,7 +66,6 @@ describe('PageBlueprint', () => {
|
||||
"inputs": {},
|
||||
"kind": "page",
|
||||
"name": "test-page",
|
||||
"namespace": undefined,
|
||||
"output": [
|
||||
[Function],
|
||||
[Function],
|
||||
|
||||
@@ -46,7 +46,6 @@ describe('RouterBlueprint', () => {
|
||||
"inputs": {},
|
||||
"kind": "app-router-component",
|
||||
"name": undefined,
|
||||
"namespace": undefined,
|
||||
"output": [
|
||||
[Function],
|
||||
],
|
||||
|
||||
@@ -42,7 +42,6 @@ describe('SignInPageBlueprint', () => {
|
||||
"inputs": {},
|
||||
"kind": "sign-in-page",
|
||||
"name": undefined,
|
||||
"namespace": undefined,
|
||||
"output": [
|
||||
[Function],
|
||||
],
|
||||
|
||||
@@ -42,7 +42,6 @@ describe('ThemeBlueprint', () => {
|
||||
"inputs": {},
|
||||
"kind": "theme",
|
||||
"name": "light",
|
||||
"namespace": undefined,
|
||||
"output": [
|
||||
[Function],
|
||||
],
|
||||
|
||||
@@ -57,7 +57,6 @@ describe('TranslationBlueprint', () => {
|
||||
"inputs": {},
|
||||
"kind": "translation",
|
||||
"name": "blob",
|
||||
"namespace": undefined,
|
||||
"output": [
|
||||
[Function],
|
||||
],
|
||||
|
||||
@@ -15,11 +15,11 @@
|
||||
*/
|
||||
|
||||
import React, { Component, ComponentType, PropsWithChildren } from 'react';
|
||||
import { BackstagePlugin } from '../wiring';
|
||||
import { FrontendPlugin } from '../wiring';
|
||||
import { CoreErrorBoundaryFallbackProps } from '../types';
|
||||
|
||||
type ErrorBoundaryProps = PropsWithChildren<{
|
||||
plugin?: BackstagePlugin;
|
||||
plugin?: FrontendPlugin;
|
||||
Fallback: ComponentType<CoreErrorBoundaryFallbackProps>;
|
||||
}>;
|
||||
type ErrorBoundaryState = { error?: Error };
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
import { ReactNode } from 'react';
|
||||
import { BackstagePlugin } from './wiring';
|
||||
import { FrontendPlugin } from './wiring';
|
||||
|
||||
// TODO(Rugvip): This might be a quite useful utility type, maybe add to @backstage/types?
|
||||
/**
|
||||
@@ -34,7 +34,7 @@ export type CoreNotFoundErrorPageProps = {
|
||||
|
||||
/** @public */
|
||||
export type CoreErrorBoundaryFallbackProps = {
|
||||
plugin?: BackstagePlugin;
|
||||
plugin?: FrontendPlugin;
|
||||
error: Error;
|
||||
resetError: () => void;
|
||||
};
|
||||
|
||||
@@ -718,7 +718,6 @@ describe('createExtension', () => {
|
||||
|
||||
it('should complain when overriding with incompatible output', () => {
|
||||
const testExtension = createExtension({
|
||||
namespace: 'test',
|
||||
attachTo: { id: 'root', input: 'blob' },
|
||||
output: [stringDataRef],
|
||||
factory() {
|
||||
|
||||
@@ -115,7 +115,6 @@ export type VerifyExtensionFactoryOutput<
|
||||
/** @public */
|
||||
export type CreateExtensionOptions<
|
||||
TKind extends string | undefined,
|
||||
TNamespace extends string | undefined,
|
||||
TName extends string | undefined,
|
||||
UOutput extends AnyExtensionDataRef,
|
||||
TInputs extends {
|
||||
@@ -128,7 +127,6 @@ export type CreateExtensionOptions<
|
||||
UFactoryOutput extends ExtensionDataValue<any, any>,
|
||||
> = {
|
||||
kind?: TKind;
|
||||
namespace?: TNamespace;
|
||||
name?: TName;
|
||||
attachTo: { id: string; input: string };
|
||||
disabled?: boolean;
|
||||
@@ -150,7 +148,6 @@ export type CreateExtensionOptions<
|
||||
/** @public */
|
||||
export type ExtensionDefinitionParameters = {
|
||||
kind?: string;
|
||||
namespace?: string;
|
||||
name?: string;
|
||||
configInput?: { [K in string]: any };
|
||||
config?: { [K in string]: any };
|
||||
@@ -233,7 +230,6 @@ export type ExtensionDefinition<
|
||||
>,
|
||||
): ExtensionDefinition<{
|
||||
kind: T['kind'];
|
||||
namespace: T['namespace'];
|
||||
name: T['name'];
|
||||
output: AnyExtensionDataRef extends UNewOutput ? T['output'] : UNewOutput;
|
||||
inputs: T['inputs'] & TExtraInputs;
|
||||
@@ -265,12 +261,10 @@ export function createExtension<
|
||||
TConfigSchema extends { [key: string]: (zImpl: typeof z) => z.ZodType },
|
||||
UFactoryOutput extends ExtensionDataValue<any, any>,
|
||||
const TKind extends string | undefined = undefined,
|
||||
const TNamespace extends string | undefined = undefined,
|
||||
const TName extends string | undefined = undefined,
|
||||
>(
|
||||
options: CreateExtensionOptions<
|
||||
TKind,
|
||||
undefined,
|
||||
TName,
|
||||
UOutput,
|
||||
TInputs,
|
||||
@@ -294,97 +288,6 @@ export function createExtension<
|
||||
inputs: TInputs;
|
||||
params: never;
|
||||
kind: string | undefined extends TKind ? undefined : TKind;
|
||||
namespace: string | undefined extends TNamespace ? undefined : TNamespace;
|
||||
name: string | undefined extends TName ? undefined : TName;
|
||||
}>;
|
||||
/**
|
||||
* @public
|
||||
* @deprecated namespace is no longer required, you can safely remove this option and it will default to the `pluginId`. It will be removed in a future release.
|
||||
*/
|
||||
export function createExtension<
|
||||
UOutput extends AnyExtensionDataRef,
|
||||
TInputs extends {
|
||||
[inputName in string]: ExtensionInput<
|
||||
AnyExtensionDataRef,
|
||||
{ optional: boolean; singleton: boolean }
|
||||
>;
|
||||
},
|
||||
TConfigSchema extends { [key: string]: (zImpl: typeof z) => z.ZodType },
|
||||
UFactoryOutput extends ExtensionDataValue<any, any>,
|
||||
const TKind extends string | undefined = undefined,
|
||||
const TNamespace extends string | undefined = undefined,
|
||||
const TName extends string | undefined = undefined,
|
||||
>(
|
||||
options: CreateExtensionOptions<
|
||||
TKind,
|
||||
TNamespace,
|
||||
TName,
|
||||
UOutput,
|
||||
TInputs,
|
||||
TConfigSchema,
|
||||
UFactoryOutput
|
||||
>,
|
||||
): ExtensionDefinition<{
|
||||
config: string extends keyof TConfigSchema
|
||||
? {}
|
||||
: {
|
||||
[key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>>;
|
||||
};
|
||||
configInput: string extends keyof TConfigSchema
|
||||
? {}
|
||||
: z.input<
|
||||
z.ZodObject<{
|
||||
[key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;
|
||||
}>
|
||||
>;
|
||||
output: UOutput;
|
||||
inputs: TInputs;
|
||||
params: never;
|
||||
kind: string | undefined extends TKind ? undefined : TKind;
|
||||
namespace: string | undefined extends TNamespace ? undefined : TNamespace;
|
||||
name: string | undefined extends TName ? undefined : TName;
|
||||
}>;
|
||||
export function createExtension<
|
||||
UOutput extends AnyExtensionDataRef,
|
||||
TInputs extends {
|
||||
[inputName in string]: ExtensionInput<
|
||||
AnyExtensionDataRef,
|
||||
{ optional: boolean; singleton: boolean }
|
||||
>;
|
||||
},
|
||||
TConfigSchema extends { [key: string]: (zImpl: typeof z) => z.ZodType },
|
||||
UFactoryOutput extends ExtensionDataValue<any, any>,
|
||||
const TKind extends string | undefined = undefined,
|
||||
const TNamespace extends string | undefined = undefined,
|
||||
const TName extends string | undefined = undefined,
|
||||
>(
|
||||
options: CreateExtensionOptions<
|
||||
TKind,
|
||||
TNamespace,
|
||||
TName,
|
||||
UOutput,
|
||||
TInputs,
|
||||
TConfigSchema,
|
||||
UFactoryOutput
|
||||
>,
|
||||
): ExtensionDefinition<{
|
||||
config: string extends keyof TConfigSchema
|
||||
? {}
|
||||
: {
|
||||
[key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>>;
|
||||
};
|
||||
configInput: string extends keyof TConfigSchema
|
||||
? {}
|
||||
: z.input<
|
||||
z.ZodObject<{
|
||||
[key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;
|
||||
}>
|
||||
>;
|
||||
output: UOutput;
|
||||
inputs: TInputs;
|
||||
params: object;
|
||||
kind: string | undefined extends TKind ? undefined : TKind;
|
||||
namespace: string | undefined extends TNamespace ? undefined : TNamespace;
|
||||
name: string | undefined extends TName ? undefined : TName;
|
||||
}> {
|
||||
const schemaDeclaration = options.config?.schema;
|
||||
@@ -417,11 +320,9 @@ export function createExtension<
|
||||
output: UOutput;
|
||||
inputs: TInputs;
|
||||
kind: string | undefined extends TKind ? undefined : TKind;
|
||||
namespace: string | undefined extends TNamespace ? undefined : TNamespace;
|
||||
name: string | undefined extends TName ? undefined : TName;
|
||||
},
|
||||
kind: options.kind,
|
||||
namespace: options.namespace,
|
||||
name: options.name,
|
||||
attachTo: options.attachTo,
|
||||
disabled: options.disabled ?? false,
|
||||
@@ -434,9 +335,6 @@ export function createExtension<
|
||||
if (options.kind) {
|
||||
parts.push(`kind=${options.kind}`);
|
||||
}
|
||||
if (options.namespace) {
|
||||
parts.push(`namespace=${options.namespace}`);
|
||||
}
|
||||
if (options.name) {
|
||||
parts.push(`name=${options.name}`);
|
||||
}
|
||||
@@ -467,7 +365,6 @@ export function createExtension<
|
||||
|
||||
return createExtension({
|
||||
kind: options.kind,
|
||||
namespace: options.namespace,
|
||||
name: options.name,
|
||||
attachTo: overrideOptions.attachTo ?? options.attachTo,
|
||||
disabled: overrideOptions.disabled ?? options.disabled,
|
||||
|
||||
@@ -43,7 +43,6 @@ import {
|
||||
*/
|
||||
export type CreateExtensionBlueprintOptions<
|
||||
TKind extends string,
|
||||
TNamespace extends string | undefined,
|
||||
TName extends string | undefined,
|
||||
TParams,
|
||||
UOutput extends AnyExtensionDataRef,
|
||||
@@ -58,7 +57,6 @@ export type CreateExtensionBlueprintOptions<
|
||||
TDataRefs extends { [name in string]: AnyExtensionDataRef },
|
||||
> = {
|
||||
kind: TKind;
|
||||
namespace?: TNamespace;
|
||||
attachTo: { id: string; input: string };
|
||||
disabled?: boolean;
|
||||
inputs?: TInputs;
|
||||
@@ -85,7 +83,6 @@ export type CreateExtensionBlueprintOptions<
|
||||
/** @public */
|
||||
export type ExtensionBlueprintParameters = {
|
||||
kind: string;
|
||||
namespace?: string;
|
||||
name?: string;
|
||||
params?: object;
|
||||
configInput?: { [K in string]: any };
|
||||
@@ -108,18 +105,13 @@ export interface ExtensionBlueprint<
|
||||
> {
|
||||
dataRefs: T['dataRefs'];
|
||||
|
||||
make<
|
||||
TNewNamespace extends string | undefined,
|
||||
TNewName extends string | undefined,
|
||||
>(args: {
|
||||
namespace?: undefined;
|
||||
make<TNewName extends string | undefined>(args: {
|
||||
name?: TNewName;
|
||||
attachTo?: { id: string; input: string };
|
||||
disabled?: boolean;
|
||||
params: T['params'];
|
||||
}): ExtensionDefinition<{
|
||||
kind: T['kind'];
|
||||
namespace: undefined;
|
||||
name: string | undefined extends TNewName ? T['name'] : TNewName;
|
||||
config: T['config'];
|
||||
configInput: T['configInput'];
|
||||
@@ -127,27 +119,6 @@ export interface ExtensionBlueprint<
|
||||
inputs: T['inputs'];
|
||||
params: T['params'];
|
||||
}>;
|
||||
/** @deprecated namespace is no longer required, you can safely remove this option and it will default to the `pluginId`. It will be removed in a future release. */
|
||||
make<
|
||||
TNewNamespace extends string | undefined,
|
||||
TNewName extends string | undefined,
|
||||
>(args: {
|
||||
namespace?: TNewNamespace;
|
||||
name?: TNewName;
|
||||
attachTo?: { id: string; input: string };
|
||||
disabled?: boolean;
|
||||
params: T['params'];
|
||||
}): ExtensionDefinition<{
|
||||
kind: T['kind'];
|
||||
namespace: string | undefined extends TNewNamespace
|
||||
? T['namespace']
|
||||
: TNewNamespace;
|
||||
name: string | undefined extends TNewName ? T['name'] : TNewName;
|
||||
config: T['config'];
|
||||
configInput: T['configInput'];
|
||||
output: T['output'];
|
||||
inputs: T['inputs'];
|
||||
}>;
|
||||
|
||||
/**
|
||||
* Creates a new extension from the blueprint.
|
||||
@@ -156,7 +127,6 @@ export interface ExtensionBlueprint<
|
||||
* optionally call the original factory with the same params.
|
||||
*/
|
||||
makeWithOverrides<
|
||||
TNewNamespace extends string | undefined,
|
||||
TNewName extends string | undefined,
|
||||
TExtensionConfigSchema extends {
|
||||
[key in string]: (zImpl: typeof z) => z.ZodType;
|
||||
@@ -170,7 +140,6 @@ export interface ExtensionBlueprint<
|
||||
>;
|
||||
},
|
||||
>(args: {
|
||||
namespace?: undefined;
|
||||
name?: TNewName;
|
||||
attachTo?: { id: string; input: string };
|
||||
disabled?: boolean;
|
||||
@@ -232,93 +201,9 @@ export interface ExtensionBlueprint<
|
||||
output: AnyExtensionDataRef extends UNewOutput ? T['output'] : UNewOutput;
|
||||
inputs: T['inputs'] & TExtraInputs;
|
||||
kind: T['kind'];
|
||||
namespace: undefined;
|
||||
name: string | undefined extends TNewName ? T['name'] : TNewName;
|
||||
params: T['params'];
|
||||
}>;
|
||||
/** @deprecated namespace is no longer required, you can safely remove this option and it will default to the `pluginId`. It will be removed in a future release. */
|
||||
makeWithOverrides<
|
||||
TNewNamespace extends string | undefined,
|
||||
TNewName extends string | undefined,
|
||||
TExtensionConfigSchema extends {
|
||||
[key in string]: (zImpl: typeof z) => z.ZodType;
|
||||
},
|
||||
UFactoryOutput extends ExtensionDataValue<any, any>,
|
||||
UNewOutput extends AnyExtensionDataRef,
|
||||
TExtraInputs extends {
|
||||
[inputName in string]: ExtensionInput<
|
||||
AnyExtensionDataRef,
|
||||
{ optional: boolean; singleton: boolean }
|
||||
>;
|
||||
},
|
||||
>(args: {
|
||||
namespace: TNewNamespace;
|
||||
name?: TNewName;
|
||||
attachTo?: { id: string; input: string };
|
||||
disabled?: boolean;
|
||||
inputs?: TExtraInputs & {
|
||||
[KName in keyof T['inputs']]?: `Error: Input '${KName &
|
||||
string}' is already defined in parent definition`;
|
||||
};
|
||||
output?: Array<UNewOutput>;
|
||||
config?: {
|
||||
schema: TExtensionConfigSchema & {
|
||||
[KName in keyof T['config']]?: `Error: Config key '${KName &
|
||||
string}' is already defined in parent schema`;
|
||||
};
|
||||
};
|
||||
factory(
|
||||
originalFactory: (
|
||||
params: T['params'],
|
||||
context?: {
|
||||
config?: T['config'];
|
||||
inputs?: ResolveInputValueOverrides<NonNullable<T['inputs']>>;
|
||||
},
|
||||
) => ExtensionDataContainer<NonNullable<T['output']>>,
|
||||
context: {
|
||||
node: AppNode;
|
||||
apis: ApiHolder;
|
||||
config: T['config'] & {
|
||||
[key in keyof TExtensionConfigSchema]: z.infer<
|
||||
ReturnType<TExtensionConfigSchema[key]>
|
||||
>;
|
||||
};
|
||||
inputs: Expand<ResolvedExtensionInputs<T['inputs'] & TExtraInputs>>;
|
||||
},
|
||||
): Iterable<UFactoryOutput> &
|
||||
VerifyExtensionFactoryOutput<
|
||||
AnyExtensionDataRef extends UNewOutput
|
||||
? NonNullable<T['output']>
|
||||
: UNewOutput,
|
||||
UFactoryOutput
|
||||
>;
|
||||
}): ExtensionDefinition<{
|
||||
config: (string extends keyof TExtensionConfigSchema
|
||||
? {}
|
||||
: {
|
||||
[key in keyof TExtensionConfigSchema]: z.infer<
|
||||
ReturnType<TExtensionConfigSchema[key]>
|
||||
>;
|
||||
}) &
|
||||
T['config'];
|
||||
configInput: (string extends keyof TExtensionConfigSchema
|
||||
? {}
|
||||
: z.input<
|
||||
z.ZodObject<{
|
||||
[key in keyof TExtensionConfigSchema]: ReturnType<
|
||||
TExtensionConfigSchema[key]
|
||||
>;
|
||||
}>
|
||||
>) &
|
||||
T['configInput'];
|
||||
output: AnyExtensionDataRef extends UNewOutput ? T['output'] : UNewOutput;
|
||||
inputs: T['inputs'] & TExtraInputs;
|
||||
kind: T['kind'];
|
||||
namespace: string | undefined extends TNewNamespace
|
||||
? T['namespace']
|
||||
: TNewNamespace;
|
||||
name: string | undefined extends TNewName ? T['name'] : TNewName;
|
||||
}>;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -339,13 +224,11 @@ export function createExtensionBlueprint<
|
||||
TConfigSchema extends { [key in string]: (zImpl: typeof z) => z.ZodType },
|
||||
UFactoryOutput extends ExtensionDataValue<any, any>,
|
||||
TKind extends string,
|
||||
TNamespace extends undefined = undefined,
|
||||
TName extends string | undefined = undefined,
|
||||
TDataRefs extends { [name in string]: AnyExtensionDataRef } = never,
|
||||
>(
|
||||
options: CreateExtensionBlueprintOptions<
|
||||
TKind,
|
||||
undefined,
|
||||
TName,
|
||||
TParams,
|
||||
UOutput,
|
||||
@@ -356,57 +239,6 @@ export function createExtensionBlueprint<
|
||||
>,
|
||||
): ExtensionBlueprint<{
|
||||
kind: TKind;
|
||||
namespace: undefined;
|
||||
name: TName;
|
||||
params: TParams;
|
||||
output: UOutput;
|
||||
inputs: string extends keyof TInputs ? {} : TInputs;
|
||||
config: string extends keyof TConfigSchema
|
||||
? {}
|
||||
: { [key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>> };
|
||||
configInput: string extends keyof TConfigSchema
|
||||
? {}
|
||||
: z.input<
|
||||
z.ZodObject<{
|
||||
[key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;
|
||||
}>
|
||||
>;
|
||||
dataRefs: TDataRefs;
|
||||
}>;
|
||||
/**
|
||||
* @public
|
||||
* @deprecated the namespace is no longer required, you can safely remove this option and it will default to the `pluginId`. It will be removed in a future release.
|
||||
*/
|
||||
export function createExtensionBlueprint<
|
||||
TParams extends object,
|
||||
UOutput extends AnyExtensionDataRef,
|
||||
TInputs extends {
|
||||
[inputName in string]: ExtensionInput<
|
||||
AnyExtensionDataRef,
|
||||
{ optional: boolean; singleton: boolean }
|
||||
>;
|
||||
},
|
||||
TConfigSchema extends { [key in string]: (zImpl: typeof z) => z.ZodType },
|
||||
UFactoryOutput extends ExtensionDataValue<any, any>,
|
||||
TKind extends string,
|
||||
TNamespace extends string | undefined = undefined,
|
||||
TName extends string | undefined = undefined,
|
||||
TDataRefs extends { [name in string]: AnyExtensionDataRef } = never,
|
||||
>(
|
||||
options: CreateExtensionBlueprintOptions<
|
||||
TKind,
|
||||
TNamespace,
|
||||
TName,
|
||||
TParams,
|
||||
UOutput,
|
||||
TInputs,
|
||||
TConfigSchema,
|
||||
UFactoryOutput,
|
||||
TDataRefs
|
||||
>,
|
||||
): ExtensionBlueprint<{
|
||||
kind: TKind;
|
||||
namespace: TNamespace;
|
||||
name: TName;
|
||||
params: TParams;
|
||||
output: UOutput;
|
||||
@@ -435,13 +267,11 @@ export function createExtensionBlueprint<
|
||||
TConfigSchema extends { [key in string]: (zImpl: typeof z) => z.ZodType },
|
||||
UFactoryOutput extends ExtensionDataValue<any, any>,
|
||||
TKind extends string,
|
||||
TNamespace extends string | undefined = undefined,
|
||||
TName extends string | undefined = undefined,
|
||||
TDataRefs extends { [name in string]: AnyExtensionDataRef } = never,
|
||||
>(
|
||||
options: CreateExtensionBlueprintOptions<
|
||||
TKind,
|
||||
TNamespace,
|
||||
TName,
|
||||
TParams,
|
||||
UOutput,
|
||||
@@ -452,7 +282,6 @@ export function createExtensionBlueprint<
|
||||
>,
|
||||
): ExtensionBlueprint<{
|
||||
kind: TKind;
|
||||
namespace: TNamespace;
|
||||
name: TName;
|
||||
params: TParams;
|
||||
output: UOutput;
|
||||
@@ -474,7 +303,6 @@ export function createExtensionBlueprint<
|
||||
make(args) {
|
||||
return createExtension({
|
||||
kind: options.kind,
|
||||
namespace: args.namespace ?? options.namespace,
|
||||
name: args.name ?? options.name,
|
||||
attachTo: args.attachTo ?? options.attachTo,
|
||||
disabled: args.disabled ?? options.disabled,
|
||||
@@ -491,7 +319,6 @@ export function createExtensionBlueprint<
|
||||
makeWithOverrides(args) {
|
||||
return createExtension({
|
||||
kind: options.kind,
|
||||
namespace: args.namespace ?? options.namespace,
|
||||
name: args.name ?? options.name,
|
||||
attachTo: args.attachTo ?? options.attachTo,
|
||||
disabled: args.disabled ?? options.disabled,
|
||||
@@ -539,7 +366,6 @@ export function createExtensionBlueprint<
|
||||
},
|
||||
} as ExtensionBlueprint<{
|
||||
kind: TKind;
|
||||
namespace: TNamespace;
|
||||
name: TName;
|
||||
params: TParams;
|
||||
output: UOutput;
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
/*
|
||||
* Copyright 2023 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { createExtension } from './createExtension';
|
||||
import {
|
||||
createExtensionOverrides,
|
||||
toInternalExtensionOverrides,
|
||||
} from './createExtensionOverrides';
|
||||
|
||||
describe('createExtensionOverrides', () => {
|
||||
it('should create overrides without extensions', () => {
|
||||
expect(createExtensionOverrides({ extensions: [] })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$$type": "@backstage/ExtensionOverrides",
|
||||
"extensions": [],
|
||||
"featureFlags": [],
|
||||
"toString": [Function],
|
||||
"version": "v1",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('should create overrides with extensions', () => {
|
||||
expect(
|
||||
createExtensionOverrides({
|
||||
extensions: [
|
||||
createExtension({
|
||||
name: 'a',
|
||||
attachTo: { id: 'app', input: 'apis' },
|
||||
output: [],
|
||||
factory: () => [],
|
||||
}),
|
||||
createExtension({
|
||||
namespace: 'b',
|
||||
attachTo: { id: 'app', input: 'apis' },
|
||||
output: [],
|
||||
factory: () => [],
|
||||
}),
|
||||
createExtension({
|
||||
kind: 'k',
|
||||
namespace: 'c',
|
||||
name: 'n',
|
||||
attachTo: { id: 'app', input: 'apis' },
|
||||
output: [],
|
||||
factory: () => [],
|
||||
}),
|
||||
],
|
||||
}),
|
||||
).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$$type": "@backstage/ExtensionOverrides",
|
||||
"extensions": [
|
||||
{
|
||||
"$$type": "@backstage/Extension",
|
||||
"T": undefined,
|
||||
"attachTo": {
|
||||
"id": "app",
|
||||
"input": "apis",
|
||||
},
|
||||
"configSchema": undefined,
|
||||
"disabled": false,
|
||||
"factory": [Function],
|
||||
"id": "a",
|
||||
"inputs": {},
|
||||
"output": [],
|
||||
"toString": [Function],
|
||||
"version": "v2",
|
||||
},
|
||||
{
|
||||
"$$type": "@backstage/Extension",
|
||||
"T": undefined,
|
||||
"attachTo": {
|
||||
"id": "app",
|
||||
"input": "apis",
|
||||
},
|
||||
"configSchema": undefined,
|
||||
"disabled": false,
|
||||
"factory": [Function],
|
||||
"id": "b",
|
||||
"inputs": {},
|
||||
"output": [],
|
||||
"toString": [Function],
|
||||
"version": "v2",
|
||||
},
|
||||
{
|
||||
"$$type": "@backstage/Extension",
|
||||
"T": undefined,
|
||||
"attachTo": {
|
||||
"id": "app",
|
||||
"input": "apis",
|
||||
},
|
||||
"configSchema": undefined,
|
||||
"disabled": false,
|
||||
"factory": [Function],
|
||||
"id": "k:c/n",
|
||||
"inputs": {},
|
||||
"output": [],
|
||||
"toString": [Function],
|
||||
"version": "v2",
|
||||
},
|
||||
],
|
||||
"featureFlags": [],
|
||||
"toString": [Function],
|
||||
"version": "v1",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('should convert to internal overrides', () => {
|
||||
const overrides = createExtensionOverrides({
|
||||
extensions: [
|
||||
createExtension({
|
||||
namespace: 'a',
|
||||
attachTo: { id: 'app', input: 'apis' },
|
||||
output: [],
|
||||
factory: () => [],
|
||||
}),
|
||||
],
|
||||
});
|
||||
const internal = toInternalExtensionOverrides(overrides);
|
||||
expect(internal).toBe(overrides);
|
||||
});
|
||||
});
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Copyright 2023 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ExtensionDefinition } from './createExtension';
|
||||
import {
|
||||
Extension,
|
||||
resolveExtensionDefinition,
|
||||
} from './resolveExtensionDefinition';
|
||||
import { ExtensionOverrides, FeatureFlagConfig } from './types';
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link createFrontendModule} instead.
|
||||
* @public
|
||||
*/
|
||||
export interface ExtensionOverridesOptions {
|
||||
extensions: ExtensionDefinition[];
|
||||
featureFlags?: FeatureFlagConfig[];
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface InternalExtensionOverrides extends ExtensionOverrides {
|
||||
readonly version: 'v1';
|
||||
readonly extensions: Extension<unknown>[];
|
||||
readonly featureFlags: FeatureFlagConfig[];
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link createFrontendModule} instead.
|
||||
* @public
|
||||
*/
|
||||
export function createExtensionOverrides(
|
||||
options: ExtensionOverridesOptions,
|
||||
): ExtensionOverrides {
|
||||
const extensions = options.extensions.map(def =>
|
||||
resolveExtensionDefinition(def),
|
||||
);
|
||||
const featureFlags = options.featureFlags ?? [];
|
||||
return {
|
||||
$$type: '@backstage/ExtensionOverrides',
|
||||
version: 'v1',
|
||||
extensions,
|
||||
featureFlags,
|
||||
toString() {
|
||||
const ex = extensions.map(String).join(',');
|
||||
const ff = featureFlags.map(f => f.name).join(',');
|
||||
return `ExtensionOverrides{extensions=[${ex}],featureFlags=[${ff}]}`;
|
||||
},
|
||||
} as InternalExtensionOverrides;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function toInternalExtensionOverrides(
|
||||
overrides: ExtensionOverrides,
|
||||
): InternalExtensionOverrides {
|
||||
const internal = overrides as InternalExtensionOverrides;
|
||||
if (internal.$$type !== '@backstage/ExtensionOverrides') {
|
||||
throw new Error(
|
||||
`Invalid extension overrides instance, bad type '${internal.$$type}'`,
|
||||
);
|
||||
}
|
||||
if (internal.version !== 'v1') {
|
||||
throw new Error(
|
||||
`Invalid extension overrides instance, bad version '${internal.version}'`,
|
||||
);
|
||||
}
|
||||
return internal;
|
||||
}
|
||||
@@ -15,7 +15,8 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { createApp } from '@backstage/frontend-app-api';
|
||||
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
|
||||
import { createApp } from '../../../frontend-defaults/src/createApp';
|
||||
import { screen } from '@testing-library/react';
|
||||
import { FrontendPlugin, createFrontendPlugin } from './createFrontendPlugin';
|
||||
import { JsonObject } from '@backstage/types';
|
||||
@@ -170,7 +171,9 @@ describe('createFrontendPlugin', () => {
|
||||
}
|
||||
`);
|
||||
// @ts-expect-error
|
||||
expect(plugin.getExtension('nonexistent')).toBeUndefined();
|
||||
expect(() => plugin.getExtension('nonexistent')).toThrow(
|
||||
/Attempted to get non-existent extension/,
|
||||
);
|
||||
|
||||
await renderWithEffects(
|
||||
createTestAppRoot({
|
||||
|
||||
@@ -14,7 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { OpaqueExtensionDefinition } from '@internal/frontend';
|
||||
import {
|
||||
OpaqueExtensionDefinition,
|
||||
OpaqueFrontendPlugin,
|
||||
} from '@internal/frontend';
|
||||
import { ExtensionDefinition } from './createExtension';
|
||||
import {
|
||||
Extension,
|
||||
@@ -27,7 +30,9 @@ import { AnyExternalRoutes, AnyRoutes, FeatureFlagConfig } from './types';
|
||||
export interface FrontendPlugin<
|
||||
TRoutes extends AnyRoutes = AnyRoutes,
|
||||
TExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes,
|
||||
TExtensionMap extends { [id in string]: ExtensionDefinition } = {},
|
||||
TExtensionMap extends { [id in string]: ExtensionDefinition } = {
|
||||
[id in string]: ExtensionDefinition;
|
||||
},
|
||||
> {
|
||||
readonly $$type: '@backstage/FrontendPlugin';
|
||||
readonly id: string;
|
||||
@@ -39,15 +44,6 @@ export interface FrontendPlugin<
|
||||
}): FrontendPlugin<TRoutes, TExternalRoutes, TExtensionMap>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @deprecated Use {@link FrontendPlugin} instead.
|
||||
*/
|
||||
export type BackstagePlugin<
|
||||
TRoutes extends AnyRoutes = AnyRoutes,
|
||||
TExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes,
|
||||
TExtensionMap extends { [id in string]: ExtensionDefinition } = {},
|
||||
> = FrontendPlugin<TRoutes, TExternalRoutes, TExtensionMap>;
|
||||
/** @public */
|
||||
export interface PluginOptions<
|
||||
TId extends string,
|
||||
@@ -62,16 +58,6 @@ export interface PluginOptions<
|
||||
featureFlags?: FeatureFlagConfig[];
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export interface InternalFrontendPlugin<
|
||||
TRoutes extends AnyRoutes = AnyRoutes,
|
||||
TExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes,
|
||||
> extends FrontendPlugin<TRoutes, TExternalRoutes> {
|
||||
readonly version: 'v1';
|
||||
readonly extensions: Extension<unknown>[];
|
||||
readonly featureFlags: FeatureFlagConfig[];
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export function createFrontendPlugin<
|
||||
TId extends string,
|
||||
@@ -121,16 +107,20 @@ export function createFrontendPlugin<
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
$$type: '@backstage/FrontendPlugin',
|
||||
version: 'v1',
|
||||
return OpaqueFrontendPlugin.createInstance('v1', {
|
||||
id: options.id,
|
||||
routes: options.routes ?? ({} as TRoutes),
|
||||
externalRoutes: options.externalRoutes ?? ({} as TExternalRoutes),
|
||||
featureFlags: options.featureFlags ?? [],
|
||||
extensions,
|
||||
extensions: extensions,
|
||||
getExtension(id) {
|
||||
return extensionDefinitionsById.get(id);
|
||||
const ext = extensionDefinitionsById.get(id);
|
||||
if (!ext) {
|
||||
throw new Error(
|
||||
`Attempted to get non-existent extension '${id}' from plugin '${options.id}'`,
|
||||
);
|
||||
}
|
||||
return ext;
|
||||
},
|
||||
toString() {
|
||||
return `Plugin{id=${options.id}}`;
|
||||
@@ -152,45 +142,5 @@ export function createFrontendPlugin<
|
||||
extensions: [...nonOverriddenExtensions, ...overrides.extensions],
|
||||
});
|
||||
},
|
||||
} as InternalFrontendPlugin<TRoutes, TExternalRoutes>;
|
||||
});
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isInternalFrontendPlugin(opaque: {
|
||||
$$type: string;
|
||||
}): opaque is InternalFrontendPlugin {
|
||||
if (
|
||||
opaque.$$type === '@backstage/FrontendPlugin' ||
|
||||
opaque.$$type === '@backstage/BackstagePlugin'
|
||||
) {
|
||||
// Make sure we throw if invalid
|
||||
toInternalFrontendPlugin(opaque as FrontendPlugin);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function toInternalFrontendPlugin(
|
||||
plugin: FrontendPlugin,
|
||||
): InternalFrontendPlugin {
|
||||
const internal = plugin as InternalFrontendPlugin;
|
||||
if (
|
||||
internal.$$type !== '@backstage/FrontendPlugin' &&
|
||||
internal.$$type !== '@backstage/BackstagePlugin'
|
||||
) {
|
||||
throw new Error(`Invalid plugin instance, bad type '${internal.$$type}'`);
|
||||
}
|
||||
if (internal.version !== 'v1') {
|
||||
throw new Error(
|
||||
`Invalid plugin instance, bad version '${internal.version}'`,
|
||||
);
|
||||
}
|
||||
return internal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @deprecated Use {@link createFrontendPlugin} instead.
|
||||
*/
|
||||
export const createPlugin = createFrontendPlugin;
|
||||
|
||||
@@ -37,10 +37,8 @@ export {
|
||||
type ConfigurableExtensionDataRef,
|
||||
} from './createExtensionDataRef';
|
||||
export {
|
||||
createPlugin,
|
||||
createFrontendPlugin,
|
||||
type FrontendPlugin,
|
||||
type BackstagePlugin,
|
||||
type PluginOptions,
|
||||
} from './createFrontendPlugin';
|
||||
export {
|
||||
@@ -48,10 +46,6 @@ export {
|
||||
type FrontendModule,
|
||||
type CreateFrontendModuleOptions,
|
||||
} from './createFrontendModule';
|
||||
export {
|
||||
createExtensionOverrides,
|
||||
type ExtensionOverridesOptions,
|
||||
} from './createExtensionOverrides';
|
||||
export { type Extension } from './resolveExtensionDefinition';
|
||||
export {
|
||||
type AnyRoutes,
|
||||
|
||||
@@ -108,103 +108,42 @@ describe('ResolveExtensionId', () => {
|
||||
it('should resolve extension IDs correctly', () => {
|
||||
type NamedExtension<
|
||||
TKind extends string | undefined,
|
||||
TNamespace extends string | undefined,
|
||||
TName extends string | undefined,
|
||||
> = ExtensionDefinition<{
|
||||
kind: TKind;
|
||||
namespace: TNamespace;
|
||||
name: TName;
|
||||
output: any;
|
||||
}>;
|
||||
|
||||
const id1: 'k:ns' = {} as ResolveExtensionId<
|
||||
NamedExtension<'k', 'ns', undefined>,
|
||||
undefined
|
||||
NamedExtension<'k', undefined>,
|
||||
'ns'
|
||||
>;
|
||||
const id2: 'k:n' = {} as ResolveExtensionId<
|
||||
NamedExtension<'k', undefined, 'n'>,
|
||||
undefined
|
||||
|
||||
const id2: 'ns/n' = {} as ResolveExtensionId<
|
||||
NamedExtension<undefined, 'n'>,
|
||||
'ns'
|
||||
>;
|
||||
const id3: 'ns/n' = {} as ResolveExtensionId<
|
||||
NamedExtension<undefined, 'ns', 'n'>,
|
||||
undefined
|
||||
|
||||
const id3: 'ns' = {} as ResolveExtensionId<
|
||||
NamedExtension<undefined, undefined>,
|
||||
'ns'
|
||||
>;
|
||||
const id4: never = {} as ResolveExtensionId<
|
||||
NamedExtension<'k', undefined, undefined>,
|
||||
undefined
|
||||
>;
|
||||
const id5: 'ns' = {} as ResolveExtensionId<
|
||||
NamedExtension<undefined, 'ns', undefined>,
|
||||
undefined
|
||||
>;
|
||||
const id6: 'n' = {} as ResolveExtensionId<
|
||||
NamedExtension<undefined, undefined, 'n'>,
|
||||
undefined
|
||||
>;
|
||||
const id7: 'k:ns/n' = {} as ResolveExtensionId<
|
||||
NamedExtension<'k', 'ns', 'n'>,
|
||||
undefined
|
||||
>;
|
||||
const id8: 'k:ns2' = {} as ResolveExtensionId<
|
||||
NamedExtension<'k', 'ns', undefined>,
|
||||
'ns2'
|
||||
>;
|
||||
const id9: 'k:ns2/n' = {} as ResolveExtensionId<
|
||||
NamedExtension<'k', undefined, 'n'>,
|
||||
'ns2'
|
||||
>;
|
||||
const ida: 'ns2/n' = {} as ResolveExtensionId<
|
||||
NamedExtension<undefined, 'ns', 'n'>,
|
||||
'ns2'
|
||||
>;
|
||||
const idb: 'k:ns2' = {} as ResolveExtensionId<
|
||||
NamedExtension<'k', undefined, undefined>,
|
||||
'ns2'
|
||||
>;
|
||||
const idc: 'ns2' = {} as ResolveExtensionId<
|
||||
NamedExtension<undefined, 'ns', undefined>,
|
||||
'ns2'
|
||||
>;
|
||||
const idd: 'ns2/n' = {} as ResolveExtensionId<
|
||||
NamedExtension<undefined, undefined, 'n'>,
|
||||
'ns2'
|
||||
>;
|
||||
const ide: 'k:ns2/n' = {} as ResolveExtensionId<
|
||||
NamedExtension<'k', 'ns', 'n'>,
|
||||
'ns2'
|
||||
|
||||
const id4: 'k:ns/n' = {} as ResolveExtensionId<
|
||||
NamedExtension<'k', 'n'>,
|
||||
'ns'
|
||||
>;
|
||||
|
||||
const invalid1: never = {} as ResolveExtensionId<
|
||||
NamedExtension<string | undefined, 'ns', 'n'>,
|
||||
undefined
|
||||
>;
|
||||
const invalid2: never = {} as ResolveExtensionId<
|
||||
NamedExtension<'k', string | undefined, 'n'>,
|
||||
undefined
|
||||
>;
|
||||
const invalid3: never = {} as ResolveExtensionId<
|
||||
NamedExtension<'k', 'ns', string | undefined>,
|
||||
undefined
|
||||
NamedExtension<'k', string | undefined>,
|
||||
'ns'
|
||||
>;
|
||||
|
||||
expect([
|
||||
id1,
|
||||
id2,
|
||||
id3,
|
||||
id4,
|
||||
id5,
|
||||
id6,
|
||||
id7,
|
||||
id8,
|
||||
id9,
|
||||
ida,
|
||||
idb,
|
||||
idc,
|
||||
idd,
|
||||
ide,
|
||||
invalid1,
|
||||
invalid2,
|
||||
invalid3,
|
||||
]).toBeDefined();
|
||||
const invalid2: never = {} as ResolveExtensionId<
|
||||
NamedExtension<'k', string>,
|
||||
'ns'
|
||||
>;
|
||||
|
||||
expect([id1, id2, id3, id4, invalid1, invalid2]).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -111,22 +111,15 @@ export function toInternalExtension<TConfig, TConfigInput>(
|
||||
/** @ignore */
|
||||
export type ResolveExtensionId<
|
||||
TExtension extends ExtensionDefinition,
|
||||
TDefaultNamespace extends string | undefined,
|
||||
TNamespace extends string,
|
||||
> = TExtension extends ExtensionDefinition<{
|
||||
kind: infer IKind extends string | undefined;
|
||||
namespace: infer INamespace extends string | undefined;
|
||||
name: infer IName extends string | undefined;
|
||||
}>
|
||||
? [string | undefined] extends [IKind | INamespace | IName]
|
||||
? [string] extends [IKind | IName]
|
||||
? never
|
||||
: (
|
||||
(
|
||||
undefined extends TDefaultNamespace ? INamespace : TDefaultNamespace
|
||||
) extends infer ISelectedNamespace extends string
|
||||
? undefined extends IName
|
||||
? ISelectedNamespace
|
||||
: `${ISelectedNamespace}/${IName}`
|
||||
: IName
|
||||
undefined extends IName ? TNamespace : `${TNamespace}/${IName}`
|
||||
) extends infer INamePart extends string
|
||||
? IKind extends string
|
||||
? `${IKind}:${INamePart}`
|
||||
|
||||
@@ -27,7 +27,6 @@ const _default: FrontendPlugin<
|
||||
{
|
||||
'nav-item:api-docs': ExtensionDefinition<{
|
||||
kind: 'nav-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -49,7 +48,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'api:api-docs/config': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'config';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -98,7 +96,6 @@ const _default: FrontendPlugin<
|
||||
>;
|
||||
};
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
params: {
|
||||
defaultPath: string;
|
||||
@@ -108,7 +105,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'entity-card:api-docs/has-apis': ExtensionDefinition<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'has-apis';
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
@@ -144,7 +140,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'entity-card:api-docs/definition': ExtensionDefinition<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'definition';
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
@@ -180,7 +175,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'entity-card:api-docs/consumed-apis': ExtensionDefinition<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'consumed-apis';
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
@@ -216,7 +210,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'entity-card:api-docs/provided-apis': ExtensionDefinition<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'provided-apis';
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
@@ -252,7 +245,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'entity-card:api-docs/consuming-components': ExtensionDefinition<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'consuming-components';
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
@@ -288,7 +280,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'entity-card:api-docs/providing-components': ExtensionDefinition<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'providing-components';
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
@@ -324,7 +315,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'entity-content:api-docs/definition': ExtensionDefinition<{
|
||||
kind: 'entity-content';
|
||||
namespace: undefined;
|
||||
name: 'definition';
|
||||
config: {
|
||||
path: string | undefined;
|
||||
@@ -380,7 +370,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'entity-content:api-docs/apis': ExtensionDefinition<{
|
||||
kind: 'entity-content';
|
||||
namespace: undefined;
|
||||
name: 'apis';
|
||||
config: {
|
||||
path: string | undefined;
|
||||
|
||||
@@ -18,7 +18,6 @@ const visualizerPlugin: FrontendPlugin<
|
||||
{
|
||||
'page:app-visualizer': ExtensionDefinition<{
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {
|
||||
path: string | undefined;
|
||||
@@ -49,7 +48,6 @@ const visualizerPlugin: FrontendPlugin<
|
||||
}>;
|
||||
'nav-item:app-visualizer': ExtensionDefinition<{
|
||||
kind: 'nav-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
|
||||
@@ -48,12 +48,10 @@ const appPlugin: FrontendPlugin<
|
||||
};
|
||||
params: never;
|
||||
kind: undefined;
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}>;
|
||||
'api:app/app-language': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'app-language';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -93,7 +91,6 @@ const appPlugin: FrontendPlugin<
|
||||
};
|
||||
params: never;
|
||||
kind: undefined;
|
||||
namespace: undefined;
|
||||
name: 'layout';
|
||||
}>;
|
||||
'app/nav': ExtensionDefinition<{
|
||||
@@ -137,7 +134,6 @@ const appPlugin: FrontendPlugin<
|
||||
};
|
||||
params: never;
|
||||
kind: undefined;
|
||||
namespace: undefined;
|
||||
name: 'nav';
|
||||
}>;
|
||||
'app/root': ExtensionDefinition<{
|
||||
@@ -203,7 +199,6 @@ const appPlugin: FrontendPlugin<
|
||||
};
|
||||
params: never;
|
||||
kind: undefined;
|
||||
namespace: undefined;
|
||||
name: 'root';
|
||||
}>;
|
||||
'app/routes': ExtensionDefinition<{
|
||||
@@ -233,7 +228,6 @@ const appPlugin: FrontendPlugin<
|
||||
};
|
||||
params: never;
|
||||
kind: undefined;
|
||||
namespace: undefined;
|
||||
name: 'routes';
|
||||
}>;
|
||||
'api:app/app-theme': ExtensionDefinition<{
|
||||
@@ -254,7 +248,6 @@ const appPlugin: FrontendPlugin<
|
||||
>;
|
||||
};
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'app-theme';
|
||||
params: {
|
||||
factory: AnyApiFactory;
|
||||
@@ -262,7 +255,6 @@ const appPlugin: FrontendPlugin<
|
||||
}>;
|
||||
'theme:app/light': ExtensionDefinition<{
|
||||
kind: 'theme';
|
||||
namespace: undefined;
|
||||
name: 'light';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -274,7 +266,6 @@ const appPlugin: FrontendPlugin<
|
||||
}>;
|
||||
'theme:app/dark': ExtensionDefinition<{
|
||||
kind: 'theme';
|
||||
namespace: undefined;
|
||||
name: 'dark';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -309,7 +300,6 @@ const appPlugin: FrontendPlugin<
|
||||
>;
|
||||
};
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'components';
|
||||
params: {
|
||||
factory: AnyApiFactory;
|
||||
@@ -339,7 +329,6 @@ const appPlugin: FrontendPlugin<
|
||||
>;
|
||||
};
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'icons';
|
||||
params: {
|
||||
factory: AnyApiFactory;
|
||||
@@ -347,7 +336,6 @@ const appPlugin: FrontendPlugin<
|
||||
}>;
|
||||
'api:app/feature-flags': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'feature-flags';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -390,7 +378,6 @@ const appPlugin: FrontendPlugin<
|
||||
>;
|
||||
};
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'translations';
|
||||
params: {
|
||||
factory: AnyApiFactory;
|
||||
@@ -398,7 +385,6 @@ const appPlugin: FrontendPlugin<
|
||||
}>;
|
||||
'app-root-element:app/oauth-request-dialog': ExtensionDefinition<{
|
||||
kind: 'app-root-element';
|
||||
namespace: undefined;
|
||||
name: 'oauth-request-dialog';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -444,7 +430,6 @@ const appPlugin: FrontendPlugin<
|
||||
>;
|
||||
};
|
||||
kind: 'app-root-element';
|
||||
namespace: undefined;
|
||||
name: 'alert-display';
|
||||
params: {
|
||||
element: JSX.Element | (() => JSX.Element);
|
||||
@@ -452,7 +437,6 @@ const appPlugin: FrontendPlugin<
|
||||
}>;
|
||||
'api:app/discovery': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'discovery';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -468,7 +452,6 @@ const appPlugin: FrontendPlugin<
|
||||
}>;
|
||||
'api:app/alert': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'alert';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -484,7 +467,6 @@ const appPlugin: FrontendPlugin<
|
||||
}>;
|
||||
'api:app/analytics': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'analytics';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -500,7 +482,6 @@ const appPlugin: FrontendPlugin<
|
||||
}>;
|
||||
'api:app/error': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'error';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -516,7 +497,6 @@ const appPlugin: FrontendPlugin<
|
||||
}>;
|
||||
'api:app/storage': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'storage';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -532,7 +512,6 @@ const appPlugin: FrontendPlugin<
|
||||
}>;
|
||||
'api:app/fetch': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'fetch';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -548,7 +527,6 @@ const appPlugin: FrontendPlugin<
|
||||
}>;
|
||||
'api:app/oauth-request': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'oauth-request';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -564,7 +542,6 @@ const appPlugin: FrontendPlugin<
|
||||
}>;
|
||||
'api:app/google-auth': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'google-auth';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -580,7 +557,6 @@ const appPlugin: FrontendPlugin<
|
||||
}>;
|
||||
'api:app/microsoft-auth': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'microsoft-auth';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -596,7 +572,6 @@ const appPlugin: FrontendPlugin<
|
||||
}>;
|
||||
'api:app/github-auth': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'github-auth';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -612,7 +587,6 @@ const appPlugin: FrontendPlugin<
|
||||
}>;
|
||||
'api:app/okta-auth': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'okta-auth';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -628,7 +602,6 @@ const appPlugin: FrontendPlugin<
|
||||
}>;
|
||||
'api:app/gitlab-auth': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'gitlab-auth';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -644,7 +617,6 @@ const appPlugin: FrontendPlugin<
|
||||
}>;
|
||||
'api:app/onelogin-auth': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'onelogin-auth';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -660,7 +632,6 @@ const appPlugin: FrontendPlugin<
|
||||
}>;
|
||||
'api:app/bitbucket-auth': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'bitbucket-auth';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -676,7 +647,6 @@ const appPlugin: FrontendPlugin<
|
||||
}>;
|
||||
'api:app/bitbucket-server-auth': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'bitbucket-server-auth';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -692,7 +662,6 @@ const appPlugin: FrontendPlugin<
|
||||
}>;
|
||||
'api:app/atlassian-auth': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'atlassian-auth';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -708,7 +677,6 @@ const appPlugin: FrontendPlugin<
|
||||
}>;
|
||||
'api:app/vmware-cloud-auth': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'vmware-cloud-auth';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -724,7 +692,6 @@ const appPlugin: FrontendPlugin<
|
||||
}>;
|
||||
'api:app/permission': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'permission';
|
||||
config: {};
|
||||
configInput: {};
|
||||
|
||||
@@ -89,7 +89,6 @@ const _default: FrontendPlugin<
|
||||
>;
|
||||
};
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'relations';
|
||||
params: {
|
||||
loader: () => Promise<JSX.Element>;
|
||||
@@ -155,7 +154,6 @@ const _default: FrontendPlugin<
|
||||
>;
|
||||
};
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
params: {
|
||||
defaultPath: string;
|
||||
|
||||
@@ -20,7 +20,6 @@ const _default: FrontendPlugin<
|
||||
{
|
||||
'api:catalog-import': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -36,7 +35,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'page:catalog-import': ExtensionDefinition<{
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {
|
||||
path: string | undefined;
|
||||
|
||||
@@ -101,7 +101,6 @@ export function convertLegacyEntityContentExtension(
|
||||
// @alpha
|
||||
export const EntityCardBlueprint: ExtensionBlueprint<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
params: {
|
||||
loader: () => Promise<JSX.Element>;
|
||||
@@ -147,7 +146,6 @@ export const EntityCardBlueprint: ExtensionBlueprint<{
|
||||
// @alpha
|
||||
export const EntityContentBlueprint: ExtensionBlueprint<{
|
||||
kind: 'entity-content';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
params: {
|
||||
loader: () => Promise<JSX.Element>;
|
||||
|
||||
@@ -63,7 +63,6 @@ describe('EntityCardBlueprint', () => {
|
||||
"inputs": {},
|
||||
"kind": "entity-card",
|
||||
"name": "test",
|
||||
"namespace": undefined,
|
||||
"output": [
|
||||
[Function],
|
||||
{
|
||||
|
||||
@@ -71,7 +71,6 @@ describe('EntityContentBlueprint', () => {
|
||||
"inputs": {},
|
||||
"kind": "entity-content",
|
||||
"name": "test",
|
||||
"namespace": undefined,
|
||||
"output": [
|
||||
[Function],
|
||||
[Function],
|
||||
|
||||
@@ -26,7 +26,6 @@ import { TranslationRef } from '@backstage/core-plugin-api/alpha';
|
||||
// @alpha
|
||||
export const CatalogFilterBlueprint: ExtensionBlueprint<{
|
||||
kind: 'catalog-filter';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
params: {
|
||||
loader: () => Promise<JSX.Element>;
|
||||
@@ -149,7 +148,6 @@ const _default: FrontendPlugin<
|
||||
{
|
||||
'api:catalog': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -165,7 +163,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'nav-item:catalog': ExtensionDefinition<{
|
||||
kind: 'nav-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -187,7 +184,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'api:catalog/starred-entities': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'starred-entities';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -203,7 +199,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'api:catalog/entity-presentation': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'entity-presentation';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -219,7 +214,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'entity-card:catalog/about': ExtensionDefinition<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'about';
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
@@ -251,7 +245,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'entity-card:catalog/links': ExtensionDefinition<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'links';
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
@@ -283,7 +276,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'entity-card:catalog/labels': ExtensionDefinition<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'labels';
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
@@ -315,7 +307,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'entity-card:catalog/depends-on-components': ExtensionDefinition<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'depends-on-components';
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
@@ -347,7 +338,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'entity-card:catalog/depends-on-resources': ExtensionDefinition<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'depends-on-resources';
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
@@ -379,7 +369,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'entity-card:catalog/has-components': ExtensionDefinition<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'has-components';
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
@@ -411,7 +400,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'entity-card:catalog/has-resources': ExtensionDefinition<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'has-resources';
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
@@ -443,7 +431,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'entity-card:catalog/has-subcomponents': ExtensionDefinition<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'has-subcomponents';
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
@@ -475,7 +462,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'entity-card:catalog/has-subdomains': ExtensionDefinition<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'has-subdomains';
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
@@ -507,7 +493,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'entity-card:catalog/has-systems': ExtensionDefinition<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'has-systems';
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
@@ -601,7 +586,6 @@ const _default: FrontendPlugin<
|
||||
>;
|
||||
};
|
||||
kind: 'entity-content';
|
||||
namespace: undefined;
|
||||
name: 'overview';
|
||||
params: {
|
||||
loader: () => Promise<JSX.Element>;
|
||||
@@ -613,7 +597,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'catalog-filter:catalog/tag': ExtensionDefinition<{
|
||||
kind: 'catalog-filter';
|
||||
namespace: undefined;
|
||||
name: 'tag';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -649,7 +632,6 @@ const _default: FrontendPlugin<
|
||||
>;
|
||||
};
|
||||
kind: 'catalog-filter';
|
||||
namespace: undefined;
|
||||
name: 'kind';
|
||||
params: {
|
||||
loader: () => Promise<JSX.Element>;
|
||||
@@ -657,7 +639,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'catalog-filter:catalog/type': ExtensionDefinition<{
|
||||
kind: 'catalog-filter';
|
||||
namespace: undefined;
|
||||
name: 'type';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -693,7 +674,6 @@ const _default: FrontendPlugin<
|
||||
>;
|
||||
};
|
||||
kind: 'catalog-filter';
|
||||
namespace: undefined;
|
||||
name: 'mode';
|
||||
params: {
|
||||
loader: () => Promise<JSX.Element>;
|
||||
@@ -701,7 +681,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'catalog-filter:catalog/namespace': ExtensionDefinition<{
|
||||
kind: 'catalog-filter';
|
||||
namespace: undefined;
|
||||
name: 'namespace';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -717,7 +696,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'catalog-filter:catalog/lifecycle': ExtensionDefinition<{
|
||||
kind: 'catalog-filter';
|
||||
namespace: undefined;
|
||||
name: 'lifecycle';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -733,7 +711,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'catalog-filter:catalog/processing-status': ExtensionDefinition<{
|
||||
kind: 'catalog-filter';
|
||||
namespace: undefined;
|
||||
name: 'processing-status';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -769,7 +746,6 @@ const _default: FrontendPlugin<
|
||||
>;
|
||||
};
|
||||
kind: 'catalog-filter';
|
||||
namespace: undefined;
|
||||
name: 'list';
|
||||
params: {
|
||||
loader: () => Promise<JSX.Element>;
|
||||
@@ -802,7 +778,6 @@ const _default: FrontendPlugin<
|
||||
>;
|
||||
};
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
params: {
|
||||
defaultPath: string;
|
||||
@@ -864,7 +839,6 @@ const _default: FrontendPlugin<
|
||||
>;
|
||||
};
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: 'entity';
|
||||
params: {
|
||||
defaultPath: string;
|
||||
@@ -874,7 +848,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'search-result-list-item:catalog': ExtensionDefinition<{
|
||||
kind: 'search-result-list-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {
|
||||
noTrack: boolean;
|
||||
|
||||
@@ -47,7 +47,6 @@ describe('CatalogFilterBlueprint', () => {
|
||||
"inputs": {},
|
||||
"kind": "catalog-filter",
|
||||
"name": undefined,
|
||||
"namespace": undefined,
|
||||
"output": [
|
||||
[Function],
|
||||
],
|
||||
|
||||
@@ -21,7 +21,6 @@ const _default: FrontendPlugin<
|
||||
{
|
||||
'api:devtools': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -37,7 +36,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'page:devtools': ExtensionDefinition<{
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {
|
||||
path: string | undefined;
|
||||
@@ -68,7 +66,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'nav-item:devtools': ExtensionDefinition<{
|
||||
kind: 'nav-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
|
||||
@@ -60,7 +60,6 @@ const _default: FrontendPlugin<
|
||||
>;
|
||||
};
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
params: {
|
||||
defaultPath: string;
|
||||
|
||||
@@ -23,7 +23,6 @@ const _default: FrontendPlugin<
|
||||
{
|
||||
'api:kubernetes': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -39,7 +38,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'page:kubernetes': ExtensionDefinition<{
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {
|
||||
path: string | undefined;
|
||||
@@ -66,7 +64,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'entity-content:kubernetes/kubernetes': ExtensionDefinition<{
|
||||
kind: 'entity-content';
|
||||
namespace: undefined;
|
||||
name: 'kubernetes';
|
||||
config: {
|
||||
path: string | undefined;
|
||||
@@ -118,7 +115,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'api:kubernetes/proxy': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'proxy';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -134,7 +130,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'api:kubernetes/auth-providers': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'auth-providers';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -150,7 +145,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'api:kubernetes/cluster-link-formatter': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'cluster-link-formatter';
|
||||
config: {};
|
||||
configInput: {};
|
||||
|
||||
@@ -19,7 +19,6 @@ const _default: FrontendPlugin<
|
||||
{
|
||||
'entity-card:org/group-profile': ExtensionDefinition<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'group-profile';
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
@@ -55,7 +54,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'entity-card:org/members-list': ExtensionDefinition<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'members-list';
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
@@ -91,7 +89,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'entity-card:org/ownership': ExtensionDefinition<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'ownership';
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
@@ -127,7 +124,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'entity-card:org/user-profile': ExtensionDefinition<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'user-profile';
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
|
||||
@@ -46,7 +46,6 @@ const _default: FrontendPlugin<
|
||||
{
|
||||
'api:scaffolder': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -62,7 +61,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'page:scaffolder': ExtensionDefinition<{
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {
|
||||
path: string | undefined;
|
||||
@@ -93,7 +91,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'nav-item:scaffolder': ExtensionDefinition<{
|
||||
kind: 'nav-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
|
||||
@@ -32,7 +32,6 @@ export type SearchResultItemExtensionPredicate = (
|
||||
// @alpha
|
||||
export const SearchResultListItemBlueprint: ExtensionBlueprint<{
|
||||
kind: 'search-result-list-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
params: SearchResultListItemBlueprintParams;
|
||||
output: ConfigurableExtensionDataRef<
|
||||
|
||||
@@ -64,7 +64,6 @@ describe('SearchResultListItemBlueprint', () => {
|
||||
"inputs": {},
|
||||
"kind": "search-result-list-item",
|
||||
"name": "test",
|
||||
"namespace": undefined,
|
||||
"output": [
|
||||
[Function],
|
||||
],
|
||||
|
||||
@@ -24,7 +24,6 @@ const _default: FrontendPlugin<
|
||||
{
|
||||
'api:search': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -40,7 +39,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'nav-item:search': ExtensionDefinition<{
|
||||
kind: 'nav-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -102,7 +100,6 @@ const _default: FrontendPlugin<
|
||||
>;
|
||||
};
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
params: {
|
||||
defaultPath: string;
|
||||
@@ -117,7 +114,6 @@ export default _default;
|
||||
// @alpha (undocumented)
|
||||
export const searchApi: ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -131,7 +127,6 @@ export const searchApi: ExtensionDefinition<{
|
||||
// @alpha (undocumented)
|
||||
export const searchNavItem: ExtensionDefinition<{
|
||||
kind: 'nav-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -191,7 +186,6 @@ export const searchPage: ExtensionDefinition<{
|
||||
>;
|
||||
};
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
params: {
|
||||
defaultPath: string;
|
||||
|
||||
@@ -33,7 +33,6 @@ const _default: FrontendPlugin<
|
||||
{
|
||||
'api:techdocs': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -49,7 +48,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'page:techdocs': ExtensionDefinition<{
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {
|
||||
path: string | undefined;
|
||||
@@ -80,7 +78,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'nav-item:techdocs': ExtensionDefinition<{
|
||||
kind: 'nav-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -102,7 +99,6 @@ const _default: FrontendPlugin<
|
||||
}>;
|
||||
'api:techdocs/storage': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'storage';
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -151,13 +147,11 @@ const _default: FrontendPlugin<
|
||||
>;
|
||||
};
|
||||
kind: 'search-result-list-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
params: SearchResultListItemBlueprintParams;
|
||||
}>;
|
||||
'page:techdocs/reader': ExtensionDefinition<{
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: 'reader';
|
||||
config: {
|
||||
path: string | undefined;
|
||||
@@ -244,7 +238,6 @@ const _default: FrontendPlugin<
|
||||
>;
|
||||
};
|
||||
kind: 'entity-content';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
params: {
|
||||
loader: () => Promise<JSX.Element>;
|
||||
@@ -275,7 +268,6 @@ const _default: FrontendPlugin<
|
||||
};
|
||||
params: never;
|
||||
kind: 'empty-state';
|
||||
namespace: undefined;
|
||||
name: 'entity-content';
|
||||
}>;
|
||||
}
|
||||
@@ -318,7 +310,6 @@ export const techDocsSearchResultListItemExtension: ExtensionDefinition<{
|
||||
>;
|
||||
};
|
||||
kind: 'search-result-list-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
params: SearchResultListItemBlueprintParams;
|
||||
}>;
|
||||
|
||||
@@ -22,7 +22,6 @@ const _default: FrontendPlugin<
|
||||
{
|
||||
'nav-item:user-settings': ExtensionDefinition<{
|
||||
kind: 'nav-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
@@ -77,7 +76,6 @@ const _default: FrontendPlugin<
|
||||
>;
|
||||
};
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
params: {
|
||||
defaultPath: string;
|
||||
@@ -92,7 +90,6 @@ export default _default;
|
||||
// @alpha (undocumented)
|
||||
export const settingsNavItem: ExtensionDefinition<{
|
||||
kind: 'nav-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
|
||||
@@ -4136,12 +4136,14 @@ __metadata:
|
||||
"@backstage/frontend-test-utils": "workspace:^"
|
||||
"@backstage/plugin-catalog": "workspace:^"
|
||||
"@backstage/test-utils": "workspace:^"
|
||||
"@backstage/types": "workspace:^"
|
||||
"@backstage/version-bridge": "workspace:^"
|
||||
"@oriflame/backstage-plugin-score-card": ^0.8.0
|
||||
"@testing-library/jest-dom": ^6.0.0
|
||||
"@testing-library/react": ^16.0.0
|
||||
"@types/react": ^16.13.1 || ^17.0.0
|
||||
lodash: ^4.17.21
|
||||
zod: ^3.22.4
|
||||
peerDependencies:
|
||||
react: ^16.13.1 || ^17.0.0 || ^18.0.0
|
||||
react-router-dom: 6.0.0-beta.0 || ^6.3.0
|
||||
@@ -4458,6 +4460,7 @@ __metadata:
|
||||
"@testing-library/react": ^16.0.0
|
||||
"@types/react": ^16.13.1 || ^17.0.0 || ^18.0.0
|
||||
lodash: ^4.17.21
|
||||
zod: ^3.22.4
|
||||
peerDependencies:
|
||||
react: ^16.13.1 || ^17.0.0 || ^18.0.0
|
||||
react-router-dom: 6.0.0-beta.0 || ^6.3.0
|
||||
|
||||
Reference in New Issue
Block a user