Merge pull request #26204 from backstage/rugvip/type-params
frontend-plugin-api: consolidate type parameters for extension definitions and blueprints
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
---
|
||||
'@backstage/frontend-test-utils': patch
|
||||
'@backstage/frontend-app-api': patch
|
||||
'@backstage/core-compat-api': patch
|
||||
'@backstage/plugin-catalog-import': patch
|
||||
'@backstage/plugin-catalog-graph': patch
|
||||
'@backstage/plugin-catalog-react': patch
|
||||
'@backstage/plugin-user-settings': patch
|
||||
'@backstage/plugin-search-react': patch
|
||||
'@backstage/plugin-kubernetes': patch
|
||||
'@backstage/plugin-scaffolder': patch
|
||||
'@backstage/plugin-api-docs': patch
|
||||
'@backstage/plugin-devtools': patch
|
||||
'@backstage/plugin-techdocs': patch
|
||||
'@backstage/plugin-catalog': patch
|
||||
'@backstage/plugin-search': patch
|
||||
'@backstage/plugin-home': patch
|
||||
'@backstage/plugin-org': patch
|
||||
---
|
||||
|
||||
Updated exports to use the new type parameters for extensions and extension blueprints.
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
'@backstage/frontend-plugin-api': minor
|
||||
---
|
||||
|
||||
**BREAKING**: Updated the type parameters for `ExtensionDefinition` and `ExtensionBlueprint` to only have a single object parameter. The base type parameter is exported as `ExtensionDefinitionParameters` and `ExtensionBlueprintParameters` respectively. This is shipped as an immediate breaking change as we expect usage of these types to be rare, and it does not affect the runtime behavior of the API.
|
||||
|
||||
This is a breaking change as it changes the type parameters. Existing usage can generally be updated as follows:
|
||||
|
||||
- `ExtensionDefinition<any>` -> `ExtensionDefinition`
|
||||
- `ExtensionDefinition<any, any>` -> `ExtensionDefinition`
|
||||
- `ExtensionDefinition<TConfig>` -> `ExtensionDefinition<{ config: TConfig }>`
|
||||
- `ExtensionDefinition<TConfig, TConfigInput>` -> `ExtensionDefinition<{ config: TConfig, configInput: TConfigInput }>`
|
||||
|
||||
If you need to infer the parameter you can use `ExtensionDefinitionParameters`, for example:
|
||||
|
||||
```ts
|
||||
import {
|
||||
ExtensionDefinition,
|
||||
ExtensionDefinitionParameters,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
|
||||
function myUtility<T extends ExtensionDefinitionParameters>(
|
||||
ext: ExtensionDefinition<T>,
|
||||
): T['config'] {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
The same patterns apply to `ExtensionBlueprint`.
|
||||
|
||||
This change is made to improve the readability of API references and ability to evolve the type parameters in the future.
|
||||
@@ -15,33 +15,32 @@ const examplePlugin: BackstagePlugin<
|
||||
{},
|
||||
{},
|
||||
{
|
||||
'page:example': ExtensionDefinition<
|
||||
{
|
||||
'page:example': ExtensionDefinition<{
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {
|
||||
path: string | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
path?: string | undefined;
|
||||
},
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}
|
||||
>;
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
}
|
||||
>;
|
||||
export default examplePlugin;
|
||||
|
||||
@@ -37,13 +37,13 @@ export function convertLegacyPageExtension(
|
||||
name?: string;
|
||||
defaultPath?: string;
|
||||
},
|
||||
): ExtensionDefinition<any>;
|
||||
): ExtensionDefinition;
|
||||
|
||||
// @public (undocumented)
|
||||
export function convertLegacyPlugin(
|
||||
legacyPlugin: BackstagePlugin,
|
||||
options: {
|
||||
extensions: ExtensionDefinition<any, any>[];
|
||||
extensions: ExtensionDefinition[];
|
||||
},
|
||||
): BackstagePlugin_2;
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ function visitRouteChildren(options: {
|
||||
parentExtensionId: string;
|
||||
context: {
|
||||
pluginId: string;
|
||||
extensions: ExtensionDefinition<any, any>[];
|
||||
extensions: ExtensionDefinition[];
|
||||
getUniqueName: () => string;
|
||||
discoverPlugin: (plugin: LegacyBackstagePlugin) => void;
|
||||
};
|
||||
@@ -159,7 +159,7 @@ export function collectLegacyRoutes(
|
||||
): BackstagePlugin[] {
|
||||
const pluginExtensions = new Map<
|
||||
LegacyBackstagePlugin,
|
||||
ExtensionDefinition<any, any>[]
|
||||
ExtensionDefinition[]
|
||||
>();
|
||||
|
||||
const getUniqueName = (() => {
|
||||
|
||||
@@ -48,12 +48,11 @@ describe('convertLegacyPageExtension', () => {
|
||||
);
|
||||
|
||||
const converted = convertLegacyPageExtension(LegacyExtension);
|
||||
expect(converted.kind).toBe('page');
|
||||
expect(converted.namespace).toBe(undefined);
|
||||
expect(converted.name).toBe('example');
|
||||
|
||||
const tester = createExtensionTester(converted);
|
||||
|
||||
expect(tester.query(converted).node.spec.id).toBe('page:example');
|
||||
|
||||
await renderInTestApp(tester.reactElement(), {
|
||||
mountedRoutes: {
|
||||
'/': convertLegacyRouteRef(routeRef),
|
||||
@@ -79,12 +78,11 @@ describe('convertLegacyPageExtension', () => {
|
||||
name: 'other',
|
||||
defaultPath: '/other',
|
||||
});
|
||||
expect(converted.kind).toBe('page');
|
||||
expect(converted.namespace).toBe(undefined);
|
||||
expect(converted.name).toBe('other');
|
||||
|
||||
const tester = createExtensionTester(converted);
|
||||
|
||||
expect(tester.query(converted).node.spec.id).toBe('page:other');
|
||||
|
||||
await renderInTestApp(tester.reactElement(), {
|
||||
mountedRoutes: {
|
||||
'/': convertLegacyRouteRef(routeRef),
|
||||
|
||||
@@ -35,7 +35,7 @@ export function convertLegacyPageExtension(
|
||||
name?: string;
|
||||
defaultPath?: string;
|
||||
},
|
||||
): ExtensionDefinition<any> {
|
||||
): ExtensionDefinition {
|
||||
const element = <LegacyExtension />;
|
||||
|
||||
const extName = getComponentData<string>(element, 'core.extensionName');
|
||||
|
||||
@@ -26,7 +26,7 @@ import { convertLegacyRouteRefs } from './convertLegacyRouteRef';
|
||||
/** @public */
|
||||
export function convertLegacyPlugin(
|
||||
legacyPlugin: LegacyBackstagePlugin,
|
||||
options: { extensions: ExtensionDefinition<any, any>[] },
|
||||
options: { extensions: ExtensionDefinition[] },
|
||||
): NewBackstagePlugin {
|
||||
const apiExtensions = Array.from(legacyPlugin.getApis()).map(factory =>
|
||||
ApiBlueprint.make({ namespace: factory.api.id, params: { factory } }),
|
||||
|
||||
@@ -76,7 +76,7 @@ function createTestExtension(options: {
|
||||
});
|
||||
}
|
||||
|
||||
function routeInfoFromExtensions(extensions: ExtensionDefinition<any, any>[]) {
|
||||
function routeInfoFromExtensions(extensions: ExtensionDefinition[]) {
|
||||
const plugin = createFrontendPlugin({
|
||||
id: 'test',
|
||||
extensions,
|
||||
|
||||
@@ -44,12 +44,13 @@ function makeExtDef(
|
||||
) {
|
||||
return {
|
||||
$$type: '@backstage/ExtensionDefinition',
|
||||
T: undefined as any,
|
||||
version: 'v1',
|
||||
name,
|
||||
attachTo: { id: attachId, input: 'default' },
|
||||
disabled: status === 'disabled',
|
||||
override: () => ({} as ExtensionDefinition<unknown>),
|
||||
} as ExtensionDefinition<unknown>;
|
||||
override: () => ({} as ExtensionDefinition),
|
||||
} as ExtensionDefinition;
|
||||
}
|
||||
|
||||
describe('resolveAppNodeSpecs', () => {
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
AppTreeApi,
|
||||
appTreeApiRef,
|
||||
coreExtensionData,
|
||||
ExtensionDefinition,
|
||||
FrontendFeature,
|
||||
RouteRef,
|
||||
ExternalRouteRef,
|
||||
@@ -112,28 +113,30 @@ const DefaultApis = defaultApis.map(factory =>
|
||||
ApiBlueprint.make({ namespace: factory.api.id, params: { factory } }),
|
||||
);
|
||||
|
||||
export const builtinExtensions = [
|
||||
Root,
|
||||
App,
|
||||
AppRoot,
|
||||
AppRoutes,
|
||||
AppNav,
|
||||
AppLayout,
|
||||
DefaultProgressComponent,
|
||||
DefaultErrorBoundaryComponent,
|
||||
DefaultNotFoundErrorPageComponent,
|
||||
LightTheme,
|
||||
DarkTheme,
|
||||
oauthRequestDialogAppRootElement,
|
||||
alertDisplayAppRootElement,
|
||||
AppThemeApi,
|
||||
AppLanguageApi,
|
||||
IconsApi,
|
||||
TranslationsApi,
|
||||
ComponentsApi,
|
||||
FeatureFlagsApi,
|
||||
...DefaultApis,
|
||||
].map(def => resolveExtensionDefinition(def));
|
||||
export const builtinExtensions = (
|
||||
[
|
||||
Root,
|
||||
App,
|
||||
AppRoot,
|
||||
AppRoutes,
|
||||
AppNav,
|
||||
AppLayout,
|
||||
DefaultProgressComponent,
|
||||
DefaultErrorBoundaryComponent,
|
||||
DefaultNotFoundErrorPageComponent,
|
||||
LightTheme,
|
||||
DarkTheme,
|
||||
oauthRequestDialogAppRootElement,
|
||||
alertDisplayAppRootElement,
|
||||
AppThemeApi,
|
||||
AppLanguageApi,
|
||||
IconsApi,
|
||||
TranslationsApi,
|
||||
ComponentsApi,
|
||||
FeatureFlagsApi,
|
||||
...DefaultApis,
|
||||
] as ExtensionDefinition[]
|
||||
).map(def => resolveExtensionDefinition(def));
|
||||
|
||||
function deduplicateFeatures(
|
||||
allFeatures: FrontendFeature[],
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -37,6 +37,7 @@ describe('ApiBlueprint', () => {
|
||||
expect(extension).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$$type": "@backstage/ExtensionDefinition",
|
||||
"T": undefined,
|
||||
"attachTo": {
|
||||
"id": "root",
|
||||
"input": "apis",
|
||||
@@ -86,6 +87,7 @@ describe('ApiBlueprint', () => {
|
||||
expect(extension).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$$type": "@backstage/ExtensionDefinition",
|
||||
"T": undefined,
|
||||
"attachTo": {
|
||||
"id": "root",
|
||||
"input": "apis",
|
||||
|
||||
@@ -27,6 +27,7 @@ describe('AppRootElementBlueprint', () => {
|
||||
expect(extension).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$$type": "@backstage/ExtensionDefinition",
|
||||
"T": undefined,
|
||||
"attachTo": {
|
||||
"id": "app/root",
|
||||
"input": "elements",
|
||||
|
||||
@@ -37,6 +37,7 @@ describe('AppRootWrapperBlueprint', () => {
|
||||
expect(extension).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$$type": "@backstage/ExtensionDefinition",
|
||||
"T": undefined,
|
||||
"attachTo": {
|
||||
"id": "app/root",
|
||||
"input": "wrappers",
|
||||
|
||||
@@ -33,6 +33,7 @@ describe('NavItemBlueprint', () => {
|
||||
expect(extension).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$$type": "@backstage/ExtensionDefinition",
|
||||
"T": undefined,
|
||||
"attachTo": {
|
||||
"id": "app/nav",
|
||||
"input": "items",
|
||||
|
||||
@@ -30,6 +30,7 @@ describe('NavLogoBlueprint', () => {
|
||||
expect(extension).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$$type": "@backstage/ExtensionDefinition",
|
||||
"T": undefined,
|
||||
"attachTo": {
|
||||
"id": "app/nav",
|
||||
"input": "logos",
|
||||
|
||||
@@ -43,6 +43,7 @@ describe('PageBlueprint', () => {
|
||||
expect(myPage).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$$type": "@backstage/ExtensionDefinition",
|
||||
"T": undefined,
|
||||
"attachTo": {
|
||||
"id": "app/routes",
|
||||
"input": "routes",
|
||||
|
||||
@@ -38,6 +38,7 @@ describe('RouterBlueprint', () => {
|
||||
expect(extension).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$$type": "@backstage/ExtensionDefinition",
|
||||
"T": undefined,
|
||||
"attachTo": {
|
||||
"id": "app/root",
|
||||
"input": "router",
|
||||
|
||||
@@ -31,6 +31,7 @@ describe('SignInPageBlueprint', () => {
|
||||
).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$$type": "@backstage/ExtensionDefinition",
|
||||
"T": undefined,
|
||||
"attachTo": {
|
||||
"id": "app/root",
|
||||
"input": "signInPage",
|
||||
|
||||
@@ -31,6 +31,7 @@ describe('ThemeBlueprint', () => {
|
||||
.toMatchInlineSnapshot(`
|
||||
{
|
||||
"$$type": "@backstage/ExtensionDefinition",
|
||||
"T": undefined,
|
||||
"attachTo": {
|
||||
"id": "api:app-theme",
|
||||
"input": "themes",
|
||||
|
||||
@@ -46,6 +46,7 @@ describe('TranslationBlueprint', () => {
|
||||
).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$$type": "@backstage/ExtensionDefinition",
|
||||
"T": undefined,
|
||||
"attachTo": {
|
||||
"id": "api:translations",
|
||||
"input": "translations",
|
||||
|
||||
@@ -18,6 +18,7 @@ import { createExtensionTester } from '@backstage/frontend-test-utils';
|
||||
import { createExtension } from './createExtension';
|
||||
import { createExtensionDataRef } from './createExtensionDataRef';
|
||||
import { createExtensionInput } from './createExtensionInput';
|
||||
import { PortableSchema } from '../schema';
|
||||
|
||||
const stringDataRef = createExtensionDataRef<string>().with({ id: 'string' });
|
||||
const numberDataRef = createExtensionDataRef<number>().with({ id: 'number' });
|
||||
@@ -289,7 +290,12 @@ describe('createExtension', () => {
|
||||
);
|
||||
|
||||
expect(
|
||||
extension.configSchema?.parse({
|
||||
(
|
||||
(extension as any).configSchema as PortableSchema<
|
||||
(typeof extension.T)['config'],
|
||||
(typeof extension.T)['configInput']
|
||||
>
|
||||
)?.parse({
|
||||
foo: 'x',
|
||||
bar: 'y',
|
||||
baz: 'z',
|
||||
@@ -302,7 +308,12 @@ describe('createExtension', () => {
|
||||
baz: 'z',
|
||||
});
|
||||
expect(
|
||||
extension.configSchema?.parse({
|
||||
(
|
||||
(extension as any).configSchema as PortableSchema<
|
||||
(typeof extension.T)['config'],
|
||||
(typeof extension.T)['configInput']
|
||||
>
|
||||
)?.parse({
|
||||
foo: 'x',
|
||||
}),
|
||||
).toEqual({
|
||||
|
||||
@@ -142,33 +142,27 @@ export type CreateExtensionOptions<
|
||||
} & VerifyExtensionFactoryOutput<UOutput, UFactoryOutput>;
|
||||
|
||||
/** @public */
|
||||
export interface ExtensionDefinition<
|
||||
TConfig,
|
||||
TConfigInput = TConfig,
|
||||
UOutput extends AnyExtensionDataRef = AnyExtensionDataRef,
|
||||
TInputs extends {
|
||||
[inputName in string]: ExtensionInput<
|
||||
export type ExtensionDefinitionParameters = {
|
||||
kind?: string;
|
||||
namespace?: string;
|
||||
name?: string;
|
||||
configInput?: { [K in string]: any };
|
||||
config?: { [K in string]: any };
|
||||
output?: AnyExtensionDataRef;
|
||||
inputs?: {
|
||||
[KName in string]: ExtensionInput<
|
||||
AnyExtensionDataRef,
|
||||
{ optional: boolean; singleton: boolean }
|
||||
>;
|
||||
} = {},
|
||||
TIdParts extends {
|
||||
kind?: string;
|
||||
namespace?: string;
|
||||
name?: string;
|
||||
} = {
|
||||
kind?: string;
|
||||
namespace?: string;
|
||||
name?: string;
|
||||
},
|
||||
> {
|
||||
};
|
||||
};
|
||||
|
||||
/** @public */
|
||||
export type ExtensionDefinition<
|
||||
T extends ExtensionDefinitionParameters = ExtensionDefinitionParameters,
|
||||
> = {
|
||||
$$type: '@backstage/ExtensionDefinition';
|
||||
readonly kind?: TIdParts['kind'];
|
||||
readonly namespace?: TIdParts['namespace'];
|
||||
readonly name?: TIdParts['name'];
|
||||
readonly attachTo: { id: string; input: string };
|
||||
readonly disabled: boolean;
|
||||
readonly configSchema?: PortableSchema<TConfig, TConfigInput>;
|
||||
readonly T: T;
|
||||
|
||||
override<
|
||||
TExtensionConfigSchema extends {
|
||||
@@ -187,78 +181,71 @@ export interface ExtensionDefinition<
|
||||
attachTo?: { id: string; input: string };
|
||||
disabled?: boolean;
|
||||
inputs?: TExtraInputs & {
|
||||
[KName in keyof TInputs]?: `Error: Input '${KName &
|
||||
[KName in keyof T['inputs']]?: `Error: Input '${KName &
|
||||
string}' is already defined in parent definition`;
|
||||
};
|
||||
output?: Array<UNewOutput>;
|
||||
config?: {
|
||||
schema: TExtensionConfigSchema & {
|
||||
[KName in keyof TConfig]?: `Error: Config key '${KName &
|
||||
[KName in keyof T['config']]?: `Error: Config key '${KName &
|
||||
string}' is already defined in parent schema`;
|
||||
};
|
||||
};
|
||||
factory(
|
||||
originalFactory: (context?: {
|
||||
config?: TConfig;
|
||||
inputs?: ResolveInputValueOverrides<TInputs>;
|
||||
}) => ExtensionDataContainer<UOutput>,
|
||||
config?: T['config'];
|
||||
inputs?: ResolveInputValueOverrides<NonNullable<T['inputs']>>;
|
||||
}) => ExtensionDataContainer<NonNullable<T['output']>>,
|
||||
context: {
|
||||
node: AppNode;
|
||||
apis: ApiHolder;
|
||||
config: TConfig & {
|
||||
config: T['config'] & {
|
||||
[key in keyof TExtensionConfigSchema]: z.infer<
|
||||
ReturnType<TExtensionConfigSchema[key]>
|
||||
>;
|
||||
};
|
||||
inputs: Expand<ResolvedExtensionInputs<TInputs & TExtraInputs>>;
|
||||
inputs: Expand<ResolvedExtensionInputs<T['inputs'] & TExtraInputs>>;
|
||||
},
|
||||
): Iterable<UFactoryOutput>;
|
||||
} & VerifyExtensionFactoryOutput<
|
||||
AnyExtensionDataRef extends UNewOutput ? UOutput : UNewOutput,
|
||||
AnyExtensionDataRef extends UNewOutput
|
||||
? NonNullable<T['output']>
|
||||
: UNewOutput,
|
||||
UFactoryOutput
|
||||
>,
|
||||
): ExtensionDefinition<
|
||||
{
|
||||
): ExtensionDefinition<{
|
||||
kind: T['kind'];
|
||||
namespace: T['namespace'];
|
||||
name: T['name'];
|
||||
output: AnyExtensionDataRef extends UNewOutput ? T['output'] : UNewOutput;
|
||||
inputs: T['inputs'] & TExtraInputs;
|
||||
config: T['config'] & {
|
||||
[key in keyof TExtensionConfigSchema]: z.infer<
|
||||
ReturnType<TExtensionConfigSchema[key]>
|
||||
>;
|
||||
} & TConfig,
|
||||
z.input<
|
||||
z.ZodObject<{
|
||||
[key in keyof TExtensionConfigSchema]: ReturnType<
|
||||
TExtensionConfigSchema[key]
|
||||
>;
|
||||
}>
|
||||
> &
|
||||
TConfigInput,
|
||||
AnyExtensionDataRef extends UNewOutput ? UOutput : UNewOutput,
|
||||
TInputs & TExtraInputs,
|
||||
TIdParts
|
||||
>;
|
||||
}
|
||||
};
|
||||
configInput: T['configInput'] &
|
||||
z.input<
|
||||
z.ZodObject<{
|
||||
[key in keyof TExtensionConfigSchema]: ReturnType<
|
||||
TExtensionConfigSchema[key]
|
||||
>;
|
||||
}>
|
||||
>;
|
||||
}>;
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
export type InternalExtensionDefinition<
|
||||
TConfig,
|
||||
TConfigInput = TConfig,
|
||||
UOutput extends AnyExtensionDataRef = AnyExtensionDataRef,
|
||||
TInputs extends {
|
||||
[inputName in string]: ExtensionInput<
|
||||
AnyExtensionDataRef,
|
||||
{ optional: boolean; singleton: boolean }
|
||||
>;
|
||||
} = {},
|
||||
TIdParts extends {
|
||||
kind?: string;
|
||||
namespace?: string;
|
||||
name?: string;
|
||||
} = {
|
||||
kind?: string;
|
||||
namespace?: string;
|
||||
name?: string;
|
||||
},
|
||||
> = ExtensionDefinition<TConfig, TConfigInput, UOutput, TInputs, TIdParts> &
|
||||
(
|
||||
T extends ExtensionDefinitionParameters = ExtensionDefinitionParameters,
|
||||
> = ExtensionDefinition<T> & {
|
||||
readonly kind?: string;
|
||||
readonly namespace?: string;
|
||||
readonly name?: string;
|
||||
readonly attachTo: { id: string; input: string };
|
||||
readonly disabled: boolean;
|
||||
readonly configSchema?: PortableSchema<T['config'], T['configInput']>;
|
||||
} & (
|
||||
| {
|
||||
readonly version: 'v1';
|
||||
readonly inputs: {
|
||||
@@ -276,7 +263,7 @@ export type InternalExtensionDefinition<
|
||||
factory(context: {
|
||||
node: AppNode;
|
||||
apis: ApiHolder;
|
||||
config: TConfig;
|
||||
config: object;
|
||||
inputs: {
|
||||
[inputName in string]: unknown;
|
||||
};
|
||||
@@ -296,7 +283,7 @@ export type InternalExtensionDefinition<
|
||||
factory(context: {
|
||||
node: AppNode;
|
||||
apis: ApiHolder;
|
||||
config: TConfig;
|
||||
config: object;
|
||||
inputs: ResolvedExtensionInputs<{
|
||||
[inputName in string]: ExtensionInput<
|
||||
AnyExtensionDataRef,
|
||||
@@ -308,13 +295,10 @@ export type InternalExtensionDefinition<
|
||||
);
|
||||
|
||||
/** @internal */
|
||||
export function toInternalExtensionDefinition<TConfig, TConfigInput>(
|
||||
overrides: ExtensionDefinition<TConfig, TConfigInput>,
|
||||
): InternalExtensionDefinition<TConfig, TConfigInput> {
|
||||
const internal = overrides as InternalExtensionDefinition<
|
||||
TConfig,
|
||||
TConfigInput
|
||||
>;
|
||||
export function toInternalExtensionDefinition<
|
||||
T extends ExtensionDefinitionParameters,
|
||||
>(overrides: ExtensionDefinition<T>): InternalExtensionDefinition<T> {
|
||||
const internal = overrides as InternalExtensionDefinition<T>;
|
||||
if (internal.$$type !== '@backstage/ExtensionDefinition') {
|
||||
throw new Error(
|
||||
`Invalid extension definition instance, bad type '${internal.$$type}'`,
|
||||
@@ -353,23 +337,45 @@ export function createExtension<
|
||||
TConfigSchema,
|
||||
UFactoryOutput
|
||||
>,
|
||||
): ExtensionDefinition<
|
||||
{
|
||||
[key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>>;
|
||||
},
|
||||
z.input<
|
||||
z.ZodObject<{
|
||||
[key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;
|
||||
}>
|
||||
>,
|
||||
UOutput,
|
||||
TInputs,
|
||||
{
|
||||
): 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;
|
||||
kind: string | undefined extends TKind ? undefined : TKind;
|
||||
namespace: string | undefined extends TNamespace ? undefined : TNamespace;
|
||||
name: string | undefined extends TName ? undefined : TName;
|
||||
}> {
|
||||
type T = {
|
||||
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;
|
||||
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;
|
||||
const configSchema =
|
||||
schemaDeclaration &&
|
||||
@@ -384,6 +390,7 @@ export function createExtension<
|
||||
return {
|
||||
$$type: '@backstage/ExtensionDefinition',
|
||||
version: 'v2',
|
||||
T: undefined as unknown as T,
|
||||
kind: options.kind,
|
||||
namespace: options.namespace,
|
||||
name: options.name,
|
||||
@@ -486,21 +493,5 @@ export function createExtension<
|
||||
},
|
||||
}) as ExtensionDefinition<any>;
|
||||
},
|
||||
} as InternalExtensionDefinition<
|
||||
{
|
||||
[key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>>;
|
||||
},
|
||||
z.input<
|
||||
z.ZodObject<{
|
||||
[key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;
|
||||
}>
|
||||
>,
|
||||
UOutput,
|
||||
TInputs,
|
||||
{
|
||||
kind: string | undefined extends TKind ? undefined : TKind;
|
||||
namespace: string | undefined extends TNamespace ? undefined : TNamespace;
|
||||
name: string | undefined extends TName ? undefined : TName;
|
||||
}
|
||||
>;
|
||||
} as InternalExtensionDefinition<T>;
|
||||
}
|
||||
|
||||
@@ -35,10 +35,7 @@ import { createExtensionDataContainer } from './createExtensionDataContainer';
|
||||
|
||||
function unused(..._any: any[]) {}
|
||||
|
||||
function factoryOutput(
|
||||
ext: ExtensionDefinition<any, any>,
|
||||
inputs: unknown = undefined,
|
||||
) {
|
||||
function factoryOutput(ext: ExtensionDefinition, inputs: unknown = undefined) {
|
||||
const int = toInternalExtensionDefinition(ext);
|
||||
if (int.version !== 'v2') {
|
||||
throw new Error('Expected v2 extension');
|
||||
|
||||
@@ -81,28 +81,31 @@ export type CreateExtensionBlueprintOptions<
|
||||
dataRefs?: TDataRefs;
|
||||
} & VerifyExtensionFactoryOutput<UOutput, UFactoryOutput>;
|
||||
|
||||
/** @public */
|
||||
export type ExtensionBlueprintParameters = {
|
||||
kind: string;
|
||||
namespace?: string;
|
||||
name?: string;
|
||||
params?: object;
|
||||
configInput?: { [K in string]: any };
|
||||
config?: { [K in string]: any };
|
||||
output?: AnyExtensionDataRef;
|
||||
inputs?: {
|
||||
[KName in string]: ExtensionInput<
|
||||
AnyExtensionDataRef,
|
||||
{ optional: boolean; singleton: boolean }
|
||||
>;
|
||||
};
|
||||
dataRefs?: { [name in string]: AnyExtensionDataRef };
|
||||
};
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface ExtensionBlueprint<
|
||||
TIdParts extends {
|
||||
kind: string;
|
||||
namespace?: string;
|
||||
name?: string;
|
||||
},
|
||||
TParams,
|
||||
UOutput extends AnyExtensionDataRef,
|
||||
TInputs extends {
|
||||
[inputName in string]: ExtensionInput<
|
||||
AnyExtensionDataRef,
|
||||
{ optional: boolean; singleton: boolean }
|
||||
>;
|
||||
},
|
||||
TConfig extends { [key in string]: unknown },
|
||||
TConfigInput extends { [key in string]: unknown },
|
||||
TDataRefs extends { [name in string]: AnyExtensionDataRef },
|
||||
T extends ExtensionBlueprintParameters = ExtensionBlueprintParameters,
|
||||
> {
|
||||
dataRefs: TDataRefs;
|
||||
dataRefs: T['dataRefs'];
|
||||
|
||||
make<
|
||||
TNewNamespace extends string | undefined,
|
||||
@@ -112,20 +115,18 @@ export interface ExtensionBlueprint<
|
||||
name?: TNewName;
|
||||
attachTo?: { id: string; input: string };
|
||||
disabled?: boolean;
|
||||
params: TParams;
|
||||
}): ExtensionDefinition<
|
||||
TConfig,
|
||||
TConfigInput,
|
||||
UOutput,
|
||||
TInputs,
|
||||
{
|
||||
kind: TIdParts['kind'];
|
||||
namespace: string | undefined extends TNewNamespace
|
||||
? TIdParts['namespace']
|
||||
: TNewNamespace;
|
||||
name: string | undefined extends TNewName ? TIdParts['name'] : TNewName;
|
||||
}
|
||||
>;
|
||||
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.
|
||||
@@ -153,63 +154,68 @@ export interface ExtensionBlueprint<
|
||||
attachTo?: { id: string; input: string };
|
||||
disabled?: boolean;
|
||||
inputs?: TExtraInputs & {
|
||||
[KName in keyof TInputs]?: `Error: Input '${KName &
|
||||
[KName in keyof T['inputs']]?: `Error: Input '${KName &
|
||||
string}' is already defined in parent definition`;
|
||||
};
|
||||
output?: Array<UNewOutput>;
|
||||
config?: {
|
||||
schema: TExtensionConfigSchema & {
|
||||
[KName in keyof TConfig]?: `Error: Config key '${KName &
|
||||
[KName in keyof T['config']]?: `Error: Config key '${KName &
|
||||
string}' is already defined in parent schema`;
|
||||
};
|
||||
};
|
||||
factory(
|
||||
originalFactory: (
|
||||
params: TParams,
|
||||
params: T['params'],
|
||||
context?: {
|
||||
config?: TConfig;
|
||||
inputs?: ResolveInputValueOverrides<TInputs>;
|
||||
config?: T['config'];
|
||||
inputs?: ResolveInputValueOverrides<NonNullable<T['inputs']>>;
|
||||
},
|
||||
) => ExtensionDataContainer<UOutput>,
|
||||
) => ExtensionDataContainer<NonNullable<T['output']>>,
|
||||
context: {
|
||||
node: AppNode;
|
||||
apis: ApiHolder;
|
||||
config: TConfig & {
|
||||
config: T['config'] & {
|
||||
[key in keyof TExtensionConfigSchema]: z.infer<
|
||||
ReturnType<TExtensionConfigSchema[key]>
|
||||
>;
|
||||
};
|
||||
inputs: Expand<ResolvedExtensionInputs<TInputs & TExtraInputs>>;
|
||||
inputs: Expand<ResolvedExtensionInputs<T['inputs'] & TExtraInputs>>;
|
||||
},
|
||||
): Iterable<UFactoryOutput> &
|
||||
VerifyExtensionFactoryOutput<
|
||||
AnyExtensionDataRef extends UNewOutput ? UOutput : UNewOutput,
|
||||
AnyExtensionDataRef extends UNewOutput
|
||||
? NonNullable<T['output']>
|
||||
: UNewOutput,
|
||||
UFactoryOutput
|
||||
>;
|
||||
}): ExtensionDefinition<
|
||||
{
|
||||
[key in keyof TExtensionConfigSchema]: z.infer<
|
||||
ReturnType<TExtensionConfigSchema[key]>
|
||||
>;
|
||||
} & TConfig,
|
||||
z.input<
|
||||
z.ZodObject<{
|
||||
[key in keyof TExtensionConfigSchema]: ReturnType<
|
||||
TExtensionConfigSchema[key]
|
||||
>;
|
||||
}>
|
||||
> &
|
||||
TConfigInput,
|
||||
AnyExtensionDataRef extends UNewOutput ? UOutput : UNewOutput,
|
||||
TInputs & TExtraInputs,
|
||||
{
|
||||
kind: TIdParts['kind'];
|
||||
namespace: string | undefined extends TNewNamespace
|
||||
? TIdParts['namespace']
|
||||
: TNewNamespace;
|
||||
name: string | undefined extends TNewName ? TIdParts['name'] : TNewName;
|
||||
}
|
||||
>;
|
||||
}): 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;
|
||||
}>;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -219,7 +225,7 @@ export interface ExtensionBlueprint<
|
||||
* @public
|
||||
*/
|
||||
export function createExtensionBlueprint<
|
||||
TParams,
|
||||
TParams extends object,
|
||||
UOutput extends AnyExtensionDataRef,
|
||||
TInputs extends {
|
||||
[inputName in string]: ExtensionInput<
|
||||
@@ -245,27 +251,25 @@ export function createExtensionBlueprint<
|
||||
UFactoryOutput,
|
||||
TDataRefs
|
||||
>,
|
||||
): ExtensionBlueprint<
|
||||
{
|
||||
kind: TKind;
|
||||
namespace: TNamespace;
|
||||
name: TName;
|
||||
},
|
||||
TParams,
|
||||
UOutput,
|
||||
string extends keyof TInputs ? {} : TInputs,
|
||||
string extends keyof TConfigSchema
|
||||
): ExtensionBlueprint<{
|
||||
kind: TKind;
|
||||
namespace: TNamespace;
|
||||
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]>> },
|
||||
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]>;
|
||||
}>
|
||||
>,
|
||||
TDataRefs
|
||||
> {
|
||||
>;
|
||||
dataRefs: TDataRefs;
|
||||
}> {
|
||||
return {
|
||||
dataRefs: options.dataRefs,
|
||||
make(args) {
|
||||
@@ -282,7 +286,7 @@ export function createExtensionBlueprint<
|
||||
options.factory(args.params, ctx) as Iterable<
|
||||
ExtensionDataValue<any, any>
|
||||
>,
|
||||
});
|
||||
}) as ExtensionDefinition;
|
||||
},
|
||||
makeWithOverrides(args) {
|
||||
return createExtension({
|
||||
@@ -327,29 +331,27 @@ export function createExtensionBlueprint<
|
||||
},
|
||||
) as Iterable<ExtensionDataValue<any, any>>;
|
||||
},
|
||||
}) as ExtensionDefinition<any>;
|
||||
}) as ExtensionDefinition;
|
||||
},
|
||||
} as ExtensionBlueprint<
|
||||
{
|
||||
kind: TKind;
|
||||
namespace: TNamespace;
|
||||
name: TName;
|
||||
},
|
||||
TParams,
|
||||
UOutput,
|
||||
string extends keyof TInputs ? {} : TInputs,
|
||||
string extends keyof TConfigSchema
|
||||
} as ExtensionBlueprint<{
|
||||
kind: TKind;
|
||||
namespace: TNamespace;
|
||||
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]>>;
|
||||
},
|
||||
string extends keyof TConfigSchema
|
||||
};
|
||||
configInput: string extends keyof TConfigSchema
|
||||
? {}
|
||||
: z.input<
|
||||
z.ZodObject<{
|
||||
[key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;
|
||||
}>
|
||||
>,
|
||||
TDataRefs
|
||||
>;
|
||||
>;
|
||||
dataRefs: TDataRefs;
|
||||
}>;
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ describe('createExtensionOverrides', () => {
|
||||
"extensions": [
|
||||
{
|
||||
"$$type": "@backstage/Extension",
|
||||
"T": undefined,
|
||||
"attachTo": {
|
||||
"id": "app",
|
||||
"input": "apis",
|
||||
@@ -80,6 +81,7 @@ describe('createExtensionOverrides', () => {
|
||||
},
|
||||
{
|
||||
"$$type": "@backstage/Extension",
|
||||
"T": undefined,
|
||||
"attachTo": {
|
||||
"id": "app",
|
||||
"input": "apis",
|
||||
@@ -95,6 +97,7 @@ describe('createExtensionOverrides', () => {
|
||||
},
|
||||
{
|
||||
"$$type": "@backstage/Extension",
|
||||
"T": undefined,
|
||||
"attachTo": {
|
||||
"id": "app",
|
||||
"input": "apis",
|
||||
|
||||
@@ -23,7 +23,7 @@ import { ExtensionOverrides, FeatureFlagConfig } from './types';
|
||||
|
||||
/** @public */
|
||||
export interface ExtensionOverridesOptions {
|
||||
extensions: ExtensionDefinition<any, any>[];
|
||||
extensions: ExtensionDefinition[];
|
||||
featureFlags?: FeatureFlagConfig[];
|
||||
}
|
||||
|
||||
|
||||
@@ -150,6 +150,7 @@ describe('createFrontendPlugin', () => {
|
||||
expect(plugin.getExtension('test/1')).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$$type": "@backstage/ExtensionDefinition",
|
||||
"T": undefined,
|
||||
"attachTo": {
|
||||
"id": "test/output",
|
||||
"input": "names",
|
||||
@@ -281,6 +282,7 @@ describe('createFrontendPlugin', () => {
|
||||
expect(plugin.getExtension('test/1')).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$$type": "@backstage/ExtensionDefinition",
|
||||
"T": undefined,
|
||||
"attachTo": {
|
||||
"id": "test/output",
|
||||
"input": "names",
|
||||
|
||||
@@ -14,7 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ExtensionDefinition } from './createExtension';
|
||||
import {
|
||||
ExtensionDefinition,
|
||||
InternalExtensionDefinition,
|
||||
toInternalExtensionDefinition,
|
||||
} from './createExtension';
|
||||
import {
|
||||
Extension,
|
||||
ResolveExtensionId,
|
||||
@@ -32,7 +36,7 @@ export interface PluginOptions<
|
||||
TId extends string,
|
||||
TRoutes extends AnyRoutes,
|
||||
TExternalRoutes extends AnyExternalRoutes,
|
||||
TExtensions extends readonly ExtensionDefinition<any, any>[],
|
||||
TExtensions extends readonly ExtensionDefinition[],
|
||||
> {
|
||||
id: TId;
|
||||
routes?: TRoutes;
|
||||
@@ -56,7 +60,7 @@ export function createFrontendPlugin<
|
||||
TId extends string,
|
||||
TRoutes extends AnyRoutes = {},
|
||||
TExternalRoutes extends AnyExternalRoutes = {},
|
||||
TExtensions extends readonly ExtensionDefinition<any, any>[] = [],
|
||||
TExtensions extends readonly ExtensionDefinition[] = [],
|
||||
>(
|
||||
options: PluginOptions<TId, TRoutes, TExternalRoutes, TExtensions>,
|
||||
): BackstagePlugin<
|
||||
@@ -69,16 +73,20 @@ export function createFrontendPlugin<
|
||||
>]: KExtension;
|
||||
}
|
||||
> {
|
||||
const extensions = new Array<Extension<unknown>>();
|
||||
const extensions = new Array<Extension<any>>();
|
||||
const extensionDefinitionsById = new Map<
|
||||
string,
|
||||
ExtensionDefinition<unknown>
|
||||
InternalExtensionDefinition
|
||||
>();
|
||||
|
||||
for (const def of options.extensions ?? []) {
|
||||
const internal = toInternalExtensionDefinition(def);
|
||||
const ext = resolveExtensionDefinition(def, { namespace: options.id });
|
||||
extensions.push(ext);
|
||||
extensionDefinitionsById.set(ext.id, { ...def, namespace: options.id });
|
||||
extensionDefinitionsById.set(ext.id, {
|
||||
...internal,
|
||||
namespace: options.id,
|
||||
});
|
||||
}
|
||||
|
||||
if (extensions.length !== extensionDefinitionsById.size) {
|
||||
|
||||
@@ -18,6 +18,7 @@ export { coreExtensionData } from './coreExtensionData';
|
||||
export {
|
||||
createExtension,
|
||||
type ExtensionDefinition,
|
||||
type ExtensionDefinitionParameters,
|
||||
type CreateExtensionOptions,
|
||||
type ResolvedExtensionInput,
|
||||
type ResolvedExtensionInputs,
|
||||
@@ -56,6 +57,7 @@ export {
|
||||
export {
|
||||
type CreateExtensionBlueprintOptions,
|
||||
type ExtensionBlueprint,
|
||||
type ExtensionBlueprintParameters,
|
||||
createExtensionBlueprint,
|
||||
} from './createExtensionBlueprint';
|
||||
export { type ResolveInputValueOverrides } from './resolveInputOverrides';
|
||||
|
||||
@@ -23,10 +23,11 @@ import {
|
||||
describe('resolveExtensionDefinition', () => {
|
||||
const baseDef = {
|
||||
$$type: '@backstage/ExtensionDefinition',
|
||||
T: undefined as any,
|
||||
version: 'v2',
|
||||
attachTo: { id: '', input: '' },
|
||||
disabled: false,
|
||||
override: () => ({} as ExtensionDefinition<unknown>),
|
||||
override: () => ({} as ExtensionDefinition),
|
||||
};
|
||||
|
||||
it.each([
|
||||
@@ -39,7 +40,7 @@ describe('resolveExtensionDefinition', () => {
|
||||
const resolved = resolveExtensionDefinition({
|
||||
...baseDef,
|
||||
...definition,
|
||||
} as ExtensionDefinition<unknown>);
|
||||
} as ExtensionDefinition);
|
||||
expect(resolved.id).toBe(expected);
|
||||
expect(String(resolved)).toBe(`Extension{id=${expected}}`);
|
||||
});
|
||||
@@ -49,12 +50,12 @@ describe('resolveExtensionDefinition', () => {
|
||||
resolveExtensionDefinition({
|
||||
...baseDef,
|
||||
kind: 'k',
|
||||
} as ExtensionDefinition<unknown>),
|
||||
} as ExtensionDefinition),
|
||||
).toThrow(
|
||||
'Extension must declare an explicit namespace or name as it could not be resolved from context, kind=k namespace=undefined name=undefined',
|
||||
);
|
||||
expect(() =>
|
||||
resolveExtensionDefinition(baseDef as ExtensionDefinition<unknown>),
|
||||
resolveExtensionDefinition(baseDef as ExtensionDefinition),
|
||||
).toThrow(
|
||||
'Extension must declare an explicit namespace or name as it could not be resolved from context, kind=undefined namespace=undefined name=undefined',
|
||||
);
|
||||
@@ -64,10 +65,11 @@ describe('resolveExtensionDefinition', () => {
|
||||
describe('old resolveExtensionDefinition', () => {
|
||||
const baseDef = {
|
||||
$$type: '@backstage/ExtensionDefinition',
|
||||
T: undefined as any,
|
||||
version: 'v1',
|
||||
attachTo: { id: '', input: '' },
|
||||
disabled: false,
|
||||
override: () => ({} as ExtensionDefinition<unknown>),
|
||||
override: () => ({} as ExtensionDefinition),
|
||||
};
|
||||
|
||||
it.each([
|
||||
@@ -80,7 +82,7 @@ describe('old resolveExtensionDefinition', () => {
|
||||
const resolved = resolveExtensionDefinition({
|
||||
...baseDef,
|
||||
...definition,
|
||||
} as ExtensionDefinition<unknown>);
|
||||
} as ExtensionDefinition);
|
||||
expect(resolved.id).toBe(expected);
|
||||
expect(String(resolved)).toBe(`Extension{id=${expected}}`);
|
||||
});
|
||||
@@ -90,12 +92,12 @@ describe('old resolveExtensionDefinition', () => {
|
||||
resolveExtensionDefinition({
|
||||
...baseDef,
|
||||
kind: 'k',
|
||||
} as ExtensionDefinition<unknown>),
|
||||
} as ExtensionDefinition),
|
||||
).toThrow(
|
||||
'Extension must declare an explicit namespace or name as it could not be resolved from context, kind=k namespace=undefined name=undefined',
|
||||
);
|
||||
expect(() =>
|
||||
resolveExtensionDefinition(baseDef as ExtensionDefinition<unknown>),
|
||||
resolveExtensionDefinition(baseDef as ExtensionDefinition),
|
||||
).toThrow(
|
||||
'Extension must declare an explicit namespace or name as it could not be resolved from context, kind=undefined namespace=undefined name=undefined',
|
||||
);
|
||||
@@ -108,13 +110,12 @@ describe('ResolveExtensionId', () => {
|
||||
TKind extends string | undefined,
|
||||
TNamespace extends string | undefined,
|
||||
TName extends string | undefined,
|
||||
> = ExtensionDefinition<
|
||||
any,
|
||||
any,
|
||||
any,
|
||||
any,
|
||||
{ kind: TKind; namespace: TNamespace; name: TName }
|
||||
>;
|
||||
> = ExtensionDefinition<{
|
||||
kind: TKind;
|
||||
namespace: TNamespace;
|
||||
name: TName;
|
||||
output: any;
|
||||
}>;
|
||||
|
||||
const id1: 'k:ns' = {} as ResolveExtensionId<
|
||||
NamedExtension<'k', 'ns', undefined>,
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
import { ApiHolder, AppNode } from '../apis';
|
||||
import {
|
||||
ExtensionDefinition,
|
||||
ExtensionDefinitionParameters,
|
||||
ResolvedExtensionInputs,
|
||||
toInternalExtensionDefinition,
|
||||
} from './createExtension';
|
||||
@@ -109,19 +110,13 @@ export function toInternalExtension<TConfig, TConfigInput>(
|
||||
|
||||
/** @ignore */
|
||||
export type ResolveExtensionId<
|
||||
TExtension extends ExtensionDefinition<any>,
|
||||
TExtension extends ExtensionDefinition,
|
||||
TDefaultNamespace extends string | undefined,
|
||||
> = TExtension extends ExtensionDefinition<
|
||||
any,
|
||||
any,
|
||||
any,
|
||||
any,
|
||||
{
|
||||
kind: infer IKind extends string | undefined;
|
||||
namespace: infer INamespace extends string | undefined;
|
||||
name: infer IName extends string | undefined;
|
||||
}
|
||||
>
|
||||
> = 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]
|
||||
? never
|
||||
: (
|
||||
@@ -140,10 +135,12 @@ export type ResolveExtensionId<
|
||||
: never;
|
||||
|
||||
/** @internal */
|
||||
export function resolveExtensionDefinition<TConfig, TConfigInput>(
|
||||
definition: ExtensionDefinition<TConfig, TConfigInput>,
|
||||
export function resolveExtensionDefinition<
|
||||
T extends ExtensionDefinitionParameters,
|
||||
>(
|
||||
definition: ExtensionDefinition<T>,
|
||||
context?: { namespace?: string },
|
||||
): Extension<TConfig, TConfigInput> {
|
||||
): Extension<T['config'], T['configInput']> {
|
||||
const internalDefinition = toInternalExtensionDefinition(definition);
|
||||
const {
|
||||
name,
|
||||
@@ -172,5 +169,5 @@ export function resolveExtensionDefinition<TConfig, TConfigInput>(
|
||||
toString() {
|
||||
return `Extension{id=${id}}`;
|
||||
},
|
||||
} as InternalExtension<TConfig, TConfigInput>;
|
||||
} as InternalExtension<T['config'], T['configInput']> & Object;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ export type AnyExternalRoutes = { [name in string]: ExternalRouteRef };
|
||||
|
||||
/** @public */
|
||||
export type ExtensionMap<
|
||||
TExtensionMap extends { [id in string]: ExtensionDefinition<any, any> },
|
||||
TExtensionMap extends { [id in string]: ExtensionDefinition },
|
||||
> = {
|
||||
get<TId extends keyof TExtensionMap>(id: TId): TExtensionMap[TId];
|
||||
};
|
||||
@@ -44,7 +44,7 @@ export type ExtensionMap<
|
||||
export interface BackstagePlugin<
|
||||
TRoutes extends AnyRoutes = AnyRoutes,
|
||||
TExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes,
|
||||
TExtensionMap extends { [id in string]: ExtensionDefinition<any, any> } = {},
|
||||
TExtensionMap extends { [id in string]: ExtensionDefinition } = {},
|
||||
> {
|
||||
readonly $$type: '@backstage/BackstagePlugin';
|
||||
readonly id: string;
|
||||
@@ -52,7 +52,7 @@ export interface BackstagePlugin<
|
||||
readonly externalRoutes: TExternalRoutes;
|
||||
getExtension<TId extends keyof TExtensionMap>(id: TId): TExtensionMap[TId];
|
||||
withOverrides(options: {
|
||||
extensions: Array<ExtensionDefinition<any, any>>;
|
||||
extensions: Array<ExtensionDefinition>;
|
||||
}): BackstagePlugin<TRoutes, TExternalRoutes, TExtensionMap>;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import { AppNodeInstance } from '@backstage/frontend-plugin-api';
|
||||
import { ErrorWithContext } from '@backstage/test-utils';
|
||||
import { ExtensionDataRef } from '@backstage/frontend-plugin-api';
|
||||
import { ExtensionDefinition } from '@backstage/frontend-plugin-api';
|
||||
import { ExtensionDefinitionParameters } from '@backstage/frontend-plugin-api';
|
||||
import { JsonObject } from '@backstage/types';
|
||||
import { MockConfigApi } from '@backstage/test-utils';
|
||||
import { MockErrorApi } from '@backstage/test-utils';
|
||||
@@ -31,16 +32,12 @@ import { TestApiRegistry } from '@backstage/test-utils';
|
||||
import { withLogCollector } from '@backstage/test-utils';
|
||||
|
||||
// @public (undocumented)
|
||||
export function createExtensionTester<
|
||||
TConfig,
|
||||
TConfigInput,
|
||||
UOutput extends AnyExtensionDataRef,
|
||||
>(
|
||||
subject: ExtensionDefinition<TConfig, TConfigInput, UOutput>,
|
||||
export function createExtensionTester<T extends ExtensionDefinitionParameters>(
|
||||
subject: ExtensionDefinition<T>,
|
||||
options?: {
|
||||
config?: TConfigInput;
|
||||
config?: T['configInput'];
|
||||
},
|
||||
): ExtensionTester<UOutput>;
|
||||
): ExtensionTester<NonNullable<T['output']>>;
|
||||
|
||||
export { ErrorWithContext };
|
||||
|
||||
@@ -64,10 +61,10 @@ export class ExtensionQuery<UOutput extends AnyExtensionDataRef> {
|
||||
// @public (undocumented)
|
||||
export class ExtensionTester<UOutput extends AnyExtensionDataRef> {
|
||||
// (undocumented)
|
||||
add<TConfig, TConfigInput>(
|
||||
extension: ExtensionDefinition<TConfig, TConfigInput>,
|
||||
add<T extends ExtensionDefinitionParameters>(
|
||||
extension: ExtensionDefinition<T>,
|
||||
options?: {
|
||||
config?: TConfigInput;
|
||||
config?: T['configInput'];
|
||||
},
|
||||
): ExtensionTester<UOutput>;
|
||||
// (undocumented)
|
||||
@@ -79,9 +76,9 @@ export class ExtensionTester<UOutput extends AnyExtensionDataRef> {
|
||||
: IData
|
||||
: never;
|
||||
// (undocumented)
|
||||
query<UQueryExtensionOutput extends AnyExtensionDataRef>(
|
||||
extension: ExtensionDefinition<any, any, UQueryExtensionOutput>,
|
||||
): ExtensionQuery<UQueryExtensionOutput>;
|
||||
query<T extends ExtensionDefinitionParameters>(
|
||||
extension: ExtensionDefinition<T>,
|
||||
): ExtensionQuery<NonNullable<T['output']>>;
|
||||
// (undocumented)
|
||||
reactElement(): JSX.Element;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
Extension,
|
||||
ExtensionDataRef,
|
||||
ExtensionDefinition,
|
||||
ExtensionDefinitionParameters,
|
||||
coreExtensionData,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
import { Config, ConfigReader } from '@backstage/config';
|
||||
@@ -28,6 +29,8 @@ import { JsonArray, JsonObject, JsonValue } from '@backstage/types';
|
||||
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
|
||||
import { resolveExtensionDefinition } from '../../../frontend-plugin-api/src/wiring/resolveExtensionDefinition';
|
||||
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
|
||||
import { toInternalExtensionDefinition } from '../../../frontend-plugin-api/src/wiring/createExtension';
|
||||
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
|
||||
import { resolveAppTree } from '../../../frontend-app-api/src/tree/resolveAppTree';
|
||||
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
|
||||
import { resolveAppNodeSpecs } from '../../../frontend-app-api/src/tree/resolveAppNodeSpecs';
|
||||
@@ -75,12 +78,12 @@ export class ExtensionQuery<UOutput extends AnyExtensionDataRef> {
|
||||
/** @public */
|
||||
export class ExtensionTester<UOutput extends AnyExtensionDataRef> {
|
||||
/** @internal */
|
||||
static forSubject<TConfig, TConfigInput, UOutput extends AnyExtensionDataRef>(
|
||||
subject: ExtensionDefinition<TConfig, TConfigInput>,
|
||||
options?: { config?: TConfigInput },
|
||||
): ExtensionTester<UOutput> {
|
||||
static forSubject<T extends ExtensionDefinitionParameters>(
|
||||
subject: ExtensionDefinition<T>,
|
||||
options?: { config?: T['configInput'] },
|
||||
): ExtensionTester<NonNullable<T['output']>> {
|
||||
const tester = new ExtensionTester();
|
||||
tester.add(subject, options as TConfigInput & {});
|
||||
tester.add(subject, options as T['configInput'] & {});
|
||||
return tester;
|
||||
}
|
||||
|
||||
@@ -89,13 +92,13 @@ export class ExtensionTester<UOutput extends AnyExtensionDataRef> {
|
||||
readonly #extensions = new Array<{
|
||||
id: string;
|
||||
extension: Extension<any>;
|
||||
definition: ExtensionDefinition<any>;
|
||||
definition: ExtensionDefinition;
|
||||
config?: JsonValue;
|
||||
}>();
|
||||
|
||||
add<TConfig, TConfigInput>(
|
||||
extension: ExtensionDefinition<TConfig, TConfigInput>,
|
||||
options?: { config?: TConfigInput },
|
||||
add<T extends ExtensionDefinitionParameters>(
|
||||
extension: ExtensionDefinition<T>,
|
||||
options?: { config?: T['configInput'] },
|
||||
): ExtensionTester<UOutput> {
|
||||
if (this.#tree) {
|
||||
throw new Error(
|
||||
@@ -103,7 +106,7 @@ export class ExtensionTester<UOutput extends AnyExtensionDataRef> {
|
||||
);
|
||||
}
|
||||
|
||||
const { name, namespace } = extension;
|
||||
const { name, namespace } = toInternalExtensionDefinition(extension);
|
||||
|
||||
const definition = {
|
||||
...extension,
|
||||
@@ -135,12 +138,18 @@ export class ExtensionTester<UOutput extends AnyExtensionDataRef> {
|
||||
return new ExtensionQuery(tree.root).get(ref);
|
||||
}
|
||||
|
||||
query<UQueryExtensionOutput extends AnyExtensionDataRef>(
|
||||
extension: ExtensionDefinition<any, any, UQueryExtensionOutput>,
|
||||
): ExtensionQuery<UQueryExtensionOutput> {
|
||||
query<T extends ExtensionDefinitionParameters>(
|
||||
extension: ExtensionDefinition<T>,
|
||||
): ExtensionQuery<NonNullable<T['output']>> {
|
||||
const tree = this.#resolveTree();
|
||||
|
||||
const actualId = resolveExtensionDefinition(extension).id;
|
||||
// Same fallback logic as in .add
|
||||
const { name, namespace } = toInternalExtensionDefinition(extension);
|
||||
const definition = {
|
||||
...extension,
|
||||
name: !namespace && !name ? 'test' : name,
|
||||
};
|
||||
const actualId = resolveExtensionDefinition(definition).id;
|
||||
|
||||
const node = tree.nodes.get(actualId);
|
||||
|
||||
@@ -232,13 +241,9 @@ export class ExtensionTester<UOutput extends AnyExtensionDataRef> {
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export function createExtensionTester<
|
||||
TConfig,
|
||||
TConfigInput,
|
||||
UOutput extends AnyExtensionDataRef,
|
||||
>(
|
||||
subject: ExtensionDefinition<TConfig, TConfigInput, UOutput>,
|
||||
options?: { config?: TConfigInput },
|
||||
): ExtensionTester<UOutput> {
|
||||
export function createExtensionTester<T extends ExtensionDefinitionParameters>(
|
||||
subject: ExtensionDefinition<T>,
|
||||
options?: { config?: T['configInput'] },
|
||||
): ExtensionTester<NonNullable<T['output']>> {
|
||||
return ExtensionTester.forSubject(subject, options);
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ export function renderInTestApp(
|
||||
element: JSX.Element,
|
||||
options?: TestAppOptions,
|
||||
): RenderResult {
|
||||
const extensions: Array<ExtensionDefinition<any, any>> = [
|
||||
const extensions: Array<ExtensionDefinition> = [
|
||||
createExtension({
|
||||
namespace: 'test',
|
||||
attachTo: { id: 'app/routes', input: 'routes' },
|
||||
|
||||
@@ -25,10 +25,13 @@ const _default: BackstagePlugin<
|
||||
registerApi: ExternalRouteRef<undefined>;
|
||||
},
|
||||
{
|
||||
'nav-item:api-docs': ExtensionDefinition<
|
||||
{},
|
||||
{},
|
||||
ConfigurableExtensionDataRef<
|
||||
'nav-item:api-docs': ExtensionDefinition<{
|
||||
kind: 'nav-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
output: ConfigurableExtensionDataRef<
|
||||
{
|
||||
title: string;
|
||||
icon: IconComponent;
|
||||
@@ -36,50 +39,48 @@ const _default: BackstagePlugin<
|
||||
},
|
||||
'core.nav-item.target',
|
||||
{}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
kind: 'nav-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}
|
||||
>;
|
||||
'api:api-docs/config': ExtensionDefinition<
|
||||
{},
|
||||
{},
|
||||
ConfigurableExtensionDataRef<AnyApiFactory, 'core.api.factory', {}>,
|
||||
{},
|
||||
{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'config';
|
||||
}
|
||||
>;
|
||||
'page:api-docs': ExtensionDefinition<
|
||||
{
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'api:api-docs/config': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'config';
|
||||
config: {};
|
||||
configInput: {};
|
||||
output: ConfigurableExtensionDataRef<
|
||||
AnyApiFactory,
|
||||
'core.api.factory',
|
||||
{}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'page:api-docs': ExtensionDefinition<{
|
||||
config: {
|
||||
initiallySelectedFilter: 'all' | 'owned' | 'starred' | undefined;
|
||||
} & {
|
||||
path: string | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
initiallySelectedFilter?: 'all' | 'owned' | 'starred' | undefined;
|
||||
} & {
|
||||
path?: string | undefined;
|
||||
},
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>,
|
||||
{
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {
|
||||
[x: string]: ExtensionInput<
|
||||
AnyExtensionDataRef,
|
||||
{
|
||||
@@ -87,303 +88,301 @@ const _default: BackstagePlugin<
|
||||
singleton: boolean;
|
||||
}
|
||||
>;
|
||||
},
|
||||
{
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}
|
||||
>;
|
||||
'entity-card:api-docs/has-apis': ExtensionDefinition<
|
||||
{
|
||||
};
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}>;
|
||||
'entity-card:api-docs/has-apis': ExtensionDefinition<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'has-apis';
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
filter?: string | undefined;
|
||||
},
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'has-apis';
|
||||
}
|
||||
>;
|
||||
'entity-card:api-docs/definition': ExtensionDefinition<
|
||||
{
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'entity-card:api-docs/definition': ExtensionDefinition<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'definition';
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
filter?: string | undefined;
|
||||
},
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'definition';
|
||||
}
|
||||
>;
|
||||
'entity-card:api-docs/consumed-apis': ExtensionDefinition<
|
||||
{
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'entity-card:api-docs/consumed-apis': ExtensionDefinition<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'consumed-apis';
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
filter?: string | undefined;
|
||||
},
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'consumed-apis';
|
||||
}
|
||||
>;
|
||||
'entity-card:api-docs/provided-apis': ExtensionDefinition<
|
||||
{
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'entity-card:api-docs/provided-apis': ExtensionDefinition<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'provided-apis';
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
filter?: string | undefined;
|
||||
},
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'provided-apis';
|
||||
}
|
||||
>;
|
||||
'entity-card:api-docs/consuming-components': ExtensionDefinition<
|
||||
{
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'entity-card:api-docs/consuming-components': ExtensionDefinition<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'consuming-components';
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
filter?: string | undefined;
|
||||
},
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'consuming-components';
|
||||
}
|
||||
>;
|
||||
'entity-card:api-docs/providing-components': ExtensionDefinition<
|
||||
{
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'entity-card:api-docs/providing-components': ExtensionDefinition<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'providing-components';
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
filter?: string | undefined;
|
||||
},
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'providing-components';
|
||||
}
|
||||
>;
|
||||
'entity-content:api-docs/definition': ExtensionDefinition<
|
||||
{
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'entity-content:api-docs/definition': ExtensionDefinition<{
|
||||
kind: 'entity-content';
|
||||
namespace: undefined;
|
||||
name: 'definition';
|
||||
config: {
|
||||
path: string | undefined;
|
||||
title: string | undefined;
|
||||
filter: string | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
filter?: string | undefined;
|
||||
title?: string | undefined;
|
||||
path?: string | undefined;
|
||||
},
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'catalog.entity-content-title', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
kind: 'entity-content';
|
||||
namespace: undefined;
|
||||
name: 'definition';
|
||||
}
|
||||
>;
|
||||
'entity-content:api-docs/apis': ExtensionDefinition<
|
||||
{
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-content-title',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'entity-content:api-docs/apis': ExtensionDefinition<{
|
||||
kind: 'entity-content';
|
||||
namespace: undefined;
|
||||
name: 'apis';
|
||||
config: {
|
||||
path: string | undefined;
|
||||
title: string | undefined;
|
||||
filter: string | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
filter?: string | undefined;
|
||||
title?: string | undefined;
|
||||
path?: string | undefined;
|
||||
},
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'catalog.entity-content-title', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
kind: 'entity-content';
|
||||
namespace: undefined;
|
||||
name: 'apis';
|
||||
}
|
||||
>;
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-content-title',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
}
|
||||
>;
|
||||
export default _default;
|
||||
|
||||
@@ -16,37 +16,39 @@ const visualizerPlugin: BackstagePlugin<
|
||||
{},
|
||||
{},
|
||||
{
|
||||
'page:app-visualizer': ExtensionDefinition<
|
||||
{
|
||||
'page:app-visualizer': ExtensionDefinition<{
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {
|
||||
path: string | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
path?: string | undefined;
|
||||
},
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}
|
||||
>;
|
||||
'nav-item:app-visualizer': ExtensionDefinition<
|
||||
{},
|
||||
{},
|
||||
ConfigurableExtensionDataRef<
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'nav-item:app-visualizer': ExtensionDefinition<{
|
||||
kind: 'nav-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
output: ConfigurableExtensionDataRef<
|
||||
{
|
||||
title: string;
|
||||
icon: IconComponent;
|
||||
@@ -54,14 +56,9 @@ const visualizerPlugin: BackstagePlugin<
|
||||
},
|
||||
'core.nav-item.target',
|
||||
{}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
kind: 'nav-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}
|
||||
>;
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
}
|
||||
>;
|
||||
export default visualizerPlugin;
|
||||
|
||||
@@ -28,8 +28,8 @@ const _default: BackstagePlugin<
|
||||
}>;
|
||||
},
|
||||
{
|
||||
'entity-card:catalog-graph/relations': ExtensionDefinition<
|
||||
{
|
||||
'entity-card:catalog-graph/relations': ExtensionDefinition<{
|
||||
config: {
|
||||
kinds: string[] | undefined;
|
||||
relations: string[] | undefined;
|
||||
maxDepth: number | undefined;
|
||||
@@ -43,8 +43,8 @@ const _default: BackstagePlugin<
|
||||
height: number | undefined;
|
||||
} & {
|
||||
filter: string | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
height?: number | undefined;
|
||||
curve?: 'curveStepBefore' | 'curveMonotoneX' | undefined;
|
||||
direction?: Direction | undefined;
|
||||
@@ -58,27 +58,28 @@ const _default: BackstagePlugin<
|
||||
relationPairs?: [string, string][] | undefined;
|
||||
} & {
|
||||
filter?: string | undefined;
|
||||
},
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>,
|
||||
{
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {
|
||||
[x: string]: ExtensionInput<
|
||||
AnyExtensionDataRef,
|
||||
{
|
||||
@@ -86,15 +87,13 @@ const _default: BackstagePlugin<
|
||||
singleton: boolean;
|
||||
}
|
||||
>;
|
||||
},
|
||||
{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'relations';
|
||||
}
|
||||
>;
|
||||
'page:catalog-graph': ExtensionDefinition<
|
||||
{
|
||||
};
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'relations';
|
||||
}>;
|
||||
'page:catalog-graph': ExtensionDefinition<{
|
||||
config: {
|
||||
selectedKinds: string[] | undefined;
|
||||
selectedRelations: string[] | undefined;
|
||||
rootEntityRefs: string[] | undefined;
|
||||
@@ -110,8 +109,8 @@ const _default: BackstagePlugin<
|
||||
zoom: 'disabled' | 'enabled' | 'enable-on-click' | undefined;
|
||||
} & {
|
||||
path: string | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
curve?: 'curveStepBefore' | 'curveMonotoneX' | undefined;
|
||||
direction?: Direction | undefined;
|
||||
zoom?: 'disabled' | 'enabled' | 'enable-on-click' | undefined;
|
||||
@@ -127,21 +126,22 @@ const _default: BackstagePlugin<
|
||||
showFilters?: boolean | undefined;
|
||||
} & {
|
||||
path?: string | undefined;
|
||||
},
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>,
|
||||
{
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {
|
||||
[x: string]: ExtensionInput<
|
||||
AnyExtensionDataRef,
|
||||
{
|
||||
@@ -149,13 +149,11 @@ const _default: BackstagePlugin<
|
||||
singleton: boolean;
|
||||
}
|
||||
>;
|
||||
},
|
||||
{
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}
|
||||
>;
|
||||
};
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}>;
|
||||
}
|
||||
>;
|
||||
export default _default;
|
||||
|
||||
@@ -18,44 +18,45 @@ const _default: BackstagePlugin<
|
||||
},
|
||||
{},
|
||||
{
|
||||
'api:catalog-import': ExtensionDefinition<
|
||||
{},
|
||||
{},
|
||||
ConfigurableExtensionDataRef<AnyApiFactory, 'core.api.factory', {}>,
|
||||
{},
|
||||
{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}
|
||||
>;
|
||||
'page:catalog-import': ExtensionDefinition<
|
||||
{
|
||||
'api:catalog-import': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
output: ConfigurableExtensionDataRef<
|
||||
AnyApiFactory,
|
||||
'core.api.factory',
|
||||
{}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'page:catalog-import': ExtensionDefinition<{
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {
|
||||
path: string | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
path?: string | undefined;
|
||||
},
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}
|
||||
>;
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
}
|
||||
>;
|
||||
export default _default;
|
||||
|
||||
@@ -83,7 +83,7 @@ export function convertLegacyEntityCardExtension(
|
||||
| typeof EntityCardBlueprint.dataRefs.filterFunction.T
|
||||
| typeof EntityCardBlueprint.dataRefs.filterExpression.T;
|
||||
},
|
||||
): ExtensionDefinition<any>;
|
||||
): ExtensionDefinition;
|
||||
|
||||
// @alpha (undocumented)
|
||||
export function convertLegacyEntityContentExtension(
|
||||
@@ -96,42 +96,41 @@ export function convertLegacyEntityContentExtension(
|
||||
defaultPath?: string;
|
||||
defaultTitle?: string;
|
||||
},
|
||||
): ExtensionDefinition<any>;
|
||||
): ExtensionDefinition;
|
||||
|
||||
// @alpha
|
||||
export const EntityCardBlueprint: ExtensionBlueprint<
|
||||
{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
},
|
||||
{
|
||||
export const EntityCardBlueprint: ExtensionBlueprint<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
params: {
|
||||
loader: () => Promise<JSX.Element>;
|
||||
filter?: string | ((entity: Entity) => boolean) | undefined;
|
||||
},
|
||||
| ConfigurableExtensionDataRef<JSX_2.Element, 'core.reactElement', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<JSX_2.Element, 'core.reactElement', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {};
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
filter?: string | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
dataRefs: {
|
||||
filterFunction: ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
@@ -142,59 +141,58 @@ export const EntityCardBlueprint: ExtensionBlueprint<
|
||||
'catalog.entity-filter-expression',
|
||||
{}
|
||||
>;
|
||||
}
|
||||
>;
|
||||
};
|
||||
}>;
|
||||
|
||||
// @alpha
|
||||
export const EntityContentBlueprint: ExtensionBlueprint<
|
||||
{
|
||||
kind: 'entity-content';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
},
|
||||
{
|
||||
export const EntityContentBlueprint: ExtensionBlueprint<{
|
||||
kind: 'entity-content';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
params: {
|
||||
loader: () => Promise<JSX.Element>;
|
||||
defaultPath: string;
|
||||
defaultTitle: string;
|
||||
routeRef?: RouteRef<AnyRouteRefParams> | undefined;
|
||||
filter?: string | ((entity: Entity) => boolean) | undefined;
|
||||
},
|
||||
| ConfigurableExtensionDataRef<JSX_2.Element, 'core.reactElement', {}>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'catalog.entity-content-title', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<JSX_2.Element, 'core.reactElement', {}>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'catalog.entity-content-title', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {};
|
||||
config: {
|
||||
path: string | undefined;
|
||||
title: string | undefined;
|
||||
filter: string | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
filter?: string | undefined;
|
||||
title?: string | undefined;
|
||||
path?: string | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
dataRefs: {
|
||||
title: ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-content-title',
|
||||
@@ -210,8 +208,8 @@ export const EntityContentBlueprint: ExtensionBlueprint<
|
||||
'catalog.entity-filter-expression',
|
||||
{}
|
||||
>;
|
||||
}
|
||||
>;
|
||||
};
|
||||
}>;
|
||||
|
||||
// @alpha
|
||||
export function isOwnerOf(owner: Entity, entity: Entity): boolean;
|
||||
|
||||
@@ -40,6 +40,7 @@ describe('EntityCardBlueprint', () => {
|
||||
expect(extension).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$$type": "@backstage/ExtensionDefinition",
|
||||
"T": undefined,
|
||||
"attachTo": {
|
||||
"id": "entity-content:catalog/overview",
|
||||
"input": "cards",
|
||||
|
||||
@@ -42,6 +42,7 @@ describe('EntityContentBlueprint', () => {
|
||||
expect(extension).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$$type": "@backstage/ExtensionDefinition",
|
||||
"T": undefined,
|
||||
"attachTo": {
|
||||
"id": "page:catalog/entity",
|
||||
"input": "contents",
|
||||
|
||||
+12
-14
@@ -48,12 +48,11 @@ describe('convertLegacyEntityCardExtension', () => {
|
||||
);
|
||||
|
||||
const converted = convertLegacyEntityCardExtension(LegacyExtension);
|
||||
expect(converted.kind).toBe('entity-card');
|
||||
expect(converted.namespace).toBe(undefined);
|
||||
expect(converted.name).toBe('example');
|
||||
|
||||
const tester = createExtensionTester(converted);
|
||||
|
||||
expect(tester.query(converted).node.spec.id).toBe('entity-card:example');
|
||||
|
||||
await renderInTestApp(tester.reactElement(), {
|
||||
mountedRoutes: {
|
||||
'/': convertLegacyRouteRef(routeRef),
|
||||
@@ -83,12 +82,11 @@ describe('convertLegacyEntityCardExtension', () => {
|
||||
name: 'other',
|
||||
filter: 'my-filter',
|
||||
});
|
||||
expect(converted.kind).toBe('entity-card');
|
||||
expect(converted.namespace).toBe(undefined);
|
||||
expect(converted.name).toBe('other');
|
||||
|
||||
const tester = createExtensionTester(converted);
|
||||
|
||||
expect(tester.query(converted).node.spec.id).toBe('entity-card:other');
|
||||
|
||||
await renderInTestApp(tester.reactElement(), {
|
||||
mountedRoutes: {
|
||||
'/': convertLegacyRouteRef(routeRef),
|
||||
@@ -106,7 +104,7 @@ describe('convertLegacyEntityCardExtension', () => {
|
||||
});
|
||||
|
||||
it('should support various naming patterns for entity card extensions', async () => {
|
||||
const withName = (name: string) => {
|
||||
const getDiscoveredId = (name: string) => {
|
||||
const converted = convertLegacyEntityCardExtension(
|
||||
legacyPlugin.provide(
|
||||
createRoutableExtension({
|
||||
@@ -116,14 +114,14 @@ describe('convertLegacyEntityCardExtension', () => {
|
||||
}),
|
||||
),
|
||||
);
|
||||
return converted.name;
|
||||
return createExtensionTester(converted).query(converted).node.spec.id;
|
||||
};
|
||||
|
||||
expect(withName('EntityTestCard')).toBe(undefined);
|
||||
expect(withName('EntityTestTrimCard')).toBe('trim');
|
||||
expect(withName('EntityTeStTrimCard')).toBe('trim');
|
||||
expect(withName('EntityExampleCard')).toBe('example');
|
||||
expect(withName('EntityExAmpleCard')).toBe('ex-ample');
|
||||
expect(withName('ExampleCard')).toBe('example-card');
|
||||
expect(getDiscoveredId('EntityTestCard')).toBe('entity-card:test'); // falls back to test namespace
|
||||
expect(getDiscoveredId('EntityTestTrimCard')).toBe('entity-card:trim');
|
||||
expect(getDiscoveredId('EntityTeStTrimCard')).toBe('entity-card:trim');
|
||||
expect(getDiscoveredId('EntityExampleCard')).toBe('entity-card:example');
|
||||
expect(getDiscoveredId('EntityExAmpleCard')).toBe('entity-card:ex-ample');
|
||||
expect(getDiscoveredId('ExampleCard')).toBe('entity-card:example-card');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -30,7 +30,7 @@ export function convertLegacyEntityCardExtension(
|
||||
| typeof EntityCardBlueprint.dataRefs.filterFunction.T
|
||||
| typeof EntityCardBlueprint.dataRefs.filterExpression.T;
|
||||
},
|
||||
): ExtensionDefinition<any> {
|
||||
): ExtensionDefinition {
|
||||
const element = <LegacyExtension />;
|
||||
|
||||
const extName = getComponentData<string>(element, 'core.extensionName');
|
||||
|
||||
+11
-13
@@ -49,12 +49,11 @@ describe('convertLegacyEntityContentExtension', () => {
|
||||
);
|
||||
|
||||
const converted = convertLegacyEntityContentExtension(LegacyExtension);
|
||||
expect(converted.kind).toBe('entity-content');
|
||||
expect(converted.namespace).toBe(undefined);
|
||||
expect(converted.name).toBe('example');
|
||||
|
||||
const tester = createExtensionTester(converted);
|
||||
|
||||
expect(tester.query(converted).node.spec.id).toBe('entity-content:example');
|
||||
|
||||
await renderInTestApp(tester.reactElement(), {
|
||||
mountedRoutes: {
|
||||
'/': convertLegacyRouteRef(routeRef),
|
||||
@@ -88,12 +87,11 @@ describe('convertLegacyEntityContentExtension', () => {
|
||||
defaultTitle: 'Other',
|
||||
filter: 'my-filter',
|
||||
});
|
||||
expect(converted.kind).toBe('entity-content');
|
||||
expect(converted.namespace).toBe(undefined);
|
||||
expect(converted.name).toBe('other');
|
||||
|
||||
const tester = createExtensionTester(converted);
|
||||
|
||||
expect(tester.query(converted).node.spec.id).toBe('entity-content:other');
|
||||
|
||||
await renderInTestApp(tester.reactElement(), {
|
||||
mountedRoutes: {
|
||||
'/': convertLegacyRouteRef(routeRef),
|
||||
@@ -123,14 +121,14 @@ describe('convertLegacyEntityContentExtension', () => {
|
||||
}),
|
||||
),
|
||||
);
|
||||
return converted.name;
|
||||
return createExtensionTester(converted).query(converted).node.spec.id;
|
||||
};
|
||||
|
||||
expect(withName('EntityTestContent')).toBe(undefined);
|
||||
expect(withName('EntityTestTrimContent')).toBe('trim');
|
||||
expect(withName('EntityTeStTrimContent')).toBe('trim');
|
||||
expect(withName('EntityExampleContent')).toBe('example');
|
||||
expect(withName('EntityExAmpleContent')).toBe('ex-ample');
|
||||
expect(withName('ExampleContent')).toBe('example-content');
|
||||
expect(withName('EntityTestContent')).toBe('entity-content:test'); // falls back to test namespace
|
||||
expect(withName('EntityTestTrimContent')).toBe('entity-content:trim');
|
||||
expect(withName('EntityTeStTrimContent')).toBe('entity-content:trim');
|
||||
expect(withName('EntityExampleContent')).toBe('entity-content:example');
|
||||
expect(withName('EntityExAmpleContent')).toBe('entity-content:ex-ample');
|
||||
expect(withName('ExampleContent')).toBe('entity-content:example-content');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -40,7 +40,7 @@ export function convertLegacyEntityContentExtension(
|
||||
defaultPath?: string;
|
||||
defaultTitle?: string;
|
||||
},
|
||||
): ExtensionDefinition<any> {
|
||||
): ExtensionDefinition {
|
||||
const element = <LegacyExtension />;
|
||||
|
||||
const extName = getComponentData<string>(element, 'core.extensionName');
|
||||
|
||||
+528
-522
File diff suppressed because it is too large
Load Diff
@@ -36,6 +36,7 @@ describe('CatalogFilterBlueprint', () => {
|
||||
expect(extension).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$$type": "@backstage/ExtensionDefinition",
|
||||
"T": undefined,
|
||||
"attachTo": {
|
||||
"id": "page:catalog",
|
||||
"input": "filters",
|
||||
|
||||
@@ -19,48 +19,52 @@ const _default: BackstagePlugin<
|
||||
},
|
||||
{},
|
||||
{
|
||||
'api:devtools': ExtensionDefinition<
|
||||
{},
|
||||
{},
|
||||
ConfigurableExtensionDataRef<AnyApiFactory, 'core.api.factory', {}>,
|
||||
{},
|
||||
{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}
|
||||
>;
|
||||
'page:devtools': ExtensionDefinition<
|
||||
{
|
||||
'api:devtools': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
output: ConfigurableExtensionDataRef<
|
||||
AnyApiFactory,
|
||||
'core.api.factory',
|
||||
{}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'page:devtools': ExtensionDefinition<{
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {
|
||||
path: string | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
path?: string | undefined;
|
||||
},
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}
|
||||
>;
|
||||
'nav-item:devtools': ExtensionDefinition<
|
||||
{},
|
||||
{},
|
||||
ConfigurableExtensionDataRef<
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'nav-item:devtools': ExtensionDefinition<{
|
||||
kind: 'nav-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
output: ConfigurableExtensionDataRef<
|
||||
{
|
||||
title: string;
|
||||
icon: IconComponent;
|
||||
@@ -68,14 +72,9 @@ const _default: BackstagePlugin<
|
||||
},
|
||||
'core.nav-item.target',
|
||||
{}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
kind: 'nav-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}
|
||||
>;
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
}
|
||||
>;
|
||||
export default _default;
|
||||
|
||||
@@ -16,31 +16,28 @@ const _default: BackstagePlugin<
|
||||
{},
|
||||
{},
|
||||
{
|
||||
'page:home': ExtensionDefinition<
|
||||
{
|
||||
[x: string]: any;
|
||||
} & {
|
||||
'page:home': ExtensionDefinition<{
|
||||
config: {
|
||||
path: string | undefined;
|
||||
},
|
||||
{
|
||||
[x: string]: any;
|
||||
} & {
|
||||
};
|
||||
configInput: {
|
||||
path?: string | undefined;
|
||||
},
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>,
|
||||
{
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {
|
||||
props: ExtensionInput<
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
@@ -61,13 +58,11 @@ const _default: BackstagePlugin<
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
},
|
||||
{
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}
|
||||
>;
|
||||
};
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}>;
|
||||
}
|
||||
>;
|
||||
export default _default;
|
||||
|
||||
@@ -21,104 +21,125 @@ const _default: BackstagePlugin<
|
||||
},
|
||||
{},
|
||||
{
|
||||
'page:kubernetes': ExtensionDefinition<
|
||||
{
|
||||
'api:kubernetes': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
output: ConfigurableExtensionDataRef<
|
||||
AnyApiFactory,
|
||||
'core.api.factory',
|
||||
{}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'page:kubernetes': ExtensionDefinition<{
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {
|
||||
path: string | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
path?: string | undefined;
|
||||
},
|
||||
| ConfigurableExtensionDataRef<JSX_2.Element, 'core.reactElement', {}>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}
|
||||
>;
|
||||
'entity-content:kubernetes/kubernetes': ExtensionDefinition<
|
||||
{
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<JSX_2.Element, 'core.reactElement', {}>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'entity-content:kubernetes/kubernetes': ExtensionDefinition<{
|
||||
kind: 'entity-content';
|
||||
namespace: undefined;
|
||||
name: 'kubernetes';
|
||||
config: {
|
||||
path: string | undefined;
|
||||
title: string | undefined;
|
||||
filter: string | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
filter?: string | undefined;
|
||||
title?: string | undefined;
|
||||
path?: string | undefined;
|
||||
},
|
||||
| ConfigurableExtensionDataRef<JSX_2.Element, 'core.reactElement', {}>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'catalog.entity-content-title', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
kind: 'entity-content';
|
||||
namespace: undefined;
|
||||
name: 'kubernetes';
|
||||
}
|
||||
>;
|
||||
'api:kubernetes/proxy': ExtensionDefinition<
|
||||
{},
|
||||
{},
|
||||
ConfigurableExtensionDataRef<AnyApiFactory, 'core.api.factory', {}>,
|
||||
{},
|
||||
{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'proxy';
|
||||
}
|
||||
>;
|
||||
'api:kubernetes/auth-providers': ExtensionDefinition<
|
||||
{},
|
||||
{},
|
||||
ConfigurableExtensionDataRef<AnyApiFactory, 'core.api.factory', {}>,
|
||||
{},
|
||||
{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'auth-providers';
|
||||
}
|
||||
>;
|
||||
'api:kubernetes/cluster-link-formatter': ExtensionDefinition<
|
||||
{},
|
||||
{},
|
||||
ConfigurableExtensionDataRef<AnyApiFactory, 'core.api.factory', {}>,
|
||||
{},
|
||||
{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'cluster-link-formatter';
|
||||
}
|
||||
>;
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<JSX_2.Element, 'core.reactElement', {}>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-content-title',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'api:kubernetes/proxy': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'proxy';
|
||||
config: {};
|
||||
configInput: {};
|
||||
output: ConfigurableExtensionDataRef<
|
||||
AnyApiFactory,
|
||||
'core.api.factory',
|
||||
{}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'api:kubernetes/auth-providers': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'auth-providers';
|
||||
config: {};
|
||||
configInput: {};
|
||||
output: ConfigurableExtensionDataRef<
|
||||
AnyApiFactory,
|
||||
'core.api.factory',
|
||||
{}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'api:kubernetes/cluster-link-formatter': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'cluster-link-formatter';
|
||||
config: {};
|
||||
configInput: {};
|
||||
output: ConfigurableExtensionDataRef<
|
||||
AnyApiFactory,
|
||||
'core.api.factory',
|
||||
{}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
}
|
||||
>;
|
||||
export default _default;
|
||||
|
||||
+120
-124
@@ -17,138 +17,134 @@ const _default: BackstagePlugin<
|
||||
catalogIndex: ExternalRouteRef<undefined>;
|
||||
},
|
||||
{
|
||||
'entity-card:org/group-profile': ExtensionDefinition<
|
||||
{
|
||||
'entity-card:org/group-profile': ExtensionDefinition<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'group-profile';
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
filter?: string | undefined;
|
||||
},
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'group-profile';
|
||||
}
|
||||
>;
|
||||
'entity-card:org/members-list': ExtensionDefinition<
|
||||
{
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'entity-card:org/members-list': ExtensionDefinition<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'members-list';
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
filter?: string | undefined;
|
||||
},
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'members-list';
|
||||
}
|
||||
>;
|
||||
'entity-card:org/ownership': ExtensionDefinition<
|
||||
{
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'entity-card:org/ownership': ExtensionDefinition<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'ownership';
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
filter?: string | undefined;
|
||||
},
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'ownership';
|
||||
}
|
||||
>;
|
||||
'entity-card:org/user-profile': ExtensionDefinition<
|
||||
{
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'entity-card:org/user-profile': ExtensionDefinition<{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'user-profile';
|
||||
config: {
|
||||
filter: string | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
filter?: string | undefined;
|
||||
},
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
kind: 'entity-card';
|
||||
namespace: undefined;
|
||||
name: 'user-profile';
|
||||
}
|
||||
>;
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
}
|
||||
>;
|
||||
export default _default;
|
||||
|
||||
@@ -44,48 +44,52 @@ const _default: BackstagePlugin<
|
||||
}>;
|
||||
},
|
||||
{
|
||||
'api:scaffolder': ExtensionDefinition<
|
||||
{},
|
||||
{},
|
||||
ConfigurableExtensionDataRef<AnyApiFactory, 'core.api.factory', {}>,
|
||||
{},
|
||||
{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}
|
||||
>;
|
||||
'page:scaffolder': ExtensionDefinition<
|
||||
{
|
||||
'api:scaffolder': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
output: ConfigurableExtensionDataRef<
|
||||
AnyApiFactory,
|
||||
'core.api.factory',
|
||||
{}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'page:scaffolder': ExtensionDefinition<{
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {
|
||||
path: string | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
path?: string | undefined;
|
||||
},
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}
|
||||
>;
|
||||
'nav-item:scaffolder': ExtensionDefinition<
|
||||
{},
|
||||
{},
|
||||
ConfigurableExtensionDataRef<
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'nav-item:scaffolder': ExtensionDefinition<{
|
||||
kind: 'nav-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
output: ConfigurableExtensionDataRef<
|
||||
{
|
||||
title: string;
|
||||
icon: IconComponent;
|
||||
@@ -93,14 +97,9 @@ const _default: BackstagePlugin<
|
||||
},
|
||||
'core.nav-item.target',
|
||||
{}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
kind: 'nav-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}
|
||||
>;
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
}
|
||||
>;
|
||||
export default _default;
|
||||
|
||||
@@ -30,29 +30,27 @@ export type SearchResultItemExtensionPredicate = (
|
||||
) => boolean;
|
||||
|
||||
// @alpha
|
||||
export const SearchResultListItemBlueprint: ExtensionBlueprint<
|
||||
{
|
||||
kind: 'search-result-list-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
},
|
||||
SearchResultListItemBlueprintParams,
|
||||
ConfigurableExtensionDataRef<
|
||||
export const SearchResultListItemBlueprint: ExtensionBlueprint<{
|
||||
kind: 'search-result-list-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
params: SearchResultListItemBlueprintParams;
|
||||
output: ConfigurableExtensionDataRef<
|
||||
{
|
||||
predicate?: SearchResultItemExtensionPredicate | undefined;
|
||||
component: SearchResultItemExtensionComponent;
|
||||
},
|
||||
'search.search-result-list-item.item',
|
||||
{}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
>;
|
||||
inputs: {};
|
||||
config: {
|
||||
noTrack: boolean;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
noTrack?: boolean | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
dataRefs: {
|
||||
item: ConfigurableExtensionDataRef<
|
||||
{
|
||||
predicate?: SearchResultItemExtensionPredicate | undefined;
|
||||
@@ -61,8 +59,8 @@ export const SearchResultListItemBlueprint: ExtensionBlueprint<
|
||||
'search.search-result-list-item.item',
|
||||
{}
|
||||
>;
|
||||
}
|
||||
>;
|
||||
};
|
||||
}>;
|
||||
|
||||
// @alpha (undocumented)
|
||||
export interface SearchResultListItemBlueprintParams {
|
||||
|
||||
@@ -40,6 +40,7 @@ describe('SearchResultListItemBlueprint', () => {
|
||||
expect(extension).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$$type": "@backstage/ExtensionDefinition",
|
||||
"T": undefined,
|
||||
"attachTo": {
|
||||
"id": "page:search",
|
||||
"input": "items",
|
||||
|
||||
@@ -22,21 +22,26 @@ const _default: BackstagePlugin<
|
||||
},
|
||||
{},
|
||||
{
|
||||
'api:search': ExtensionDefinition<
|
||||
{},
|
||||
{},
|
||||
ConfigurableExtensionDataRef<AnyApiFactory, 'core.api.factory', {}>,
|
||||
{},
|
||||
{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}
|
||||
>;
|
||||
'nav-item:search': ExtensionDefinition<
|
||||
{},
|
||||
{},
|
||||
ConfigurableExtensionDataRef<
|
||||
'api:search': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
output: ConfigurableExtensionDataRef<
|
||||
AnyApiFactory,
|
||||
'core.api.factory',
|
||||
{}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'nav-item:search': ExtensionDefinition<{
|
||||
kind: 'nav-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
output: ConfigurableExtensionDataRef<
|
||||
{
|
||||
title: string;
|
||||
icon: IconComponent;
|
||||
@@ -44,39 +49,35 @@ const _default: BackstagePlugin<
|
||||
},
|
||||
'core.nav-item.target',
|
||||
{}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
kind: 'nav-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}
|
||||
>;
|
||||
'page:search': ExtensionDefinition<
|
||||
{
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'page:search': ExtensionDefinition<{
|
||||
config: {
|
||||
noTrack: boolean;
|
||||
} & {
|
||||
path: string | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
noTrack?: boolean | undefined;
|
||||
} & {
|
||||
path?: string | undefined;
|
||||
},
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>,
|
||||
{
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {
|
||||
items: ExtensionInput<
|
||||
ConfigurableExtensionDataRef<
|
||||
{
|
||||
@@ -91,35 +92,34 @@ const _default: BackstagePlugin<
|
||||
optional: false;
|
||||
}
|
||||
>;
|
||||
},
|
||||
{
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}
|
||||
>;
|
||||
};
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}>;
|
||||
}
|
||||
>;
|
||||
export default _default;
|
||||
|
||||
// @alpha (undocumented)
|
||||
export const searchApi: ExtensionDefinition<
|
||||
{},
|
||||
{},
|
||||
ConfigurableExtensionDataRef<AnyApiFactory, 'core.api.factory', {}>,
|
||||
{},
|
||||
{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}
|
||||
>;
|
||||
export const searchApi: ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
output: ConfigurableExtensionDataRef<AnyApiFactory, 'core.api.factory', {}>;
|
||||
inputs: {};
|
||||
}>;
|
||||
|
||||
// @alpha (undocumented)
|
||||
export const searchNavItem: ExtensionDefinition<
|
||||
{},
|
||||
{},
|
||||
ConfigurableExtensionDataRef<
|
||||
export const searchNavItem: ExtensionDefinition<{
|
||||
kind: 'nav-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
output: ConfigurableExtensionDataRef<
|
||||
{
|
||||
title: string;
|
||||
icon: IconComponent;
|
||||
@@ -127,37 +127,33 @@ export const searchNavItem: ExtensionDefinition<
|
||||
},
|
||||
'core.nav-item.target',
|
||||
{}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
kind: 'nav-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}
|
||||
>;
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
|
||||
// @alpha (undocumented)
|
||||
export const searchPage: ExtensionDefinition<
|
||||
{
|
||||
export const searchPage: ExtensionDefinition<{
|
||||
config: {
|
||||
noTrack: boolean;
|
||||
} & {
|
||||
path: string | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
noTrack?: boolean | undefined;
|
||||
} & {
|
||||
path?: string | undefined;
|
||||
},
|
||||
| ConfigurableExtensionDataRef<React_2.JSX.Element, 'core.reactElement', {}>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>,
|
||||
{
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<React_2.JSX.Element, 'core.reactElement', {}>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {
|
||||
items: ExtensionInput<
|
||||
ConfigurableExtensionDataRef<
|
||||
{
|
||||
@@ -172,13 +168,11 @@ export const searchPage: ExtensionDefinition<
|
||||
optional: false;
|
||||
}
|
||||
>;
|
||||
},
|
||||
{
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}
|
||||
>;
|
||||
};
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}>;
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
```
|
||||
|
||||
@@ -30,10 +30,52 @@ const _default: BackstagePlugin<
|
||||
},
|
||||
{},
|
||||
{
|
||||
'nav-item:techdocs': ExtensionDefinition<
|
||||
{},
|
||||
{},
|
||||
ConfigurableExtensionDataRef<
|
||||
'api:techdocs': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
output: ConfigurableExtensionDataRef<
|
||||
AnyApiFactory,
|
||||
'core.api.factory',
|
||||
{}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'page:techdocs': ExtensionDefinition<{
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {
|
||||
path: string | undefined;
|
||||
};
|
||||
configInput: {
|
||||
path?: string | undefined;
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'nav-item:techdocs': ExtensionDefinition<{
|
||||
kind: 'nav-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
output: ConfigurableExtensionDataRef<
|
||||
{
|
||||
title: string;
|
||||
icon: IconComponent;
|
||||
@@ -41,51 +83,48 @@ const _default: BackstagePlugin<
|
||||
},
|
||||
'core.nav-item.target',
|
||||
{}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
kind: 'nav-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}
|
||||
>;
|
||||
'api:techdocs/storage': ExtensionDefinition<
|
||||
{},
|
||||
{},
|
||||
ConfigurableExtensionDataRef<AnyApiFactory, 'core.api.factory', {}>,
|
||||
{},
|
||||
{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'storage';
|
||||
}
|
||||
>;
|
||||
'search-result-list-item:techdocs': ExtensionDefinition<
|
||||
{
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'api:techdocs/storage': ExtensionDefinition<{
|
||||
kind: 'api';
|
||||
namespace: undefined;
|
||||
name: 'storage';
|
||||
config: {};
|
||||
configInput: {};
|
||||
output: ConfigurableExtensionDataRef<
|
||||
AnyApiFactory,
|
||||
'core.api.factory',
|
||||
{}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'search-result-list-item:techdocs': ExtensionDefinition<{
|
||||
config: {
|
||||
title: string | undefined;
|
||||
lineClamp: number;
|
||||
asLink: boolean;
|
||||
asListItem: boolean;
|
||||
} & {
|
||||
noTrack: boolean;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
title?: string | undefined;
|
||||
lineClamp?: number | undefined;
|
||||
asListItem?: boolean | undefined;
|
||||
asLink?: boolean | undefined;
|
||||
} & {
|
||||
noTrack?: boolean | undefined;
|
||||
},
|
||||
ConfigurableExtensionDataRef<
|
||||
};
|
||||
output: ConfigurableExtensionDataRef<
|
||||
{
|
||||
predicate?: SearchResultItemExtensionPredicate | undefined;
|
||||
component: SearchResultItemExtensionComponent;
|
||||
},
|
||||
'search.search-result-list-item.item',
|
||||
{}
|
||||
>,
|
||||
{
|
||||
>;
|
||||
inputs: {
|
||||
[x: string]: ExtensionInput<
|
||||
AnyExtensionDataRef,
|
||||
{
|
||||
@@ -93,117 +132,117 @@ const _default: BackstagePlugin<
|
||||
singleton: boolean;
|
||||
}
|
||||
>;
|
||||
},
|
||||
{
|
||||
kind: 'search-result-list-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}
|
||||
>;
|
||||
'page:techdocs/reader': ExtensionDefinition<
|
||||
{
|
||||
};
|
||||
kind: 'search-result-list-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}>;
|
||||
'page:techdocs/reader': ExtensionDefinition<{
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: 'reader';
|
||||
config: {
|
||||
path: string | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
path?: string | undefined;
|
||||
},
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: 'reader';
|
||||
}
|
||||
>;
|
||||
'entity-content:techdocs': ExtensionDefinition<
|
||||
{
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'entity-content:techdocs': ExtensionDefinition<{
|
||||
kind: 'entity-content';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {
|
||||
path: string | undefined;
|
||||
title: string | undefined;
|
||||
filter: string | undefined;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
filter?: string | undefined;
|
||||
title?: string | undefined;
|
||||
path?: string | undefined;
|
||||
},
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'catalog.entity-content-title', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
kind: 'entity-content';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}
|
||||
>;
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-content-title',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
(entity: Entity) => boolean,
|
||||
'catalog.entity-filter-function',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<
|
||||
string,
|
||||
'catalog.entity-filter-expression',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
}
|
||||
>;
|
||||
export default _default;
|
||||
|
||||
// @alpha (undocumented)
|
||||
export const techDocsSearchResultListItemExtension: ExtensionDefinition<
|
||||
{
|
||||
export const techDocsSearchResultListItemExtension: ExtensionDefinition<{
|
||||
config: {
|
||||
title: string | undefined;
|
||||
lineClamp: number;
|
||||
asLink: boolean;
|
||||
asListItem: boolean;
|
||||
} & {
|
||||
noTrack: boolean;
|
||||
},
|
||||
{
|
||||
};
|
||||
configInput: {
|
||||
title?: string | undefined;
|
||||
lineClamp?: number | undefined;
|
||||
asListItem?: boolean | undefined;
|
||||
asLink?: boolean | undefined;
|
||||
} & {
|
||||
noTrack?: boolean | undefined;
|
||||
},
|
||||
ConfigurableExtensionDataRef<
|
||||
};
|
||||
output: ConfigurableExtensionDataRef<
|
||||
{
|
||||
predicate?: SearchResultItemExtensionPredicate | undefined;
|
||||
component: SearchResultItemExtensionComponent;
|
||||
},
|
||||
'search.search-result-list-item.item',
|
||||
{}
|
||||
>,
|
||||
{
|
||||
>;
|
||||
inputs: {
|
||||
[x: string]: ExtensionInput<
|
||||
AnyExtensionDataRef,
|
||||
{
|
||||
@@ -211,13 +250,11 @@ export const techDocsSearchResultListItemExtension: ExtensionDefinition<
|
||||
singleton: boolean;
|
||||
}
|
||||
>;
|
||||
},
|
||||
{
|
||||
kind: 'search-result-list-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}
|
||||
>;
|
||||
};
|
||||
kind: 'search-result-list-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}>;
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
```
|
||||
|
||||
@@ -20,10 +20,13 @@ const _default: BackstagePlugin<
|
||||
},
|
||||
{},
|
||||
{
|
||||
'nav-item:user-settings': ExtensionDefinition<
|
||||
{},
|
||||
{},
|
||||
ConfigurableExtensionDataRef<
|
||||
'nav-item:user-settings': ExtensionDefinition<{
|
||||
kind: 'nav-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
output: ConfigurableExtensionDataRef<
|
||||
{
|
||||
title: string;
|
||||
icon: IconComponent;
|
||||
@@ -31,39 +34,31 @@ const _default: BackstagePlugin<
|
||||
},
|
||||
'core.nav-item.target',
|
||||
{}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
kind: 'nav-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}
|
||||
>;
|
||||
'page:user-settings': ExtensionDefinition<
|
||||
{
|
||||
[x: string]: any;
|
||||
} & {
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
'page:user-settings': ExtensionDefinition<{
|
||||
config: {
|
||||
path: string | undefined;
|
||||
},
|
||||
{
|
||||
[x: string]: any;
|
||||
} & {
|
||||
};
|
||||
configInput: {
|
||||
path?: string | undefined;
|
||||
},
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>,
|
||||
{
|
||||
};
|
||||
output:
|
||||
| ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
'core.reactElement',
|
||||
{}
|
||||
>
|
||||
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
|
||||
| ConfigurableExtensionDataRef<
|
||||
RouteRef<AnyRouteRefParams>,
|
||||
'core.routing.ref',
|
||||
{
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {
|
||||
providerSettings: ExtensionInput<
|
||||
ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
@@ -75,22 +70,23 @@ const _default: BackstagePlugin<
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
},
|
||||
{
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}
|
||||
>;
|
||||
};
|
||||
kind: 'page';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}>;
|
||||
}
|
||||
>;
|
||||
export default _default;
|
||||
|
||||
// @alpha (undocumented)
|
||||
export const settingsNavItem: ExtensionDefinition<
|
||||
{},
|
||||
{},
|
||||
ConfigurableExtensionDataRef<
|
||||
export const settingsNavItem: ExtensionDefinition<{
|
||||
kind: 'nav-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
config: {};
|
||||
configInput: {};
|
||||
output: ConfigurableExtensionDataRef<
|
||||
{
|
||||
title: string;
|
||||
icon: IconComponent;
|
||||
@@ -98,14 +94,9 @@ export const settingsNavItem: ExtensionDefinition<
|
||||
},
|
||||
'core.nav-item.target',
|
||||
{}
|
||||
>,
|
||||
{},
|
||||
{
|
||||
kind: 'nav-item';
|
||||
namespace: undefined;
|
||||
name: undefined;
|
||||
}
|
||||
>;
|
||||
>;
|
||||
inputs: {};
|
||||
}>;
|
||||
|
||||
// @alpha (undocumented)
|
||||
export const userSettingsTranslationRef: TranslationRef<
|
||||
|
||||
Reference in New Issue
Block a user