diff --git a/packages/frontend-plugin-api/api-report.md b/packages/frontend-plugin-api/api-report.md index 2c92f863e8..96c7675c0d 100644 --- a/packages/frontend-plugin-api/api-report.md +++ b/packages/frontend-plugin-api/api-report.md @@ -147,20 +147,23 @@ export { AnyApiFactory }; export { AnyApiRef }; -// @public (undocumented) +// @public @deprecated (undocumented) export type AnyExtensionDataMap = { - [name in string]: ExtensionDataRef< - unknown, - string, - { - optional?: true; - } - >; + [name in string]: AnyExtensionDataRef; }; // @public (undocumented) +export type AnyExtensionDataRef = ExtensionDataRef< + unknown, + string, + { + optional?: true; + } +>; + +// @public @deprecated (undocumented) export type AnyExtensionInputMap = { - [inputName in string]: ExtensionInput< + [inputName in string]: LegacyExtensionInput< AnyExtensionDataMap, { optional: boolean; @@ -318,16 +321,18 @@ export { configApiRef }; // @public (undocumented) export interface ConfigurableExtensionDataRef< - TId extends string, TData, + TId extends string, TConfig extends { optional?: true; } = {}, > extends ExtensionDataRef { + // (undocumented) + (t: TData): ExtensionDataValue; // (undocumented) optional(): ConfigurableExtensionDataRef< - TId, TData, + TId, TData & { optional: true; } @@ -351,14 +356,14 @@ export type CoreErrorBoundaryFallbackProps = { // @public (undocumented) export const coreExtensionData: { reactElement: ConfigurableExtensionDataRef< - 'core.reactElement', JSX_2.Element, + 'core.reactElement', {} >; - routePath: ConfigurableExtensionDataRef<'core.routing.path', string, {}>; + routePath: ConfigurableExtensionDataRef; routeRef: ConfigurableExtensionDataRef< - 'core.routing.ref', RouteRef, + 'core.routing.ref', {} >; }; @@ -397,8 +402,8 @@ export function createApiExtension< export namespace createApiExtension { const // (undocumented) factoryDataRef: ConfigurableExtensionDataRef< - 'core.api.factory', AnyApiFactory, + 'core.api.factory', {} >; } @@ -455,10 +460,10 @@ export function createAppRootWrapperExtension< export namespace createAppRootWrapperExtension { const // (undocumented) componentDataRef: ConfigurableExtensionDataRef< - 'app.root.wrapper', React_2.ComponentType<{ children?: React_2.ReactNode; }>, + 'app.root.wrapper', {} >; } @@ -493,11 +498,11 @@ export function createComponentExtension< export namespace createComponentExtension { const // (undocumented) componentDataRef: ConfigurableExtensionDataRef< - 'core.component.component', { ref: ComponentRef; impl: ComponentType; }, + 'core.component.component', {} >; } @@ -508,6 +513,50 @@ export function createComponentRef(options: { }): ComponentRef; // @public (undocumented) +export function createExtension< + UOutput extends AnyExtensionDataRef, + TInputs extends { + [inputName in string]: ExtensionInput< + AnyExtensionDataRef, + { + optional: boolean; + singleton: boolean; + } + >; + }, + TConfig, + TConfigInput, + TConfigSchema extends { + [key: string]: (zImpl: typeof z) => z.ZodType; + }, + UFactoryOutput extends ExtensionDataValue, +>( + options: CreateExtensionOptions< + UOutput, + TInputs, + TConfig, + TConfigInput, + TConfigSchema, + UFactoryOutput + >, +): ExtensionDefinition< + TConfig & + (string extends keyof TConfigSchema + ? {} + : { + [key in keyof TConfigSchema]: z.infer>; + }), + TConfigInput & + (string extends keyof TConfigSchema + ? {} + : z.input< + z.ZodObject<{ + [key in keyof TConfigSchema]: ReturnType; + }> + >) +>; + +// @public @deprecated (undocumented) export function createExtension< TOutput extends AnyExtensionDataMap, TInputs extends AnyExtensionInputMap, @@ -517,7 +566,7 @@ export function createExtension< [key: string]: (zImpl: typeof z) => z.ZodType; }, >( - options: CreateExtensionOptions< + options: LegacyCreateExtensionOptions< TOutput, TInputs, TConfig, @@ -624,27 +673,27 @@ export interface CreateExtensionBlueprintOptions< // @public @deprecated (undocumented) export function createExtensionDataRef( id: string, -): ConfigurableExtensionDataRef; +): ConfigurableExtensionDataRef; // @public (undocumented) export function createExtensionDataRef(): { with(options: { id: TId; - }): ConfigurableExtensionDataRef; + }): ConfigurableExtensionDataRef; }; -// @public (undocumented) +// @public @deprecated (undocumented) export function createExtensionInput< - TExtensionData extends AnyExtensionDataMap, + TExtensionDataMap extends AnyExtensionDataMap, TConfig extends { singleton?: boolean; optional?: boolean; }, >( - extensionData: TExtensionData, + extensionData: TExtensionDataMap, config?: TConfig, -): ExtensionInput< - TExtensionData, +): LegacyExtensionInput< + TExtensionDataMap, { singleton: TConfig['singleton'] extends true ? true : false; optional: TConfig['optional'] extends true ? true : false; @@ -652,29 +701,62 @@ export function createExtensionInput< >; // @public (undocumented) -export interface CreateExtensionOptions< - TOutput extends AnyExtensionDataMap, - TInputs extends AnyExtensionInputMap, +export function createExtensionInput< + UExtensionData extends ExtensionDataRef< + unknown, + string, + { + optional?: true; + } + >, + TConfig extends { + singleton?: boolean; + optional?: boolean; + }, +>( + extensionData: Array, + config?: TConfig, +): ExtensionInput< + UExtensionData, + { + singleton: TConfig['singleton'] extends true ? true : false; + optional: TConfig['optional'] extends true ? true : false; + } +>; + +// @public (undocumented) +export type CreateExtensionOptions< + UOutput extends AnyExtensionDataRef, + TInputs extends { + [inputName in string]: ExtensionInput< + AnyExtensionDataRef, + { + optional: boolean; + singleton: boolean; + } + >; + }, TConfig, TConfigInput, TConfigSchema extends { [key: string]: (zImpl: typeof z) => z.ZodType; }, -> { - // (undocumented) + UFactoryOutput extends ExtensionDataValue, +> = { + kind?: string; + namespace?: string; + name?: string; attachTo: { id: string; input: string; }; - // (undocumented) + disabled?: boolean; + inputs?: TInputs; + output: Array; + configSchema?: PortableSchema; config?: { schema: TConfigSchema; }; - // @deprecated (undocumented) - configSchema?: PortableSchema; - // (undocumented) - disabled?: boolean; - // (undocumented) factory(context: { node: AppNode; config: TConfig & @@ -686,18 +768,23 @@ export interface CreateExtensionOptions< >; }); inputs: Expand>; - }): Expand>; - // (undocumented) - inputs?: TInputs; - // (undocumented) - kind?: string; - // (undocumented) - name?: string; - // (undocumented) - namespace?: string; - // (undocumented) - output: TOutput; -} + }): Iterable; +} & (( + UOutput extends any + ? UOutput['config']['optional'] extends true + ? never + : UOutput['id'] + : never +) extends infer IRequiredOutputIds + ? [IRequiredOutputIds] extends [UFactoryOutput['id']] + ? {} + : { + 'Error: The extension factory is missing the following outputs': Exclude< + IRequiredOutputIds, + UFactoryOutput['id'] + >; + } + : never); // @public (undocumented) export function createExtensionOverrides( @@ -750,12 +837,12 @@ export function createNavItemExtension(options: { export namespace createNavItemExtension { const // (undocumented) targetDataRef: ConfigurableExtensionDataRef< - 'core.nav-item.target', { title: string; icon: IconComponent_2; routeRef: RouteRef; }, + 'core.nav-item.target', {} >; } @@ -772,11 +859,11 @@ export function createNavLogoExtension(options: { export namespace createNavLogoExtension { const // (undocumented) logoElementsDataRef: ConfigurableExtensionDataRef< - 'core.nav-logo.logo-elements', { logoIcon?: JSX.Element | undefined; logoFull?: JSX.Element | undefined; }, + 'core.nav-logo.logo-elements', {} >; } @@ -866,10 +953,10 @@ export function createRouterExtension< export namespace createRouterExtension { const // (undocumented) componentDataRef: ConfigurableExtensionDataRef< - 'app.router.wrapper', React_2.ComponentType<{ children?: React_2.ReactNode; }>, + 'app.router.wrapper', {} >; } @@ -903,8 +990,8 @@ export function createSignInPageExtension< export namespace createSignInPageExtension { const // (undocumented) componentDataRef: ConfigurableExtensionDataRef< - 'core.sign-in-page.component', React_2.ComponentType, + 'core.sign-in-page.component', {} >; } @@ -927,8 +1014,8 @@ export function createThemeExtension( export namespace createThemeExtension { const // (undocumented) themeDataRef: ConfigurableExtensionDataRef< - 'core.theme.theme', AppTheme, + 'core.theme.theme', {} >; } @@ -943,7 +1030,6 @@ export function createTranslationExtension(options: { export namespace createTranslationExtension { const // (undocumented) translationDataRef: ConfigurableExtensionDataRef< - 'core.translation.translation', | TranslationResource | TranslationMessages< string, @@ -952,6 +1038,7 @@ export namespace createTranslationExtension { }, boolean >, + 'core.translation.translation', {} >; } @@ -1083,6 +1170,18 @@ export interface ExtensionBoundaryProps { routable?: boolean; } +// @public (undocumented) +export type ExtensionDataContainer = + { + get( + ref: ExtensionDataRef, + ): UExtensionData extends ExtensionDataRef + ? IConfig['optional'] extends true + ? IData | undefined + : IData + : never; + }; + // @public (undocumented) export type ExtensionDataRef< TData, @@ -1091,13 +1190,20 @@ export type ExtensionDataRef< optional?: true; } = {}, > = { - id: TId; - T: TData; - config: TConfig; - $$type: '@backstage/ExtensionDataRef'; + readonly $$type: '@backstage/ExtensionDataRef'; + readonly id: TId; + readonly T: TData; + readonly config: TConfig; }; -// @public +// @public (undocumented) +export type ExtensionDataValue = { + readonly $$type: '@backstage/ExtensionDataValue'; + readonly id: TId; + readonly value: TData; +}; + +// @public @deprecated export type ExtensionDataValues = { [DataName in keyof TExtensionData as TExtensionData[DataName]['config'] extends { optional: true; @@ -1135,7 +1241,13 @@ export interface ExtensionDefinition { // @public (undocumented) export interface ExtensionInput< - TExtensionData extends AnyExtensionDataMap, + TExtensionData extends ExtensionDataRef< + unknown, + string, + { + optional?: true; + } + >, TConfig extends { singleton: boolean; optional: boolean; @@ -1146,7 +1258,7 @@ export interface ExtensionInput< // (undocumented) config: TConfig; // (undocumented) - extensionData: TExtensionData; + extensionData: Array; } // @public (undocumented) @@ -1214,10 +1326,10 @@ export const IconBundleBlueprint: ExtensionBlueprint< AnyExtensionInputMap, { icons: ConfigurableExtensionDataRef< - 'core.icons', { [x: string]: IconComponent; }, + 'core.icons', {} >; }, @@ -1231,10 +1343,10 @@ export const IconBundleBlueprint: ExtensionBlueprint< }, { icons: ConfigurableExtensionDataRef< - 'core.icons', { [x: string]: IconComponent; }, + 'core.icons', {} >; } @@ -1265,6 +1377,70 @@ export { IdentityApi }; export { identityApiRef }; +// @public @deprecated (undocumented) +export interface LegacyCreateExtensionOptions< + TOutput extends AnyExtensionDataMap, + TInputs extends AnyExtensionInputMap, + TConfig, + TConfigInput, + TConfigSchema extends { + [key: string]: (zImpl: typeof z) => z.ZodType; + }, +> { + // (undocumented) + attachTo: { + id: string; + input: string; + }; + // (undocumented) + config?: { + schema: TConfigSchema; + }; + // @deprecated (undocumented) + configSchema?: PortableSchema; + // (undocumented) + disabled?: boolean; + // (undocumented) + factory(context: { + node: AppNode; + config: TConfig & + (string extends keyof TConfigSchema + ? {} + : { + [key in keyof TConfigSchema]: z.infer< + ReturnType + >; + }); + inputs: Expand>; + }): Expand>; + // (undocumented) + inputs?: TInputs; + // (undocumented) + kind?: string; + // (undocumented) + name?: string; + // (undocumented) + namespace?: string; + // (undocumented) + output: TOutput; +} + +// @public @deprecated (undocumented) +export interface LegacyExtensionInput< + TExtensionDataMap extends AnyExtensionDataMap, + TConfig extends { + singleton: boolean; + optional: boolean; + }, +> { + // (undocumented) + $$type: '@backstage/ExtensionInput'; + // (undocumented) + config: TConfig; + // (undocumented) + extensionData: TExtensionDataMap; +} + export { microsoftAuthApiRef }; export { OAuthApi }; @@ -1315,25 +1491,30 @@ export { ProfileInfo }; export { ProfileInfoApi }; // @public -export type ResolvedExtensionInput = - { - node: AppNode; - output: ExtensionDataValues; - }; +export type ResolvedExtensionInput< + TExtensionInput extends ExtensionInput, +> = TExtensionInput['extensionData'] extends Array + ? { + node: AppNode; + } & ExtensionDataContainer + : TExtensionInput['extensionData'] extends AnyExtensionDataMap + ? { + node: AppNode; + output: ExtensionDataValues; + } + : never; // @public export type ResolvedExtensionInputs< TInputs extends { - [name in string]: ExtensionInput; + [name in string]: ExtensionInput | LegacyExtensionInput; }, > = { [InputName in keyof TInputs]: false extends TInputs[InputName]['config']['singleton'] - ? Array>> + ? Array>> : false extends TInputs[InputName]['config']['optional'] - ? Expand> - : Expand< - ResolvedExtensionInput | undefined - >; + ? Expand> + : Expand | undefined>; }; // @public diff --git a/packages/frontend-plugin-api/src/wiring/index.ts b/packages/frontend-plugin-api/src/wiring/index.ts index baada41ae8..4b99ba8ebc 100644 --- a/packages/frontend-plugin-api/src/wiring/index.ts +++ b/packages/frontend-plugin-api/src/wiring/index.ts @@ -23,6 +23,7 @@ export { type ExtensionDataValues, type ResolvedExtensionInput, type ResolvedExtensionInputs, + type LegacyCreateExtensionOptions, type AnyExtensionInputMap, type AnyExtensionDataMap, } from './createExtension'; diff --git a/plugins/catalog-react/api-report-alpha.md b/plugins/catalog-react/api-report-alpha.md index 1ffa67068f..206c0160e2 100644 --- a/plugins/catalog-react/api-report-alpha.md +++ b/plugins/catalog-react/api-report-alpha.md @@ -18,18 +18,18 @@ import { TranslationRef } from '@backstage/core-plugin-api/alpha'; // @alpha (undocumented) export const catalogExtensionData: { entityContentTitle: ConfigurableExtensionDataRef< - 'catalog.entity-content-title', string, + 'catalog.entity-content-title', {} >; entityFilterFunction: ConfigurableExtensionDataRef< - 'catalog.entity-filter-function', (entity: Entity) => boolean, + 'catalog.entity-filter-function', {} >; entityFilterExpression: ConfigurableExtensionDataRef< - 'catalog.entity-filter-expression', string, + 'catalog.entity-filter-expression', {} >; }; diff --git a/plugins/home/api-report-alpha.md b/plugins/home/api-report-alpha.md index 1dd3da96be..eb693a8e6f 100644 --- a/plugins/home/api-report-alpha.md +++ b/plugins/home/api-report-alpha.md @@ -12,8 +12,8 @@ export default _default; // @alpha (undocumented) export const titleExtensionDataRef: ConfigurableExtensionDataRef< - 'title', string, + 'title', {} >; diff --git a/plugins/search-react/api-report-alpha.md b/plugins/search-react/api-report-alpha.md index 3da9ac23a4..c6e011fe41 100644 --- a/plugins/search-react/api-report-alpha.md +++ b/plugins/search-react/api-report-alpha.md @@ -31,11 +31,11 @@ export function createSearchResultListItemExtension< export namespace createSearchResultListItemExtension { const // (undocumented) itemDataRef: ConfigurableExtensionDataRef< - 'search.search-result-list-item.item', { predicate?: SearchResultItemExtensionPredicate | undefined; component: SearchResultItemExtensionComponent; }, + 'search.search-result-list-item.item', {} >; }