diff --git a/packages/app-next-example-plugin/api-report.md b/packages/app-next-example-plugin/api-report.md index 4698edec6b..fe2afb81a7 100644 --- a/packages/app-next-example-plugin/api-report.md +++ b/packages/app-next-example-plugin/api-report.md @@ -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 - | ConfigurableExtensionDataRef< - RouteRef, - 'core.routing.ref', - { - optional: true; - } - >, - {}, - { - kind: 'page'; - namespace: undefined; - name: undefined; - } - >; + }; + output: + | ConfigurableExtensionDataRef< + React_2.JSX.Element, + 'core.reactElement', + {} + > + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + RouteRef, + 'core.routing.ref', + { + optional: true; + } + >; + inputs: {}; + }>; } >; export default examplePlugin; diff --git a/packages/core-compat-api/api-report.md b/packages/core-compat-api/api-report.md index 75b91cc055..9e72d6178c 100644 --- a/packages/core-compat-api/api-report.md +++ b/packages/core-compat-api/api-report.md @@ -37,13 +37,13 @@ export function convertLegacyPageExtension( name?: string; defaultPath?: string; }, -): ExtensionDefinition; +): ExtensionDefinition; // @public (undocumented) export function convertLegacyPlugin( legacyPlugin: BackstagePlugin, options: { - extensions: ExtensionDefinition[]; + extensions: ExtensionDefinition[]; }, ): BackstagePlugin_2; diff --git a/packages/core-compat-api/src/collectLegacyRoutes.tsx b/packages/core-compat-api/src/collectLegacyRoutes.tsx index c5cb13b6e1..4c0e7efceb 100644 --- a/packages/core-compat-api/src/collectLegacyRoutes.tsx +++ b/packages/core-compat-api/src/collectLegacyRoutes.tsx @@ -106,7 +106,7 @@ function visitRouteChildren(options: { parentExtensionId: string; context: { pluginId: string; - extensions: ExtensionDefinition[]; + extensions: ExtensionDefinition[]; getUniqueName: () => string; discoverPlugin: (plugin: LegacyBackstagePlugin) => void; }; @@ -159,7 +159,7 @@ export function collectLegacyRoutes( ): BackstagePlugin[] { const pluginExtensions = new Map< LegacyBackstagePlugin, - ExtensionDefinition[] + ExtensionDefinition[] >(); const getUniqueName = (() => { diff --git a/packages/core-compat-api/src/convertLegacyPageExtension.test.tsx b/packages/core-compat-api/src/convertLegacyPageExtension.test.tsx index 482474d580..c1630b31b5 100644 --- a/packages/core-compat-api/src/convertLegacyPageExtension.test.tsx +++ b/packages/core-compat-api/src/convertLegacyPageExtension.test.tsx @@ -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), diff --git a/packages/core-compat-api/src/convertLegacyPageExtension.tsx b/packages/core-compat-api/src/convertLegacyPageExtension.tsx index 7ef4e0faff..3931a730c8 100644 --- a/packages/core-compat-api/src/convertLegacyPageExtension.tsx +++ b/packages/core-compat-api/src/convertLegacyPageExtension.tsx @@ -35,7 +35,7 @@ export function convertLegacyPageExtension( name?: string; defaultPath?: string; }, -): ExtensionDefinition { +): ExtensionDefinition { const element = ; const extName = getComponentData(element, 'core.extensionName'); diff --git a/packages/core-compat-api/src/convertLegacyPlugin.ts b/packages/core-compat-api/src/convertLegacyPlugin.ts index 5856108f29..bf5759f214 100644 --- a/packages/core-compat-api/src/convertLegacyPlugin.ts +++ b/packages/core-compat-api/src/convertLegacyPlugin.ts @@ -26,7 +26,7 @@ import { convertLegacyRouteRefs } from './convertLegacyRouteRef'; /** @public */ export function convertLegacyPlugin( legacyPlugin: LegacyBackstagePlugin, - options: { extensions: ExtensionDefinition[] }, + options: { extensions: ExtensionDefinition[] }, ): NewBackstagePlugin { const apiExtensions = Array.from(legacyPlugin.getApis()).map(factory => ApiBlueprint.make({ namespace: factory.api.id, params: { factory } }), diff --git a/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.test.ts b/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.test.ts index 8dc41ef155..4d450f0ae4 100644 --- a/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.test.ts +++ b/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.test.ts @@ -76,7 +76,7 @@ function createTestExtension(options: { }); } -function routeInfoFromExtensions(extensions: ExtensionDefinition[]) { +function routeInfoFromExtensions(extensions: ExtensionDefinition[]) { const plugin = createFrontendPlugin({ id: 'test', extensions, diff --git a/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.test.ts b/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.test.ts index a732b327b6..0be99c4969 100644 --- a/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.test.ts +++ b/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.test.ts @@ -44,12 +44,13 @@ function makeExtDef( ) { return { $$type: '@backstage/ExtensionDefinition', + T: null as any, version: 'v1', name, attachTo: { id: attachId, input: 'default' }, disabled: status === 'disabled', - override: () => ({} as ExtensionDefinition), - } as ExtensionDefinition; + override: () => ({} as ExtensionDefinition), + } as ExtensionDefinition; } describe('resolveAppNodeSpecs', () => { diff --git a/packages/frontend-app-api/src/wiring/createApp.tsx b/packages/frontend-app-api/src/wiring/createApp.tsx index b31ce85f1a..242709cdb2 100644 --- a/packages/frontend-app-api/src/wiring/createApp.tsx +++ b/packages/frontend-app-api/src/wiring/createApp.tsx @@ -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[], diff --git a/packages/frontend-plugin-api/api-report.md b/packages/frontend-plugin-api/api-report.md index 5b0d7d4432..266315c396 100644 --- a/packages/frontend-plugin-api/api-report.md +++ b/packages/frontend-plugin-api/api-report.md @@ -172,27 +172,25 @@ export type AnyRoutes = { }; // @public -export const ApiBlueprint: ExtensionBlueprint< - { - kind: 'api'; - namespace: undefined; - name: undefined; - }, - { +export const ApiBlueprint: ExtensionBlueprint<{ + kind: 'api'; + namespace: undefined; + name: undefined; + params: { factory: AnyApiFactory; - }, - ConfigurableExtensionDataRef, - {}, - {}, - {}, - { + }; + output: ConfigurableExtensionDataRef; + inputs: {}; + config: {}; + configInput: {}; + dataRefs: { factory: ConfigurableExtensionDataRef< AnyApiFactory, 'core.api.factory', {} >; - } ->; + }; +}>; export { ApiFactory }; @@ -246,43 +244,39 @@ export interface AppNodeSpec { } // @public -export const AppRootElementBlueprint: ExtensionBlueprint< - { - kind: 'app-root-element'; - namespace: undefined; - name: undefined; - }, - { +export const AppRootElementBlueprint: ExtensionBlueprint<{ + kind: 'app-root-element'; + namespace: undefined; + name: undefined; + params: { element: JSX.Element | (() => JSX.Element); - }, - ConfigurableExtensionDataRef, - {}, - {}, - {}, - never ->; + }; + output: ConfigurableExtensionDataRef; + inputs: {}; + config: {}; + configInput: {}; + dataRefs: never; +}>; // @public -export const AppRootWrapperBlueprint: ExtensionBlueprint< - { - kind: 'app-root-wrapper'; - namespace: undefined; - name: undefined; - }, - { +export const AppRootWrapperBlueprint: ExtensionBlueprint<{ + kind: 'app-root-wrapper'; + namespace: undefined; + name: undefined; + params: { Component: ComponentType>; - }, - ConfigurableExtensionDataRef< + }; + output: ConfigurableExtensionDataRef< React_2.ComponentType<{ children?: React_2.ReactNode; }>, 'app.root.wrapper', {} - >, - {}, - {}, - {}, - { + >; + inputs: {}; + config: {}; + configInput: {}; + dataRefs: { component: ConfigurableExtensionDataRef< React_2.ComponentType<{ children?: React_2.ReactNode; @@ -290,8 +284,8 @@ export const AppRootWrapperBlueprint: ExtensionBlueprint< 'app.root.wrapper', {} >; - } ->; + }; +}>; export { AppTheme }; @@ -331,7 +325,7 @@ export interface BackstagePlugin< TRoutes extends AnyRoutes = AnyRoutes, TExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes, TExtensionMap extends { - [id in string]: ExtensionDefinition; + [id in string]: ExtensionDefinition; } = {}, > { // (undocumented) @@ -346,7 +340,7 @@ export interface BackstagePlugin< readonly routes: TRoutes; // (undocumented) withOverrides(options: { - extensions: Array>; + extensions: Array; }): BackstagePlugin; } @@ -454,22 +448,18 @@ export function createComponentExtension(options: { | { sync: () => ComponentType; }; -}): ExtensionDefinition< - { - [x: string]: any; - }, - { - [x: string]: any; - }, - ConfigurableExtensionDataRef< +}): ExtensionDefinition<{ + config: {}; + configInput: {}; + output: ConfigurableExtensionDataRef< { ref: ComponentRef; impl: ComponentType; }, 'core.component.component', {} - >, - { + >; + inputs: { [x: string]: ExtensionInput< AnyExtensionDataRef, { @@ -477,13 +467,11 @@ export function createComponentExtension(options: { singleton: boolean; } >; - }, - { - kind: 'component'; - namespace: string; - name: string; - } ->; + }; + kind: 'component'; + namespace: string; + name: string; +}>; // @public (undocumented) export namespace createComponentExtension { @@ -532,27 +520,29 @@ export function createExtension< TConfigSchema, UFactoryOutput >, -): ExtensionDefinition< - { - [key in keyof TConfigSchema]: z.infer>; - }, - z.input< - z.ZodObject<{ - [key in keyof TConfigSchema]: ReturnType; - }> - >, - UOutput, - TInputs, - { - kind: string | undefined extends TKind ? undefined : TKind; - namespace: string | undefined extends TNamespace ? undefined : TNamespace; - name: string | undefined extends TName ? undefined : TName; - } ->; +): ExtensionDefinition<{ + config: string extends keyof TConfigSchema + ? {} + : { + [key in keyof TConfigSchema]: z.infer>; + }; + configInput: string extends keyof TConfigSchema + ? {} + : z.input< + z.ZodObject<{ + [key in keyof TConfigSchema]: ReturnType; + }> + >; + 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; +}>; // @public export function createExtensionBlueprint< - TParams, + TParams extends object, UOutput extends AnyExtensionDataRef, TInputs extends { [inputName in string]: ExtensionInput< @@ -585,29 +575,27 @@ 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>; - }, - string extends keyof TConfigSchema + }; + configInput: string extends keyof TConfigSchema ? {} : z.input< z.ZodObject<{ [key in keyof TConfigSchema]: ReturnType; }> - >, - TDataRefs ->; + >; + dataRefs: TDataRefs; +}>; // @public (undocumented) export type CreateExtensionBlueprintOptions< @@ -777,7 +765,7 @@ export function createFrontendPlugin< TId extends string, TRoutes extends AnyRoutes = {}, TExternalRoutes extends AnyExternalRoutes = {}, - TExtensions extends readonly ExtensionDefinition[] = [], + TExtensions extends readonly ExtensionDefinition[] = [], >( options: PluginOptions, ): BackstagePlugin< @@ -860,34 +848,10 @@ export interface Extension { // @public (undocumented) 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, > { // (undocumented) - dataRefs: TDataRefs; + dataRefs: T['dataRefs']; // (undocumented) make< TNewNamespace extends string | undefined, @@ -900,20 +864,18 @@ export interface ExtensionBlueprint< 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']; + }>; makeWithOverrides< TNewNamespace extends string | undefined, TNewName extends string | undefined, @@ -940,65 +902,95 @@ export interface ExtensionBlueprint< }; 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; 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; + config?: T['config']; + inputs?: ResolveInputValueOverrides>; }, - ) => ExtensionDataContainer, + ) => ExtensionDataContainer, context: { node: AppNode; apis: ApiHolder; - config: TConfig & { + config: T['config'] & { [key in keyof TExtensionConfigSchema]: z.infer< ReturnType >; }; - inputs: Expand>; + inputs: Expand>; }, ): Iterable & VerifyExtensionFactoryOutput< - AnyExtensionDataRef extends UNewOutput ? UOutput : UNewOutput, + AnyExtensionDataRef extends UNewOutput ? T['output'] : UNewOutput, UFactoryOutput >; - }): ExtensionDefinition< - { - [key in keyof TExtensionConfigSchema]: z.infer< - ReturnType - >; - } & 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 + >; + }) & + T['config']; + configInput: (string extends keyof TExtensionConfigSchema + ? {} + : z.input< + z.ZodObject<{ + [key in keyof TExtensionConfigSchema]: ReturnType< + TExtensionConfigSchema[key] + >; + }> + >) & + T['configInput']; + output: AnyExtensionDataRef extends UNewOutput ? T['output'] : UNewOutput; + inputs: T['inputs'] & TExtraInputs; + kind: T['kind']; + namespace: string | undefined extends TNewNamespace + ? T['namespace'] + : TNewNamespace; + name: string | undefined extends TNewName ? T['name'] : TNewName; + }>; } +// @public (undocumented) +export type ExtensionBlueprintParameters = { + kind: string; + namespace?: string; + name?: string; + params: object; + configInput?: { + [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 (undocumented) export function ExtensionBoundary( props: ExtensionBoundaryProps, @@ -1072,47 +1064,11 @@ export type ExtensionDataValue = { }; // @public (undocumented) -export interface ExtensionDefinition< - 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; - }, -> { - // (undocumented) +export type ExtensionDefinition< + T extends ExtensionDefinitionParameters = ExtensionDefinitionParameters, +> = { $$type: '@backstage/ExtensionDefinition'; - // (undocumented) - readonly attachTo: { - id: string; - input: string; - }; - // (undocumented) - readonly configSchema?: PortableSchema; - // (undocumented) - readonly disabled: boolean; - // (undocumented) - readonly kind?: TIdParts['kind']; - // (undocumented) - readonly name?: TIdParts['name']; - // (undocumented) - readonly namespace?: TIdParts['namespace']; - // (undocumented) + readonly T: T; override< TExtensionConfigSchema extends { [key in string]: (zImpl: typeof z) => z.ZodType; @@ -1136,55 +1092,82 @@ export interface ExtensionDefinition< }; 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; 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; - }) => ExtensionDataContainer, + config?: T['config']; + inputs?: ResolveInputValueOverrides>; + }) => ExtensionDataContainer>, context: { node: AppNode; apis: ApiHolder; - config: TConfig & { + config: T['config'] & { [key in keyof TExtensionConfigSchema]: z.infer< ReturnType >; }; - inputs: Expand>; + inputs: Expand>; }, ): Iterable; } & VerifyExtensionFactoryOutput< - AnyExtensionDataRef extends UNewOutput ? UOutput : UNewOutput, + AnyExtensionDataRef extends UNewOutput + ? NonNullable + : 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 >; - } & 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] + >; + }> + >; + }>; +}; + +// @public (undocumented) +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; + } + >; + }; +}; // @public (undocumented) export interface ExtensionInput< @@ -1222,7 +1205,7 @@ export interface ExtensionOverrides { // @public (undocumented) export interface ExtensionOverridesOptions { // (undocumented) - extensions: ExtensionDefinition[]; + extensions: ExtensionDefinition[]; // (undocumented) featureFlags?: FeatureFlagConfig[]; } @@ -1266,34 +1249,32 @@ export { gitlabAuthApiRef }; export { googleAuthApiRef }; // @public (undocumented) -export const IconBundleBlueprint: ExtensionBlueprint< - { - kind: 'icon-bundle'; - namespace: 'app'; - name: undefined; - }, - { +export const IconBundleBlueprint: ExtensionBlueprint<{ + kind: 'icon-bundle'; + namespace: 'app'; + name: undefined; + params: { icons: { [x: string]: IconComponent; }; - }, - ConfigurableExtensionDataRef< + }; + output: ConfigurableExtensionDataRef< { [x: string]: IconComponent; }, 'core.icons', {} - >, - {}, - { + >; + inputs: {}; + config: { icons: string; test: string; - }, - { + }; + configInput: { test: string; icons?: string | undefined; - }, - { + }; + dataRefs: { icons: ConfigurableExtensionDataRef< { [x: string]: IconComponent; @@ -1301,8 +1282,8 @@ export const IconBundleBlueprint: ExtensionBlueprint< 'core.icons', {} >; - } ->; + }; +}>; // @public export type IconComponent = ComponentType< @@ -1332,18 +1313,16 @@ export { identityApiRef }; export { microsoftAuthApiRef }; // @public -export const NavItemBlueprint: ExtensionBlueprint< - { - kind: 'nav-item'; - namespace: undefined; - name: undefined; - }, - { +export const NavItemBlueprint: ExtensionBlueprint<{ + kind: 'nav-item'; + namespace: undefined; + name: undefined; + params: { title: string; icon: IconComponent_2; routeRef: RouteRef; - }, - ConfigurableExtensionDataRef< + }; + output: ConfigurableExtensionDataRef< { title: string; icon: IconComponent_2; @@ -1351,11 +1330,11 @@ export const NavItemBlueprint: ExtensionBlueprint< }, 'core.nav-item.target', {} - >, - {}, - {}, - {}, - { + >; + inputs: {}; + config: {}; + configInput: {}; + dataRefs: { target: ConfigurableExtensionDataRef< { title: string; @@ -1365,32 +1344,30 @@ export const NavItemBlueprint: ExtensionBlueprint< 'core.nav-item.target', {} >; - } ->; + }; +}>; // @public -export const NavLogoBlueprint: ExtensionBlueprint< - { - kind: 'nav-logo'; - namespace: undefined; - name: undefined; - }, - { +export const NavLogoBlueprint: ExtensionBlueprint<{ + kind: 'nav-logo'; + namespace: undefined; + name: undefined; + params: { logoIcon: JSX.Element; logoFull: JSX.Element; - }, - ConfigurableExtensionDataRef< + }; + output: ConfigurableExtensionDataRef< { logoIcon?: JSX.Element | undefined; logoFull?: JSX.Element | undefined; }, 'core.nav-logo.logo-elements', {} - >, - {}, - {}, - {}, - { + >; + inputs: {}; + config: {}; + configInput: {}; + dataRefs: { logoElements: ConfigurableExtensionDataRef< { logoIcon?: JSX.Element | undefined; @@ -1399,8 +1376,8 @@ export const NavLogoBlueprint: ExtensionBlueprint< 'core.nav-logo.logo-elements', {} >; - } ->; + }; +}>; export { OAuthApi }; @@ -1421,35 +1398,34 @@ export { oneloginAuthApiRef }; export { OpenIdConnectApi }; // @public -export const PageBlueprint: ExtensionBlueprint< - { - kind: 'page'; - namespace: undefined; - name: undefined; - }, - { +export const PageBlueprint: ExtensionBlueprint<{ + kind: 'page'; + namespace: undefined; + name: undefined; + params: { defaultPath: string; loader: () => Promise; routeRef?: RouteRef | undefined; - }, - | ConfigurableExtensionDataRef - | ConfigurableExtensionDataRef - | ConfigurableExtensionDataRef< - RouteRef, - 'core.routing.ref', - { - optional: true; - } - >, - {}, - { + }; + output: + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + RouteRef, + 'core.routing.ref', + { + optional: true; + } + >; + inputs: {}; + config: { path: string | undefined; - }, - { + }; + configInput: { path?: string | undefined; - }, - never ->; + }; + dataRefs: never; +}>; export { PendingOAuthRequest }; @@ -1458,7 +1434,7 @@ export interface PluginOptions< TId extends string, TRoutes extends AnyRoutes, TExternalRoutes extends AnyExternalRoutes, - TExtensions extends readonly ExtensionDefinition[], + TExtensions extends readonly ExtensionDefinition[], > { // (undocumented) extensions?: TExtensions; @@ -1579,26 +1555,24 @@ export type RouteFunc = ( ) => string; // @public (undocumented) -export const RouterBlueprint: ExtensionBlueprint< - { - kind: 'app-router-component'; - namespace: undefined; - name: undefined; - }, - { +export const RouterBlueprint: ExtensionBlueprint<{ + kind: 'app-router-component'; + namespace: undefined; + name: undefined; + params: { Component: ComponentType>; - }, - ConfigurableExtensionDataRef< + }; + output: ConfigurableExtensionDataRef< ComponentType<{ children?: ReactNode; }>, 'app.router.wrapper', {} - >, - {}, - {}, - {}, - { + >; + inputs: {}; + config: {}; + configInput: {}; + dataRefs: { component: ConfigurableExtensionDataRef< ComponentType<{ children?: ReactNode; @@ -1606,8 +1580,8 @@ export const RouterBlueprint: ExtensionBlueprint< 'app.router.wrapper', {} >; - } ->; + }; +}>; // @public export interface RouteRef< @@ -1644,31 +1618,29 @@ export { SessionApi }; export { SessionState }; // @public -export const SignInPageBlueprint: ExtensionBlueprint< - { - kind: 'sign-in-page'; - namespace: undefined; - name: undefined; - }, - { +export const SignInPageBlueprint: ExtensionBlueprint<{ + kind: 'sign-in-page'; + namespace: undefined; + name: undefined; + params: { loader: () => Promise>; - }, - ConfigurableExtensionDataRef< + }; + output: ConfigurableExtensionDataRef< React_2.ComponentType, 'core.sign-in-page.component', {} - >, - {}, - {}, - {}, - { + >; + inputs: {}; + config: {}; + configInput: {}; + dataRefs: { component: ConfigurableExtensionDataRef< React_2.ComponentType, 'core.sign-in-page.component', {} >; - } ->; + }; +}>; export { StorageApi }; @@ -1689,35 +1661,31 @@ export interface SubRouteRef< } // @public -export const ThemeBlueprint: ExtensionBlueprint< - { - kind: 'theme'; - namespace: 'app'; - name: undefined; - }, - { +export const ThemeBlueprint: ExtensionBlueprint<{ + kind: 'theme'; + namespace: 'app'; + name: undefined; + params: { theme: AppTheme; - }, - ConfigurableExtensionDataRef, - {}, - {}, - {}, - { + }; + output: ConfigurableExtensionDataRef; + inputs: {}; + config: {}; + configInput: {}; + dataRefs: { theme: ConfigurableExtensionDataRef; - } ->; + }; +}>; // @public -export const TranslationBlueprint: ExtensionBlueprint< - { - kind: 'translation'; - namespace: undefined; - name: undefined; - }, - { +export const TranslationBlueprint: ExtensionBlueprint<{ + kind: 'translation'; + namespace: undefined; + name: undefined; + params: { resource: TranslationResource | TranslationMessages; - }, - ConfigurableExtensionDataRef< + }; + output: ConfigurableExtensionDataRef< | TranslationResource | TranslationMessages< string, @@ -1728,11 +1696,11 @@ export const TranslationBlueprint: ExtensionBlueprint< >, 'core.translation.translation', {} - >, - {}, - {}, - {}, - { + >; + inputs: {}; + config: {}; + configInput: {}; + dataRefs: { translation: ConfigurableExtensionDataRef< | TranslationResource | TranslationMessages< @@ -1745,8 +1713,8 @@ export const TranslationBlueprint: ExtensionBlueprint< 'core.translation.translation', {} >; - } ->; + }; +}>; export { TranslationMessages }; diff --git a/packages/frontend-plugin-api/src/wiring/createExtension.test.ts b/packages/frontend-plugin-api/src/wiring/createExtension.test.ts index 5853f28004..68478a756e 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtension.test.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtension.test.ts @@ -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().with({ id: 'string' }); const numberDataRef = createExtensionDataRef().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({ diff --git a/packages/frontend-plugin-api/src/wiring/createExtension.ts b/packages/frontend-plugin-api/src/wiring/createExtension.ts index 9d1568dc2f..d8b53c4aaa 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtension.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtension.ts @@ -142,33 +142,27 @@ export type CreateExtensionOptions< } & VerifyExtensionFactoryOutput; /** @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; + 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; 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; - }) => ExtensionDataContainer, + config?: T['config']; + inputs?: ResolveInputValueOverrides>; + }) => ExtensionDataContainer>, context: { node: AppNode; apis: ApiHolder; - config: TConfig & { + config: T['config'] & { [key in keyof TExtensionConfigSchema]: z.infer< ReturnType >; }; - inputs: Expand>; + inputs: Expand>; }, ): Iterable; } & VerifyExtensionFactoryOutput< - AnyExtensionDataRef extends UNewOutput ? UOutput : UNewOutput, + AnyExtensionDataRef extends UNewOutput + ? NonNullable + : 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 >; - } & 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 & - ( + T extends ExtensionDefinitionParameters = ExtensionDefinitionParameters, +> = ExtensionDefinition & { + readonly kind?: string; + readonly namespace?: string; + readonly name?: string; + readonly attachTo: { id: string; input: string }; + readonly disabled: boolean; + readonly configSchema?: PortableSchema; +} & ( | { 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( - overrides: ExtensionDefinition, -): InternalExtensionDefinition { - const internal = overrides as InternalExtensionDefinition< - TConfig, - TConfigInput - >; +export function toInternalExtensionDefinition< + T extends ExtensionDefinitionParameters, +>(overrides: ExtensionDefinition): InternalExtensionDefinition { + const internal = overrides as InternalExtensionDefinition; 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>; - }, - z.input< - z.ZodObject<{ - [key in keyof TConfigSchema]: ReturnType; - }> - >, - UOutput, - TInputs, - { +): ExtensionDefinition<{ + config: string extends keyof TConfigSchema + ? {} + : { + [key in keyof TConfigSchema]: z.infer>; + }; + configInput: string extends keyof TConfigSchema + ? {} + : z.input< + z.ZodObject<{ + [key in keyof TConfigSchema]: ReturnType; + }> + >; + 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>; + }; + configInput: string extends keyof TConfigSchema + ? {} + : z.input< + z.ZodObject<{ + [key in keyof TConfigSchema]: ReturnType; + }> + >; + 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: null as unknown as T, kind: options.kind, namespace: options.namespace, name: options.name, @@ -486,21 +493,5 @@ export function createExtension< }, }) as ExtensionDefinition; }, - } as InternalExtensionDefinition< - { - [key in keyof TConfigSchema]: z.infer>; - }, - z.input< - z.ZodObject<{ - [key in keyof TConfigSchema]: ReturnType; - }> - >, - 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; } diff --git a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.test.tsx b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.test.tsx index 58d68f82e8..fc77c63e97 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.test.tsx +++ b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.test.tsx @@ -35,10 +35,7 @@ import { createExtensionDataContainer } from './createExtensionDataContainer'; function unused(..._any: any[]) {} -function factoryOutput( - ext: ExtensionDefinition, - inputs: unknown = undefined, -) { +function factoryOutput(ext: ExtensionDefinition, inputs: unknown = undefined) { const int = toInternalExtensionDefinition(ext); if (int.version !== 'v2') { throw new Error('Expected v2 extension'); diff --git a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts index 25eb55d21f..85823b96a5 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts @@ -81,28 +81,31 @@ export type CreateExtensionBlueprintOptions< dataRefs?: TDataRefs; } & VerifyExtensionFactoryOutput; +/** @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,66 @@ 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; 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; + config?: T['config']; + inputs?: ResolveInputValueOverrides>; }, - ) => ExtensionDataContainer, + ) => ExtensionDataContainer, context: { node: AppNode; apis: ApiHolder; - config: TConfig & { + config: T['config'] & { [key in keyof TExtensionConfigSchema]: z.infer< ReturnType >; }; - inputs: Expand>; + inputs: Expand>; }, ): Iterable & VerifyExtensionFactoryOutput< - AnyExtensionDataRef extends UNewOutput ? UOutput : UNewOutput, + AnyExtensionDataRef extends UNewOutput ? T['output'] : UNewOutput, UFactoryOutput >; - }): ExtensionDefinition< - { - [key in keyof TExtensionConfigSchema]: z.infer< - ReturnType - >; - } & 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 + >; + }) & + 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 +223,7 @@ export interface ExtensionBlueprint< * @public */ export function createExtensionBlueprint< - TParams, + TParams extends object, UOutput extends AnyExtensionDataRef, TInputs extends { [inputName in string]: ExtensionInput< @@ -245,27 +249,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> }, - string extends keyof TConfigSchema + : { [key in keyof TConfigSchema]: z.infer> }; + configInput: string extends keyof TConfigSchema ? {} : z.input< z.ZodObject<{ [key in keyof TConfigSchema]: ReturnType; }> - >, - TDataRefs -> { + >; + dataRefs: TDataRefs; +}> { return { dataRefs: options.dataRefs, make(args) { @@ -282,7 +284,7 @@ export function createExtensionBlueprint< options.factory(args.params, ctx) as Iterable< ExtensionDataValue >, - }); + }) as ExtensionDefinition; }, makeWithOverrides(args) { return createExtension({ @@ -327,29 +329,27 @@ export function createExtensionBlueprint< }, ) as Iterable>; }, - }) as ExtensionDefinition; + }) 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>; - }, - string extends keyof TConfigSchema + }; + configInput: string extends keyof TConfigSchema ? {} : z.input< z.ZodObject<{ [key in keyof TConfigSchema]: ReturnType; }> - >, - TDataRefs - >; + >; + dataRefs: TDataRefs; + }>; } diff --git a/packages/frontend-plugin-api/src/wiring/createExtensionOverrides.ts b/packages/frontend-plugin-api/src/wiring/createExtensionOverrides.ts index 75c43a36d2..5add7b79b9 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtensionOverrides.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtensionOverrides.ts @@ -23,7 +23,7 @@ import { ExtensionOverrides, FeatureFlagConfig } from './types'; /** @public */ export interface ExtensionOverridesOptions { - extensions: ExtensionDefinition[]; + extensions: ExtensionDefinition[]; featureFlags?: FeatureFlagConfig[]; } diff --git a/packages/frontend-plugin-api/src/wiring/createFrontendPlugin.ts b/packages/frontend-plugin-api/src/wiring/createFrontendPlugin.ts index bab09c631e..2bea1fe8be 100644 --- a/packages/frontend-plugin-api/src/wiring/createFrontendPlugin.ts +++ b/packages/frontend-plugin-api/src/wiring/createFrontendPlugin.ts @@ -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[], + 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[] = [], + TExtensions extends readonly ExtensionDefinition[] = [], >( options: PluginOptions, ): BackstagePlugin< @@ -69,16 +73,20 @@ export function createFrontendPlugin< >]: KExtension; } > { - const extensions = new Array>(); + const extensions = new Array>(); const extensionDefinitionsById = new Map< string, - ExtensionDefinition + 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) { diff --git a/packages/frontend-plugin-api/src/wiring/index.ts b/packages/frontend-plugin-api/src/wiring/index.ts index 3862c0e178..6e136a6514 100644 --- a/packages/frontend-plugin-api/src/wiring/index.ts +++ b/packages/frontend-plugin-api/src/wiring/index.ts @@ -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'; diff --git a/packages/frontend-plugin-api/src/wiring/resolveExtensionDefinition.test.ts b/packages/frontend-plugin-api/src/wiring/resolveExtensionDefinition.test.ts index 3b43cd6518..cc874f9d03 100644 --- a/packages/frontend-plugin-api/src/wiring/resolveExtensionDefinition.test.ts +++ b/packages/frontend-plugin-api/src/wiring/resolveExtensionDefinition.test.ts @@ -23,10 +23,11 @@ import { describe('resolveExtensionDefinition', () => { const baseDef = { $$type: '@backstage/ExtensionDefinition', + T: null as any, version: 'v2', attachTo: { id: '', input: '' }, disabled: false, - override: () => ({} as ExtensionDefinition), + override: () => ({} as ExtensionDefinition), }; it.each([ @@ -39,7 +40,7 @@ describe('resolveExtensionDefinition', () => { const resolved = resolveExtensionDefinition({ ...baseDef, ...definition, - } as ExtensionDefinition); + } 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), + } 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), + 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: null as any, version: 'v1', attachTo: { id: '', input: '' }, disabled: false, - override: () => ({} as ExtensionDefinition), + override: () => ({} as ExtensionDefinition), }; it.each([ @@ -80,7 +82,7 @@ describe('old resolveExtensionDefinition', () => { const resolved = resolveExtensionDefinition({ ...baseDef, ...definition, - } as ExtensionDefinition); + } 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), + } 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), + 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>, diff --git a/packages/frontend-plugin-api/src/wiring/resolveExtensionDefinition.ts b/packages/frontend-plugin-api/src/wiring/resolveExtensionDefinition.ts index fe25164603..49d623ad68 100644 --- a/packages/frontend-plugin-api/src/wiring/resolveExtensionDefinition.ts +++ b/packages/frontend-plugin-api/src/wiring/resolveExtensionDefinition.ts @@ -17,6 +17,7 @@ import { ApiHolder, AppNode } from '../apis'; import { ExtensionDefinition, + ExtensionDefinitionParameters, ResolvedExtensionInputs, toInternalExtensionDefinition, } from './createExtension'; @@ -109,19 +110,14 @@ export function toInternalExtension( /** @ignore */ export type ResolveExtensionId< - TExtension extends ExtensionDefinition, + 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; + output: any; +}> ? [string | undefined] extends [IKind | INamespace | IName] ? never : ( @@ -140,10 +136,12 @@ export type ResolveExtensionId< : never; /** @internal */ -export function resolveExtensionDefinition( - definition: ExtensionDefinition, +export function resolveExtensionDefinition< + T extends ExtensionDefinitionParameters, +>( + definition: ExtensionDefinition, context?: { namespace?: string }, -): Extension { +): Extension { const internalDefinition = toInternalExtensionDefinition(definition); const { name, @@ -172,5 +170,5 @@ export function resolveExtensionDefinition( toString() { return `Extension{id=${id}}`; }, - } as InternalExtension; + } as InternalExtension & Object; } diff --git a/packages/frontend-plugin-api/src/wiring/types.ts b/packages/frontend-plugin-api/src/wiring/types.ts index 4a7d972b37..b713b2d926 100644 --- a/packages/frontend-plugin-api/src/wiring/types.ts +++ b/packages/frontend-plugin-api/src/wiring/types.ts @@ -35,7 +35,7 @@ export type AnyExternalRoutes = { [name in string]: ExternalRouteRef }; /** @public */ export type ExtensionMap< - TExtensionMap extends { [id in string]: ExtensionDefinition }, + TExtensionMap extends { [id in string]: ExtensionDefinition }, > = { get(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 } = {}, + TExtensionMap extends { [id in string]: ExtensionDefinition } = {}, > { readonly $$type: '@backstage/BackstagePlugin'; readonly id: string; @@ -52,7 +52,7 @@ export interface BackstagePlugin< readonly externalRoutes: TExternalRoutes; getExtension(id: TId): TExtensionMap[TId]; withOverrides(options: { - extensions: Array>; + extensions: Array; }): BackstagePlugin; } diff --git a/packages/frontend-test-utils/api-report.md b/packages/frontend-test-utils/api-report.md index 2f330dd3ee..3dcbacac57 100644 --- a/packages/frontend-test-utils/api-report.md +++ b/packages/frontend-test-utils/api-report.md @@ -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, +export function createExtensionTester( + subject: ExtensionDefinition, options?: { - config?: TConfigInput; + config?: T['configInput']; }, -): ExtensionTester; +): ExtensionTester; export { ErrorWithContext }; @@ -64,10 +61,10 @@ export class ExtensionQuery { // @public (undocumented) export class ExtensionTester { // (undocumented) - add( - extension: ExtensionDefinition, + add( + extension: ExtensionDefinition, options?: { - config?: TConfigInput; + config?: T['configInput']; }, ): ExtensionTester; // (undocumented) @@ -79,9 +76,9 @@ export class ExtensionTester { : IData : never; // (undocumented) - query( - extension: ExtensionDefinition, - ): ExtensionQuery; + query( + extension: ExtensionDefinition, + ): ExtensionQuery; // (undocumented) reactElement(): JSX.Element; } diff --git a/packages/frontend-test-utils/src/app/createExtensionTester.tsx b/packages/frontend-test-utils/src/app/createExtensionTester.tsx index 043438fe34..01687abc2d 100644 --- a/packages/frontend-test-utils/src/app/createExtensionTester.tsx +++ b/packages/frontend-test-utils/src/app/createExtensionTester.tsx @@ -21,6 +21,7 @@ import { Extension, ExtensionDataRef, ExtensionDefinition, + ExtensionDefinitionParameters, coreExtensionData, } from '@backstage/frontend-plugin-api'; import { Config, ConfigReader } from '@backstage/config'; @@ -75,12 +76,12 @@ export class ExtensionQuery { /** @public */ export class ExtensionTester { /** @internal */ - static forSubject( - subject: ExtensionDefinition, - options?: { config?: TConfigInput }, - ): ExtensionTester { + static forSubject( + subject: ExtensionDefinition, + options?: { config?: T['configInput'] }, + ): ExtensionTester { const tester = new ExtensionTester(); - tester.add(subject, options as TConfigInput & {}); + tester.add(subject, options as T['configInput'] & {}); return tester; } @@ -89,13 +90,13 @@ export class ExtensionTester { readonly #extensions = new Array<{ id: string; extension: Extension; - definition: ExtensionDefinition; + definition: ExtensionDefinition; config?: JsonValue; }>(); - add( - extension: ExtensionDefinition, - options?: { config?: TConfigInput }, + add( + extension: ExtensionDefinition, + options?: { config?: T['configInput'] }, ): ExtensionTester { if (this.#tree) { throw new Error( @@ -103,20 +104,19 @@ export class ExtensionTester { ); } - const { name, namespace } = extension; - - const definition = { - ...extension, - // setting name "test" as fallback - name: !namespace && !name ? 'test' : name, - }; - - const resolvedExtension = resolveExtensionDefinition(definition); + let resolvedExtension; + try { + resolvedExtension = resolveExtensionDefinition(extension); + } catch { + resolvedExtension = resolveExtensionDefinition(extension, { + namespace: 'test', + }); + } this.#extensions.push({ id: resolvedExtension.id, extension: resolvedExtension, - definition, + definition: extension, config: options?.config as JsonValue, }); @@ -135,12 +135,17 @@ export class ExtensionTester { return new ExtensionQuery(tree.root).get(ref); } - query( - extension: ExtensionDefinition, - ): ExtensionQuery { + query( + extension: ExtensionDefinition, + ): ExtensionQuery { const tree = this.#resolveTree(); - const actualId = resolveExtensionDefinition(extension).id; + const actualId = this.#extensions.find(e => e.definition === extension)?.id; + if (!actualId) { + throw new Error( + `Unable to query extension as it has not been added to the tester, ${extension}`, + ); + } const node = tree.nodes.get(actualId); @@ -232,13 +237,9 @@ export class ExtensionTester { } /** @public */ -export function createExtensionTester< - TConfig, - TConfigInput, - UOutput extends AnyExtensionDataRef, ->( - subject: ExtensionDefinition, - options?: { config?: TConfigInput }, -): ExtensionTester { +export function createExtensionTester( + subject: ExtensionDefinition, + options?: { config?: T['configInput'] }, +): ExtensionTester { return ExtensionTester.forSubject(subject, options); } diff --git a/packages/frontend-test-utils/src/app/renderInTestApp.tsx b/packages/frontend-test-utils/src/app/renderInTestApp.tsx index 8bbe2d058c..a9275071b4 100644 --- a/packages/frontend-test-utils/src/app/renderInTestApp.tsx +++ b/packages/frontend-test-utils/src/app/renderInTestApp.tsx @@ -123,7 +123,7 @@ export function renderInTestApp( element: JSX.Element, options?: TestAppOptions, ): RenderResult { - const extensions: Array> = [ + const extensions: Array = [ createExtension({ namespace: 'test', attachTo: { id: 'app/routes', input: 'routes' }, diff --git a/plugins/api-docs/api-report-alpha.md b/plugins/api-docs/api-report-alpha.md index c7ab4eb9e0..70bf57ebc0 100644 --- a/plugins/api-docs/api-report-alpha.md +++ b/plugins/api-docs/api-report-alpha.md @@ -25,10 +25,13 @@ const _default: BackstagePlugin< registerApi: ExternalRouteRef; }, { - '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, - {}, - { - 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 - | ConfigurableExtensionDataRef< - RouteRef, - 'core.routing.ref', - { - optional: true; - } - >, - { + }; + output: + | ConfigurableExtensionDataRef< + React_2.JSX.Element, + 'core.reactElement', + {} + > + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + RouteRef, + '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 - | ConfigurableExtensionDataRef< - RouteRef, - 'core.routing.ref', - { - optional: true; - } - > - | ConfigurableExtensionDataRef - | 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 + | ConfigurableExtensionDataRef< + RouteRef, + '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 - | ConfigurableExtensionDataRef< - RouteRef, - 'core.routing.ref', - { - optional: true; - } - > - | ConfigurableExtensionDataRef - | 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 + | ConfigurableExtensionDataRef< + RouteRef, + '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; diff --git a/plugins/app-visualizer/api-report.md b/plugins/app-visualizer/api-report.md index e01040a22a..7bf5e3608b 100644 --- a/plugins/app-visualizer/api-report.md +++ b/plugins/app-visualizer/api-report.md @@ -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 - | ConfigurableExtensionDataRef< - RouteRef, - '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 + | ConfigurableExtensionDataRef< + RouteRef, + '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; diff --git a/plugins/catalog-graph/api-report-alpha.md b/plugins/catalog-graph/api-report-alpha.md index 6ab438def3..6e1027dea0 100644 --- a/plugins/catalog-graph/api-report-alpha.md +++ b/plugins/catalog-graph/api-report-alpha.md @@ -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 - | ConfigurableExtensionDataRef< - RouteRef, - 'core.routing.ref', - { - optional: true; - } - >, - { + }; + output: + | ConfigurableExtensionDataRef< + React_2.JSX.Element, + 'core.reactElement', + {} + > + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + RouteRef, + '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; diff --git a/plugins/catalog-import/api-report-alpha.md b/plugins/catalog-import/api-report-alpha.md index 9f82f39266..992de9fc54 100644 --- a/plugins/catalog-import/api-report-alpha.md +++ b/plugins/catalog-import/api-report-alpha.md @@ -18,44 +18,45 @@ const _default: BackstagePlugin< }, {}, { - 'api:catalog-import': ExtensionDefinition< - {}, - {}, - ConfigurableExtensionDataRef, - {}, - { - 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 - | ConfigurableExtensionDataRef< - RouteRef, - 'core.routing.ref', - { - optional: true; - } - >, - {}, - { - kind: 'page'; - namespace: undefined; - name: undefined; - } - >; + }; + output: + | ConfigurableExtensionDataRef< + React_2.JSX.Element, + 'core.reactElement', + {} + > + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + RouteRef, + 'core.routing.ref', + { + optional: true; + } + >; + inputs: {}; + }>; } >; export default _default; diff --git a/plugins/catalog-react/api-report-alpha.md b/plugins/catalog-react/api-report-alpha.md index b22d76cd15..5dec3ab99d 100644 --- a/plugins/catalog-react/api-report-alpha.md +++ b/plugins/catalog-react/api-report-alpha.md @@ -83,7 +83,7 @@ export function convertLegacyEntityCardExtension( | typeof EntityCardBlueprint.dataRefs.filterFunction.T | typeof EntityCardBlueprint.dataRefs.filterExpression.T; }, -): ExtensionDefinition; +): ExtensionDefinition; // @alpha (undocumented) export function convertLegacyEntityContentExtension( @@ -96,42 +96,41 @@ export function convertLegacyEntityContentExtension( defaultPath?: string; defaultTitle?: string; }, -): ExtensionDefinition; +): 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; filter?: string | ((entity: Entity) => boolean) | undefined; - }, - | ConfigurableExtensionDataRef - | ConfigurableExtensionDataRef< - (entity: Entity) => boolean, - 'catalog.entity-filter-function', - { - optional: true; - } - > - | ConfigurableExtensionDataRef< - string, - 'catalog.entity-filter-expression', - { - optional: true; - } - >, - {}, - { + }; + output: + | ConfigurableExtensionDataRef + | 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; defaultPath: string; defaultTitle: string; routeRef?: RouteRef | undefined; filter?: string | ((entity: Entity) => boolean) | undefined; - }, - | ConfigurableExtensionDataRef - | ConfigurableExtensionDataRef - | ConfigurableExtensionDataRef< - RouteRef, - 'core.routing.ref', - { - optional: true; - } - > - | ConfigurableExtensionDataRef - | ConfigurableExtensionDataRef< - (entity: Entity) => boolean, - 'catalog.entity-filter-function', - { - optional: true; - } - > - | ConfigurableExtensionDataRef< - string, - 'catalog.entity-filter-expression', - { - optional: true; - } - >, - {}, - { + }; + output: + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + RouteRef, + 'core.routing.ref', + { + optional: true; + } + > + | ConfigurableExtensionDataRef + | 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; diff --git a/plugins/catalog-react/src/alpha/converters/convertLegacyEntityCardExtension.test.tsx b/plugins/catalog-react/src/alpha/converters/convertLegacyEntityCardExtension.test.tsx index 7dacd9c3e8..dd13318333 100644 --- a/plugins/catalog-react/src/alpha/converters/convertLegacyEntityCardExtension.test.tsx +++ b/plugins/catalog-react/src/alpha/converters/convertLegacyEntityCardExtension.test.tsx @@ -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'); }); }); diff --git a/plugins/catalog-react/src/alpha/converters/convertLegacyEntityCardExtension.tsx b/plugins/catalog-react/src/alpha/converters/convertLegacyEntityCardExtension.tsx index 76442f526d..ed92461736 100644 --- a/plugins/catalog-react/src/alpha/converters/convertLegacyEntityCardExtension.tsx +++ b/plugins/catalog-react/src/alpha/converters/convertLegacyEntityCardExtension.tsx @@ -30,7 +30,7 @@ export function convertLegacyEntityCardExtension( | typeof EntityCardBlueprint.dataRefs.filterFunction.T | typeof EntityCardBlueprint.dataRefs.filterExpression.T; }, -): ExtensionDefinition { +): ExtensionDefinition { const element = ; const extName = getComponentData(element, 'core.extensionName'); diff --git a/plugins/catalog-react/src/alpha/converters/convertLegacyEntityContentExtension.test.tsx b/plugins/catalog-react/src/alpha/converters/convertLegacyEntityContentExtension.test.tsx index 6d7c8f0420..d8ca126aa2 100644 --- a/plugins/catalog-react/src/alpha/converters/convertLegacyEntityContentExtension.test.tsx +++ b/plugins/catalog-react/src/alpha/converters/convertLegacyEntityContentExtension.test.tsx @@ -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'); }); }); diff --git a/plugins/catalog-react/src/alpha/converters/convertLegacyEntityContentExtension.tsx b/plugins/catalog-react/src/alpha/converters/convertLegacyEntityContentExtension.tsx index e44b5671fc..02f5d104bc 100644 --- a/plugins/catalog-react/src/alpha/converters/convertLegacyEntityContentExtension.tsx +++ b/plugins/catalog-react/src/alpha/converters/convertLegacyEntityContentExtension.tsx @@ -40,7 +40,7 @@ export function convertLegacyEntityContentExtension( defaultPath?: string; defaultTitle?: string; }, -): ExtensionDefinition { +): ExtensionDefinition { const element = ; const extName = getComponentData(element, 'core.extensionName'); diff --git a/plugins/catalog/api-report-alpha.md b/plugins/catalog/api-report-alpha.md index 42f4355921..151794858a 100644 --- a/plugins/catalog/api-report-alpha.md +++ b/plugins/catalog/api-report-alpha.md @@ -23,21 +23,19 @@ import { SearchResultItemExtensionPredicate } from '@backstage/plugin-search-rea import { TranslationRef } from '@backstage/core-plugin-api/alpha'; // @alpha -export const CatalogFilterBlueprint: ExtensionBlueprint< - { - kind: 'catalog-filter'; - namespace: undefined; - name: undefined; - }, - { +export const CatalogFilterBlueprint: ExtensionBlueprint<{ + kind: 'catalog-filter'; + namespace: undefined; + name: undefined; + params: { loader: () => Promise; - }, - ConfigurableExtensionDataRef, - {}, - {}, - {}, - never ->; + }; + output: ConfigurableExtensionDataRef; + inputs: {}; + config: {}; + configInput: {}; + dataRefs: never; +}>; // @alpha (undocumented) export const catalogTranslationRef: TranslationRef< @@ -148,10 +146,26 @@ const _default: BackstagePlugin< unregisterRedirect: ExternalRouteRef; }, { - 'nav-item:catalog': ExtensionDefinition< - {}, - {}, - ConfigurableExtensionDataRef< + 'api:catalog': ExtensionDefinition<{ + kind: 'api'; + namespace: undefined; + name: undefined; + config: {}; + configInput: {}; + output: ConfigurableExtensionDataRef< + AnyApiFactory, + 'core.api.factory', + {} + >; + inputs: {}; + }>; + 'nav-item:catalog': ExtensionDefinition<{ + kind: 'nav-item'; + namespace: undefined; + name: undefined; + config: {}; + configInput: {}; + output: ConfigurableExtensionDataRef< { title: string; icon: IconComponent; @@ -159,366 +173,356 @@ const _default: BackstagePlugin< }, 'core.nav-item.target', {} - >, - {}, - { - kind: 'nav-item'; - namespace: undefined; - name: undefined; - } - >; - 'api:catalog/starred-entities': ExtensionDefinition< - {}, - {}, - ConfigurableExtensionDataRef, - {}, - { - kind: 'api'; - namespace: undefined; - name: 'starred-entities'; - } - >; - 'api:catalog/entity-presentation': ExtensionDefinition< - {}, - {}, - ConfigurableExtensionDataRef, - {}, - { - kind: 'api'; - namespace: undefined; - name: 'entity-presentation'; - } - >; - 'entity-card:catalog/about': ExtensionDefinition< - { + >; + inputs: {}; + }>; + 'api:catalog/starred-entities': ExtensionDefinition<{ + kind: 'api'; + namespace: undefined; + name: 'starred-entities'; + config: {}; + configInput: {}; + output: ConfigurableExtensionDataRef< + AnyApiFactory, + 'core.api.factory', + {} + >; + inputs: {}; + }>; + 'api:catalog/entity-presentation': ExtensionDefinition<{ + kind: 'api'; + namespace: undefined; + name: 'entity-presentation'; + config: {}; + configInput: {}; + output: ConfigurableExtensionDataRef< + AnyApiFactory, + 'core.api.factory', + {} + >; + inputs: {}; + }>; + 'entity-card:catalog/about': ExtensionDefinition<{ + kind: 'entity-card'; + namespace: undefined; + name: 'about'; + config: { filter: string | undefined; - }, - { + }; + configInput: { filter?: string | undefined; - }, - | ConfigurableExtensionDataRef - | ConfigurableExtensionDataRef< - (entity: Entity) => boolean, - 'catalog.entity-filter-function', - { - optional: true; - } - > - | ConfigurableExtensionDataRef< - string, - 'catalog.entity-filter-expression', - { - optional: true; - } - >, - {}, - { - kind: 'entity-card'; - namespace: undefined; - name: 'about'; - } - >; - 'entity-card:catalog/links': ExtensionDefinition< - { + }; + output: + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + (entity: Entity) => boolean, + 'catalog.entity-filter-function', + { + optional: true; + } + > + | ConfigurableExtensionDataRef< + string, + 'catalog.entity-filter-expression', + { + optional: true; + } + >; + inputs: {}; + }>; + 'entity-card:catalog/links': ExtensionDefinition<{ + kind: 'entity-card'; + namespace: undefined; + name: 'links'; + config: { filter: string | undefined; - }, - { + }; + configInput: { filter?: string | undefined; - }, - | ConfigurableExtensionDataRef - | ConfigurableExtensionDataRef< - (entity: Entity) => boolean, - 'catalog.entity-filter-function', - { - optional: true; - } - > - | ConfigurableExtensionDataRef< - string, - 'catalog.entity-filter-expression', - { - optional: true; - } - >, - {}, - { - kind: 'entity-card'; - namespace: undefined; - name: 'links'; - } - >; - 'entity-card:catalog/labels': ExtensionDefinition< - { + }; + output: + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + (entity: Entity) => boolean, + 'catalog.entity-filter-function', + { + optional: true; + } + > + | ConfigurableExtensionDataRef< + string, + 'catalog.entity-filter-expression', + { + optional: true; + } + >; + inputs: {}; + }>; + 'entity-card:catalog/labels': ExtensionDefinition<{ + kind: 'entity-card'; + namespace: undefined; + name: 'labels'; + config: { filter: string | undefined; - }, - { + }; + configInput: { filter?: string | undefined; - }, - | ConfigurableExtensionDataRef - | ConfigurableExtensionDataRef< - (entity: Entity) => boolean, - 'catalog.entity-filter-function', - { - optional: true; - } - > - | ConfigurableExtensionDataRef< - string, - 'catalog.entity-filter-expression', - { - optional: true; - } - >, - {}, - { - kind: 'entity-card'; - namespace: undefined; - name: 'labels'; - } - >; - 'entity-card:catalog/depends-on-components': ExtensionDefinition< - { + }; + output: + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + (entity: Entity) => boolean, + 'catalog.entity-filter-function', + { + optional: true; + } + > + | ConfigurableExtensionDataRef< + string, + 'catalog.entity-filter-expression', + { + optional: true; + } + >; + inputs: {}; + }>; + 'entity-card:catalog/depends-on-components': ExtensionDefinition<{ + kind: 'entity-card'; + namespace: undefined; + name: 'depends-on-components'; + config: { filter: string | undefined; - }, - { + }; + configInput: { filter?: string | undefined; - }, - | ConfigurableExtensionDataRef - | ConfigurableExtensionDataRef< - (entity: Entity) => boolean, - 'catalog.entity-filter-function', - { - optional: true; - } - > - | ConfigurableExtensionDataRef< - string, - 'catalog.entity-filter-expression', - { - optional: true; - } - >, - {}, - { - kind: 'entity-card'; - namespace: undefined; - name: 'depends-on-components'; - } - >; - 'entity-card:catalog/depends-on-resources': ExtensionDefinition< - { + }; + output: + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + (entity: Entity) => boolean, + 'catalog.entity-filter-function', + { + optional: true; + } + > + | ConfigurableExtensionDataRef< + string, + 'catalog.entity-filter-expression', + { + optional: true; + } + >; + inputs: {}; + }>; + 'entity-card:catalog/depends-on-resources': ExtensionDefinition<{ + kind: 'entity-card'; + namespace: undefined; + name: 'depends-on-resources'; + config: { filter: string | undefined; - }, - { + }; + configInput: { filter?: string | undefined; - }, - | ConfigurableExtensionDataRef - | ConfigurableExtensionDataRef< - (entity: Entity) => boolean, - 'catalog.entity-filter-function', - { - optional: true; - } - > - | ConfigurableExtensionDataRef< - string, - 'catalog.entity-filter-expression', - { - optional: true; - } - >, - {}, - { - kind: 'entity-card'; - namespace: undefined; - name: 'depends-on-resources'; - } - >; - 'entity-card:catalog/has-components': ExtensionDefinition< - { + }; + output: + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + (entity: Entity) => boolean, + 'catalog.entity-filter-function', + { + optional: true; + } + > + | ConfigurableExtensionDataRef< + string, + 'catalog.entity-filter-expression', + { + optional: true; + } + >; + inputs: {}; + }>; + 'entity-card:catalog/has-components': ExtensionDefinition<{ + kind: 'entity-card'; + namespace: undefined; + name: 'has-components'; + config: { filter: string | undefined; - }, - { + }; + configInput: { filter?: string | undefined; - }, - | ConfigurableExtensionDataRef - | 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-components'; - } - >; - 'entity-card:catalog/has-resources': ExtensionDefinition< - { + }; + output: + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + (entity: Entity) => boolean, + 'catalog.entity-filter-function', + { + optional: true; + } + > + | ConfigurableExtensionDataRef< + string, + 'catalog.entity-filter-expression', + { + optional: true; + } + >; + inputs: {}; + }>; + 'entity-card:catalog/has-resources': ExtensionDefinition<{ + kind: 'entity-card'; + namespace: undefined; + name: 'has-resources'; + config: { filter: string | undefined; - }, - { + }; + configInput: { filter?: string | undefined; - }, - | ConfigurableExtensionDataRef - | 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-resources'; - } - >; - 'entity-card:catalog/has-subcomponents': ExtensionDefinition< - { + }; + output: + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + (entity: Entity) => boolean, + 'catalog.entity-filter-function', + { + optional: true; + } + > + | ConfigurableExtensionDataRef< + string, + 'catalog.entity-filter-expression', + { + optional: true; + } + >; + inputs: {}; + }>; + 'entity-card:catalog/has-subcomponents': ExtensionDefinition<{ + kind: 'entity-card'; + namespace: undefined; + name: 'has-subcomponents'; + config: { filter: string | undefined; - }, - { + }; + configInput: { filter?: string | undefined; - }, - | ConfigurableExtensionDataRef - | 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-subcomponents'; - } - >; - 'entity-card:catalog/has-subdomains': ExtensionDefinition< - { + }; + output: + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + (entity: Entity) => boolean, + 'catalog.entity-filter-function', + { + optional: true; + } + > + | ConfigurableExtensionDataRef< + string, + 'catalog.entity-filter-expression', + { + optional: true; + } + >; + inputs: {}; + }>; + 'entity-card:catalog/has-subdomains': ExtensionDefinition<{ + kind: 'entity-card'; + namespace: undefined; + name: 'has-subdomains'; + config: { filter: string | undefined; - }, - { + }; + configInput: { filter?: string | undefined; - }, - | ConfigurableExtensionDataRef - | 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-subdomains'; - } - >; - 'entity-card:catalog/has-systems': ExtensionDefinition< - { + }; + output: + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + (entity: Entity) => boolean, + 'catalog.entity-filter-function', + { + optional: true; + } + > + | ConfigurableExtensionDataRef< + string, + 'catalog.entity-filter-expression', + { + optional: true; + } + >; + inputs: {}; + }>; + 'entity-card:catalog/has-systems': ExtensionDefinition<{ + kind: 'entity-card'; + namespace: undefined; + name: 'has-systems'; + config: { filter: string | undefined; - }, - { + }; + configInput: { filter?: string | undefined; - }, - | ConfigurableExtensionDataRef - | 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-systems'; - } - >; - 'entity-content:catalog/overview': ExtensionDefinition< - { - [x: string]: any; - } & { + }; + output: + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + (entity: Entity) => boolean, + 'catalog.entity-filter-function', + { + optional: true; + } + > + | ConfigurableExtensionDataRef< + string, + 'catalog.entity-filter-expression', + { + optional: true; + } + >; + inputs: {}; + }>; + 'entity-content:catalog/overview': ExtensionDefinition<{ + config: { path: string | undefined; title: string | undefined; filter: string | undefined; - }, - { - [x: string]: any; - } & { + }; + configInput: { filter?: string | undefined; title?: string | undefined; path?: string | undefined; - }, - | ConfigurableExtensionDataRef - | ConfigurableExtensionDataRef - | ConfigurableExtensionDataRef< - RouteRef, - 'core.routing.ref', - { - optional: true; - } - > - | ConfigurableExtensionDataRef - | ConfigurableExtensionDataRef< - (entity: Entity) => boolean, - 'catalog.entity-filter-function', - { - optional: true; - } - > - | ConfigurableExtensionDataRef< - string, - 'catalog.entity-filter-expression', - { - optional: true; - } - >, - { + }; + output: + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + RouteRef, + '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: { cards: ExtensionInput< | ConfigurableExtensionDataRef | ConfigurableExtensionDataRef< @@ -540,33 +544,37 @@ const _default: BackstagePlugin< optional: false; } >; - }, - { - kind: 'entity-content'; - namespace: undefined; - name: 'overview'; - } - >; - 'catalog-filter:catalog/tag': ExtensionDefinition< - {}, - {}, - ConfigurableExtensionDataRef, - {}, - { - kind: 'catalog-filter'; - namespace: undefined; - name: 'tag'; - } - >; - 'catalog-filter:catalog/kind': ExtensionDefinition< - { + }; + kind: 'entity-content'; + namespace: undefined; + name: 'overview'; + }>; + 'catalog-filter:catalog/tag': ExtensionDefinition<{ + kind: 'catalog-filter'; + namespace: undefined; + name: 'tag'; + config: {}; + configInput: {}; + output: ConfigurableExtensionDataRef< + JSX_2.Element, + 'core.reactElement', + {} + >; + inputs: {}; + }>; + 'catalog-filter:catalog/kind': ExtensionDefinition<{ + config: { initialFilter: string; - }, - { + }; + configInput: { initialFilter?: string | undefined; - }, - ConfigurableExtensionDataRef, - { + }; + output: ConfigurableExtensionDataRef< + JSX_2.Element, + 'core.reactElement', + {} + >; + inputs: { [x: string]: ExtensionInput< AnyExtensionDataRef, { @@ -574,33 +582,37 @@ const _default: BackstagePlugin< singleton: boolean; } >; - }, - { - kind: 'catalog-filter'; - namespace: undefined; - name: 'kind'; - } - >; - 'catalog-filter:catalog/type': ExtensionDefinition< - {}, - {}, - ConfigurableExtensionDataRef, - {}, - { - kind: 'catalog-filter'; - namespace: undefined; - name: 'type'; - } - >; - 'catalog-filter:catalog/mode': ExtensionDefinition< - { + }; + kind: 'catalog-filter'; + namespace: undefined; + name: 'kind'; + }>; + 'catalog-filter:catalog/type': ExtensionDefinition<{ + kind: 'catalog-filter'; + namespace: undefined; + name: 'type'; + config: {}; + configInput: {}; + output: ConfigurableExtensionDataRef< + JSX_2.Element, + 'core.reactElement', + {} + >; + inputs: {}; + }>; + 'catalog-filter:catalog/mode': ExtensionDefinition<{ + config: { mode: 'all' | 'owners-only' | undefined; - }, - { + }; + configInput: { mode?: 'all' | 'owners-only' | undefined; - }, - ConfigurableExtensionDataRef, - { + }; + output: ConfigurableExtensionDataRef< + JSX_2.Element, + 'core.reactElement', + {} + >; + inputs: { [x: string]: ExtensionInput< AnyExtensionDataRef, { @@ -608,55 +620,63 @@ const _default: BackstagePlugin< singleton: boolean; } >; - }, - { - kind: 'catalog-filter'; - namespace: undefined; - name: 'mode'; - } - >; - 'catalog-filter:catalog/namespace': ExtensionDefinition< - {}, - {}, - ConfigurableExtensionDataRef, - {}, - { - kind: 'catalog-filter'; - namespace: undefined; - name: 'namespace'; - } - >; - 'catalog-filter:catalog/lifecycle': ExtensionDefinition< - {}, - {}, - ConfigurableExtensionDataRef, - {}, - { - kind: 'catalog-filter'; - namespace: undefined; - name: 'lifecycle'; - } - >; - 'catalog-filter:catalog/processing-status': ExtensionDefinition< - {}, - {}, - ConfigurableExtensionDataRef, - {}, - { - kind: 'catalog-filter'; - namespace: undefined; - name: 'processing-status'; - } - >; - 'catalog-filter:catalog/list': ExtensionDefinition< - { + }; + kind: 'catalog-filter'; + namespace: undefined; + name: 'mode'; + }>; + 'catalog-filter:catalog/namespace': ExtensionDefinition<{ + kind: 'catalog-filter'; + namespace: undefined; + name: 'namespace'; + config: {}; + configInput: {}; + output: ConfigurableExtensionDataRef< + JSX_2.Element, + 'core.reactElement', + {} + >; + inputs: {}; + }>; + 'catalog-filter:catalog/lifecycle': ExtensionDefinition<{ + kind: 'catalog-filter'; + namespace: undefined; + name: 'lifecycle'; + config: {}; + configInput: {}; + output: ConfigurableExtensionDataRef< + JSX_2.Element, + 'core.reactElement', + {} + >; + inputs: {}; + }>; + 'catalog-filter:catalog/processing-status': ExtensionDefinition<{ + kind: 'catalog-filter'; + namespace: undefined; + name: 'processing-status'; + config: {}; + configInput: {}; + output: ConfigurableExtensionDataRef< + JSX_2.Element, + 'core.reactElement', + {} + >; + inputs: {}; + }>; + 'catalog-filter:catalog/list': ExtensionDefinition<{ + config: { initialFilter: 'all' | 'owned' | 'starred'; - }, - { + }; + configInput: { initialFilter?: 'all' | 'owned' | 'starred' | undefined; - }, - ConfigurableExtensionDataRef, - { + }; + output: ConfigurableExtensionDataRef< + JSX_2.Element, + 'core.reactElement', + {} + >; + inputs: { [x: string]: ExtensionInput< AnyExtensionDataRef, { @@ -664,34 +684,29 @@ const _default: BackstagePlugin< singleton: boolean; } >; - }, - { - kind: 'catalog-filter'; - namespace: undefined; - name: 'list'; - } - >; - 'page:catalog': ExtensionDefinition< - { - [x: string]: any; - } & { + }; + kind: 'catalog-filter'; + namespace: undefined; + name: 'list'; + }>; + 'page:catalog': ExtensionDefinition<{ + config: { path: string | undefined; - }, - { - [x: string]: any; - } & { + }; + configInput: { path?: string | undefined; - }, - | ConfigurableExtensionDataRef - | ConfigurableExtensionDataRef - | ConfigurableExtensionDataRef< - RouteRef, - 'core.routing.ref', - { - optional: true; - } - >, - { + }; + output: + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + RouteRef, + 'core.routing.ref', + { + optional: true; + } + >; + inputs: { filters: ExtensionInput< ConfigurableExtensionDataRef, { @@ -699,34 +714,29 @@ const _default: BackstagePlugin< optional: false; } >; - }, - { - kind: 'page'; - namespace: undefined; - name: undefined; - } - >; - 'page:catalog/entity': ExtensionDefinition< - { - [x: string]: any; - } & { + }; + kind: 'page'; + namespace: undefined; + name: undefined; + }>; + 'page:catalog/entity': ExtensionDefinition<{ + config: { path: string | undefined; - }, - { - [x: string]: any; - } & { + }; + configInput: { path?: string | undefined; - }, - | ConfigurableExtensionDataRef - | ConfigurableExtensionDataRef - | ConfigurableExtensionDataRef< - RouteRef, - 'core.routing.ref', - { - optional: true; - } - >, - { + }; + output: + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + RouteRef, + 'core.routing.ref', + { + optional: true; + } + >; + inputs: { contents: ExtensionInput< | ConfigurableExtensionDataRef | ConfigurableExtensionDataRef @@ -761,35 +771,31 @@ const _default: BackstagePlugin< optional: false; } >; - }, - { - kind: 'page'; - namespace: undefined; - name: 'entity'; - } - >; - 'search-result-list-item:catalog': ExtensionDefinition< - { + }; + kind: 'page'; + namespace: undefined; + name: 'entity'; + }>; + 'search-result-list-item:catalog': ExtensionDefinition<{ + kind: 'search-result-list-item'; + namespace: undefined; + name: undefined; + config: { noTrack: boolean; - }, - { + }; + configInput: { noTrack?: boolean | undefined; - }, - ConfigurableExtensionDataRef< + }; + output: ConfigurableExtensionDataRef< { predicate?: SearchResultItemExtensionPredicate | undefined; component: SearchResultItemExtensionComponent; }, 'search.search-result-list-item.item', {} - >, - {}, - { - kind: 'search-result-list-item'; - namespace: undefined; - name: undefined; - } - >; + >; + inputs: {}; + }>; } >; export default _default; diff --git a/plugins/devtools/api-report-alpha.md b/plugins/devtools/api-report-alpha.md index 888faa29c7..a6a121ebd7 100644 --- a/plugins/devtools/api-report-alpha.md +++ b/plugins/devtools/api-report-alpha.md @@ -19,48 +19,52 @@ const _default: BackstagePlugin< }, {}, { - 'api:devtools': ExtensionDefinition< - {}, - {}, - ConfigurableExtensionDataRef, - {}, - { - 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 - | ConfigurableExtensionDataRef< - RouteRef, - '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 + | ConfigurableExtensionDataRef< + RouteRef, + '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; diff --git a/plugins/home/api-report-alpha.md b/plugins/home/api-report-alpha.md index e32412168b..7347d98d7b 100644 --- a/plugins/home/api-report-alpha.md +++ b/plugins/home/api-report-alpha.md @@ -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 - | ConfigurableExtensionDataRef< - RouteRef, - 'core.routing.ref', - { - optional: true; - } - >, - { + }; + output: + | ConfigurableExtensionDataRef< + React_2.JSX.Element, + 'core.reactElement', + {} + > + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + RouteRef, + '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; diff --git a/plugins/kubernetes/api-report-alpha.md b/plugins/kubernetes/api-report-alpha.md index 15f7efaf1b..b0cad703d6 100644 --- a/plugins/kubernetes/api-report-alpha.md +++ b/plugins/kubernetes/api-report-alpha.md @@ -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 - | ConfigurableExtensionDataRef - | ConfigurableExtensionDataRef< - RouteRef, - 'core.routing.ref', - { - optional: true; - } - >, - {}, - { - kind: 'page'; - namespace: undefined; - name: undefined; - } - >; - 'entity-content:kubernetes/kubernetes': ExtensionDefinition< - { + }; + output: + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + RouteRef, + '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 - | ConfigurableExtensionDataRef - | ConfigurableExtensionDataRef< - RouteRef, - 'core.routing.ref', - { - optional: true; - } - > - | ConfigurableExtensionDataRef - | 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, - {}, - { - kind: 'api'; - namespace: undefined; - name: 'proxy'; - } - >; - 'api:kubernetes/auth-providers': ExtensionDefinition< - {}, - {}, - ConfigurableExtensionDataRef, - {}, - { - kind: 'api'; - namespace: undefined; - name: 'auth-providers'; - } - >; - 'api:kubernetes/cluster-link-formatter': ExtensionDefinition< - {}, - {}, - ConfigurableExtensionDataRef, - {}, - { - kind: 'api'; - namespace: undefined; - name: 'cluster-link-formatter'; - } - >; + }; + output: + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + RouteRef, + '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; diff --git a/plugins/org/api-report-alpha.md b/plugins/org/api-report-alpha.md index 1187c8f0e3..c50e28bc7d 100644 --- a/plugins/org/api-report-alpha.md +++ b/plugins/org/api-report-alpha.md @@ -17,138 +17,134 @@ const _default: BackstagePlugin< catalogIndex: ExternalRouteRef; }, { - '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; diff --git a/plugins/scaffolder/api-report-alpha.md b/plugins/scaffolder/api-report-alpha.md index 007b106665..7758cc59d2 100644 --- a/plugins/scaffolder/api-report-alpha.md +++ b/plugins/scaffolder/api-report-alpha.md @@ -44,48 +44,52 @@ const _default: BackstagePlugin< }>; }, { - 'api:scaffolder': ExtensionDefinition< - {}, - {}, - ConfigurableExtensionDataRef, - {}, - { - 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 - | ConfigurableExtensionDataRef< - RouteRef, - '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 + | ConfigurableExtensionDataRef< + RouteRef, + '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; diff --git a/plugins/search-react/api-report-alpha.md b/plugins/search-react/api-report-alpha.md index 57bf03114f..51c98a8d93 100644 --- a/plugins/search-react/api-report-alpha.md +++ b/plugins/search-react/api-report-alpha.md @@ -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 { diff --git a/plugins/search/api-report-alpha.md b/plugins/search/api-report-alpha.md index 6aa956f131..9e043ab792 100644 --- a/plugins/search/api-report-alpha.md +++ b/plugins/search/api-report-alpha.md @@ -22,21 +22,26 @@ const _default: BackstagePlugin< }, {}, { - 'api:search': ExtensionDefinition< - {}, - {}, - ConfigurableExtensionDataRef, - {}, - { - 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 - | ConfigurableExtensionDataRef< - RouteRef, - 'core.routing.ref', - { - optional: true; - } - >, - { + }; + output: + | ConfigurableExtensionDataRef< + React_2.JSX.Element, + 'core.reactElement', + {} + > + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + RouteRef, + '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, - {}, - { - kind: 'api'; - namespace: undefined; - name: undefined; - } ->; +export const searchApi: ExtensionDefinition<{ + kind: 'api'; + namespace: undefined; + name: undefined; + config: {}; + configInput: {}; + output: ConfigurableExtensionDataRef; + 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 - | ConfigurableExtensionDataRef - | ConfigurableExtensionDataRef< - RouteRef, - 'core.routing.ref', - { - optional: true; - } - >, - { + }; + output: + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + RouteRef, + '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) ``` diff --git a/plugins/techdocs/api-report-alpha.md b/plugins/techdocs/api-report-alpha.md index 27d09e53e0..881778d5ae 100644 --- a/plugins/techdocs/api-report-alpha.md +++ b/plugins/techdocs/api-report-alpha.md @@ -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 + | ConfigurableExtensionDataRef< + RouteRef, + '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, - {}, - { - 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 - | ConfigurableExtensionDataRef< - RouteRef, - 'core.routing.ref', - { - optional: true; - } - >, - {}, - { - kind: 'page'; - namespace: undefined; - name: 'reader'; - } - >; - 'entity-content:techdocs': ExtensionDefinition< - { + }; + output: + | ConfigurableExtensionDataRef< + React_2.JSX.Element, + 'core.reactElement', + {} + > + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + RouteRef, + '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 - | ConfigurableExtensionDataRef< - RouteRef, - 'core.routing.ref', - { - optional: true; - } - > - | ConfigurableExtensionDataRef - | 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 + | ConfigurableExtensionDataRef< + RouteRef, + '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) ``` diff --git a/plugins/user-settings/api-report-alpha.md b/plugins/user-settings/api-report-alpha.md index f14c014a1e..c8e320e7d0 100644 --- a/plugins/user-settings/api-report-alpha.md +++ b/plugins/user-settings/api-report-alpha.md @@ -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 - | ConfigurableExtensionDataRef< - RouteRef, - 'core.routing.ref', - { - optional: true; - } - >, - { + }; + output: + | ConfigurableExtensionDataRef< + React_2.JSX.Element, + 'core.reactElement', + {} + > + | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef< + RouteRef, + '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<