import * as react_jsx_runtime from 'react/jsx-runtime'; import * as react from 'react'; import { ReactNode, JSX as JSX$1, ComponentType, PropsWithChildren } from 'react'; import * as _backstage_frontend_plugin_api from '@backstage/frontend-plugin-api'; import { Expand, JsonObject, Observable, JsonValue, ExpandRecursive } from '@backstage/types'; import { z } from 'zod'; import { Config } from '@backstage/config'; /** * Analytics context envelope. * * @public */ interface AnalyticsContextValue { /** * The nearest known parent plugin where the event was captured. */ pluginId: string; /** * The nearest known parent extension where the event was captured. */ extensionId: string; [key: string]: string | boolean | number | undefined; } /** * Provides components in the child react tree an Analytics Context, ensuring * all analytics events captured within the context have relevant attributes. * * @remarks * * Analytics contexts are additive, meaning the context ultimately emitted with * an event is the combination of all contexts in the parent tree. * * @public */ declare const AnalyticsContext: (options: { attributes: Partial; children: ReactNode; }) => react_jsx_runtime.JSX.Element; /** * IconComponent is the common icon type used throughout Backstage when * working with and rendering generic icons, including the app system icons. * * @remarks * * The type is based on SvgIcon from Material UI, but we do not want the plugin-api * package to have a dependency on Material UI, nor do we want the props to be as broad * as the SvgIconProps interface. * * If you have the need to forward additional props from SvgIconProps, you can * open an issue or submit a PR to the main Backstage repo. When doing so please * also describe your use-case and reasoning of the addition. * * @public * @deprecated Use {@link IconElement} instead, passing `` rather than `MyIcon`. */ type IconComponent = ComponentType<{ fontSize?: 'medium' | 'large' | 'small' | 'inherit'; }>; /** * The type used for icon elements throughout Backstage. * * @remarks * * Icons should be exactly 24x24 pixels in size. * * @public */ type IconElement = JSX$1.Element | null; /** * Catch-all type for route params. * * @public */ type AnyRouteRefParams = { [param in string]: string; } | undefined; /** * Absolute route reference. * * @remarks * * See {@link https://backstage.io/docs/plugins/composability#routing-system}. * * @public */ interface RouteRef { readonly $$type: '@backstage/RouteRef'; readonly T: TParams; } /** * Create a {@link RouteRef} from a route descriptor. * * @param config - Description of the route reference to be created. * @public */ declare function createRouteRef(config?: { /** A list of parameter names that the path that this route ref is bound to must contain */ readonly params?: string extends TParamKeys ? (keyof TParams)[] : TParamKeys[]; aliasFor?: string; }): RouteRef; /** @public */ declare const coreExtensionData: { title: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef; /** An icon element for the extension. Should be exactly 24x24 pixels. */ icon: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef; reactElement: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef; routePath: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef; routeRef: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef, "core.routing.ref", {}>; }; /** @public */ type ExtensionDataValue = { readonly $$type: '@backstage/ExtensionDataValue'; readonly id: TId; readonly value: TData; }; /** @public */ type ExtensionDataRef = { readonly $$type: '@backstage/ExtensionDataRef'; readonly id: TId; readonly T: TData; readonly config: TConfig; }; /** @public */ type ExtensionDataRefToValue = TDataRef extends ExtensionDataRef ? ExtensionDataValue : never; /** * @deprecated Use `ExtensionDataRef` without type parameters instead. * @public */ type AnyExtensionDataRef = ExtensionDataRef; /** @public */ interface ConfigurableExtensionDataRef extends ExtensionDataRef { optional(): ConfigurableExtensionDataRef; (t: TData): ExtensionDataValue; } /** @public */ declare function createExtensionDataRef(): { with(options: { id: TId; }): ConfigurableExtensionDataRef; }; /** @public */ interface ExtensionInput = ExtensionDataRef, TConfig extends { singleton: boolean; optional: boolean; internal?: boolean; } = { singleton: boolean; optional: boolean; internal?: boolean; }> { readonly $$type: '@backstage/ExtensionInput'; readonly extensionData: Array; readonly config: TConfig; readonly replaces?: Array<{ id: string; input: string; }>; } /** * Creates a new extension input to be passed to the input map of an extension. * * @remarks * * Extension inputs created with this function can be passed to any `inputs` map * as part of creating or overriding an extension. * * The array of extension data references defines the data this input expects. * If the required data is not provided by the attached extension, the * attachment will fail. * * The `config` object can be used to restrict the behavior and shape of the * input. By default an input will accept zero or more extensions from any * plugin. The following options are available: * * - `singleton`: If set to `true`, only one extension can be attached to the * input at a time. Additional extensions will trigger an app error and be * ignored. * - `optional`: If set to `true`, the input is optional and can be omitted, * this only has an effect if the `singleton` is set to `true`. * - `internal`: If set to `true`, only extensions from the same plugin will be * allowed to attach to this input. Other extensions will trigger an app error * and be ignored. * * @param extensionData - The array of extension data references that this input * expects. * @param config - The configuration object for the input. * @returns An extension input declaration. * @example * ```ts * const extension = createExtension({ * attachTo: { id: 'example-parent', input: 'example-input' }, * inputs: { * content: createExtensionInput([coreExtensionData.reactElement], { * singleton: true, * }), * }, * output: [coreExtensionData.reactElement], * *factory({ inputs }) { * const content = inputs.content?.get(coreExtensionData.reactElement); * yield coreExtensionData.reactElement({content}); * }, * }); * ``` * @public */ declare function createExtensionInput, TConfig extends { singleton?: boolean; optional?: boolean; internal?: boolean; }>(extensionData: Array, config?: TConfig & { replaces?: Array<{ id: string; input: string; }>; }): ExtensionInput; /** @ignore */ type ResolvedInputValueOverrides = Expand<{ [KName in keyof TInputs as TInputs[KName] extends ExtensionInput ? IOptional extends true ? never : KName : never]: TInputs[KName] extends ExtensionInput ? ISingleton extends true ? Iterable> : Array>> : never; } & { [KName in keyof TInputs as TInputs[KName] extends ExtensionInput ? IOptional extends true ? KName : never : never]?: TInputs[KName] extends ExtensionInput ? ISingleton extends true ? Iterable> : Array>> : never; }>; /** @public */ interface CreateFrontendModuleOptions { pluginId: TPluginId; extensions?: TExtensions; featureFlags?: FeatureFlagConfig[]; } /** @public */ interface FrontendModule { readonly $$type: '@backstage/FrontendModule'; readonly pluginId: string; } /** * Creates a new module that can be installed in a Backstage app. * * @remarks * * Modules are used to add or override extensions for an existing plugin. If a * module provides an extension with the same ID as one provided by the plugin, * the extension provided by the module will always take precedence. * * Every module is created for a specific plugin by providing the * unique ID of the plugin that the module should be installed for. If that * plugin is not present in the app, the module will be ignored and have no * effect. * * For more information on how modules work, see the * {@link https://backstage.io/docs/frontend-system/architecture/extension-overrides#creating-a-frontend-module | documentation for modules} * in the frontend system documentation. * * It is recommended to name the module variable of the form `Module`. * * @example * * ```tsx * import { createFrontendModule } from '@backstage/frontend-plugin-api'; * * export const exampleModuleCustomPage = createFrontendModule({ * pluginId: 'example', * extensions: [ * // Overrides the default page for the 'example' plugin * PageBlueprint.make({ * path: '/example', * loader: () => import('./CustomPage').then(m => ), * }), * ], * }); * ``` * * @public */ declare function createFrontendModule(options: CreateFrontendModuleOptions): FrontendModule; /** @public */ type PortableSchema = { parse: (input: TInput) => TOutput; schema: JsonObject; }; /** @public */ type ExtensionAttachTo = { id: string; input: string; } | Array<{ id: string; input: string; }>; /** * @deprecated Use {@link ExtensionAttachTo} instead. * @public */ type ExtensionAttachToSpec = ExtensionAttachTo; /** @public */ interface Extension { $$type: '@backstage/Extension'; readonly id: string; readonly attachTo: ExtensionAttachToSpec; readonly disabled: boolean; readonly configSchema?: PortableSchema; } /** @ignore */ type ResolveExtensionId = TExtension extends ExtensionDefinition<{ kind: infer IKind extends string | undefined; name: infer IName extends string | undefined; params: any; }> ? [string] extends [IKind | IName] ? never : (undefined extends IName ? TNamespace : `${TNamespace}/${IName}`) extends infer INamePart extends string ? IKind extends string ? `${IKind}:${INamePart}` : INamePart : never : never; type CompareChars = [A, B] extends [ `${infer IAHead}${infer IARest}`, `${infer IBHead}${infer IBRest}` ] ? IAHead extends IBHead ? IBRest extends '' ? IARest extends '' ? 'eq' : 'gt' : IARest extends '' ? 'lt' : CompareChars : `0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz` extends `${string}${IAHead}${string}${IBHead}${string}` ? 'lt' : 'gt' : 'eq'; type CompareStrings = A extends B ? 'eq' : A extends undefined ? 'lt' : B extends undefined ? 'gt' : CompareChars; type CompareExtensions = CompareStrings extends 'eq' ? CompareStrings : CompareStrings; type SortExtensionsInner = TRest extends [ infer IHead extends ExtensionDefinition, ...infer IRest extends readonly ExtensionDefinition[] ] ? CompareExtensions extends 'lt' ? SortExtensionsInner : SortExtensionsInner : [low: TLow, high: THigh]; type SortExtensions = T extends [ infer IPivot extends ExtensionDefinition, ...infer IRest extends readonly ExtensionDefinition[] ] ? SortExtensionsInner extends [ low: infer ILow extends readonly ExtensionDefinition[], high: infer IHigh extends readonly ExtensionDefinition[] ] ? [...SortExtensions, IPivot, ...SortExtensions] : 'invalid SortExtensionsInner' : []; type UnionToIntersection$1 = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never; type PopUnion$1 = UnionToIntersection$1 U : never> extends () => infer R ? [next: R, rest: Exclude] : undefined; type UnionToArray = PopUnion$1 extends [ next: infer INext extends T, rest: infer IRest extends T ] ? UnionToArray : TResult; type ExtensionArrayToMap = T extends [ infer IHead extends ExtensionDefinition, ...infer IRest extends ExtensionDefinition[] ] ? ExtensionArrayToMap]: IHead; }> : TOut extends infer O ? { [K in keyof O]: O[K]; } : never; /** @ignore */ type MakeSortedExtensionsMap = ExtensionArrayToMap>, TId>; /** * Descriptor of a route relative to an absolute {@link RouteRef}. * * @remarks * * See {@link https://backstage.io/docs/plugins/composability#routing-system}. * * @public */ interface SubRouteRef { readonly $$type: '@backstage/SubRouteRef'; readonly T: TParams; readonly path: string; } /** * Used in {@link PathParams} type declaration. * @ignore */ type ParamPart = S extends `:${infer Param}` ? Param : never; /** * Used in {@link PathParams} type declaration. * @ignore */ type ParamNames = S extends `${infer Part}/${infer Rest}` ? ParamPart | ParamNames : ParamPart; /** * This utility type helps us infer a Param object type from a string path * For example, `/foo/:bar/:baz` inferred to `{ bar: string, baz: string }` * @ignore */ type PathParams = { [name in ParamNames]: string; }; /** * Merges a param object type with an optional params type into a params object. * @ignore */ type MergeParams = (P1[keyof P1] extends never ? {} : P1) & (P2 extends undefined ? {} : P2); /** * Convert empty params to undefined. * @ignore */ type TrimEmptyParams = keyof Params extends never ? undefined : Params; /** * Creates a SubRouteRef type given the desired parameters and parent route parameters. * The parameters types are merged together while ensuring that there is no overlap between the two. * * @ignore */ type MakeSubRouteRef = keyof Params & keyof ParentParams extends never ? SubRouteRef>> : never; /** * Create a {@link SubRouteRef} from a route descriptor. * * @param config - Description of the route reference to be created. * @public */ declare function createSubRouteRef(config: { path: Path; parent: RouteRef; }): MakeSubRouteRef, ParentParams>; /** * Route descriptor, to be later bound to a concrete route by the app. Used to implement cross-plugin route references. * * @remarks * * See {@link https://backstage.io/docs/plugins/composability#routing-system}. * * @public */ interface ExternalRouteRef { readonly $$type: '@backstage/ExternalRouteRef'; readonly T: TParams; } /** * Creates a route descriptor, to be later bound to a concrete route by the app. Used to implement cross-plugin route references. * * @remarks * * See {@link https://backstage.io/docs/plugins/composability#routing-system}. * * @param options - Description of the route reference to be created. * @public */ declare function createExternalRouteRef(config?: { /** * The parameters that will be provided to the external route reference. */ readonly params?: string extends TParamKeys ? (keyof TParams)[] : TParamKeys[]; /** * The route (typically in another plugin) that this should map to by default. * * The string is expected to be on the standard `.` form, * for example `techdocs.docRoot`. */ defaultTarget?: string; }): ExternalRouteRef; /** * React hook for constructing URLs to routes. * * @remarks * * See {@link https://backstage.io/docs/plugins/composability#routing-system} * * @param routeRef - The ref to route that should be converted to URL. * @returns A function that will in turn return the concrete URL of the `routeRef`, or `undefined` if the route is not available. * @public */ declare function useRouteRef(routeRef: RouteRef | SubRouteRef | ExternalRouteRef): RouteFunc | undefined; /** * React hook for retrieving dynamic params from the current URL. * @param _routeRef - Ref of the current route. * @public */ declare function useRouteRefParams(_routeRef: RouteRef | SubRouteRef): Params; /** * Information about the plugin. * * @public * @remarks * * This interface is intended to be extended via [module * augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation) * in order to add fields that are specific to each project. * * For example, one might add a `slackChannel` field that is read from the * opaque manifest file. * * See the options for `createApp` for more information about how to * customize the parsing of manifest files. */ interface FrontendPluginInfo { /** * The name of the package that implements the plugin. */ packageName?: string; /** * The version of the plugin, typically the version of the package.json file. */ version?: string; /** * As short description of the plugin, typically the description field in * package.json. */ description?: string; /** * The owner entity references of the plugin. */ ownerEntityRefs?: string[]; /** * Links related to the plugin. */ links?: Array<{ title: string; url: string; }>; } /** * Options for providing information for a plugin. * * @public */ type FrontendPluginInfoOptions = { /** * A loader function for the package.json file for the plugin. */ packageJson?: () => Promise<{ name: string; } & JsonObject>; /** * A loader function for an opaque manifest file for the plugin. */ manifest?: () => Promise; }; /** * A variant of the {@link FrontendPlugin} interface that can also be used to install overrides for the plugin. * * @public */ interface OverridableFrontendPlugin extends FrontendPlugin { getExtension(id: TId): OverridableExtensionDefinition; withOverrides(options: { extensions?: Array; /** * Overrides the display title of the plugin. */ title?: string; /** * Overrides the display icon of the plugin. */ icon?: IconElement; /** * Overrides the original info loaders of the plugin one by one. */ info?: FrontendPluginInfoOptions; }): OverridableFrontendPlugin; } /** @public */ interface FrontendPlugin { readonly $$type: '@backstage/FrontendPlugin'; /** * The plugin ID. */ readonly pluginId: string; /** * Deprecated alias for `pluginId`. * * @deprecated Use `pluginId` instead. */ readonly id: string; /** * The display title of the plugin, used in page headers and navigation. * Falls back to the plugin ID if not provided. */ readonly title?: string; /** * The display icon of the plugin, used in page headers and navigation. */ readonly icon?: IconElement; readonly routes: TRoutes; readonly externalRoutes: TExternalRoutes; /** * Loads the plugin info. */ info(): Promise; } /** @public */ interface PluginOptions { pluginId: TId; /** * The display title of the plugin, used in page headers and navigation. * Falls back to the plugin ID if not provided. */ title?: string; /** * The display icon of the plugin, used in page headers and navigation. */ icon?: IconElement; routes?: TRoutes; externalRoutes?: TExternalRoutes; extensions?: TExtensions; featureFlags?: FeatureFlagConfig[]; info?: FrontendPluginInfoOptions; } /** * Creates a new plugin that can be installed in a Backstage app. * * @remarks * * Every plugin is created with a unique ID and a set of extensions * that are installed as part of the plugin. * * For more information on how plugins work, see the * {@link https://backstage.io/docs/frontend-system/building-plugins/index | documentation for plugins} * in the frontend system documentation. * * @example * * ```tsx * import { createFrontendPlugin } from '@backstage/frontend-plugin-api'; * * export const examplePlugin = createFrontendPlugin({ * pluginId: 'example', * extensions: [ * PageBlueprint.make({ * path: '/example', * loader: () => import('./ExamplePage').then(m => ), * }), * ], * }); * ``` * * @public */ declare function createFrontendPlugin(options: PluginOptions): OverridableFrontendPlugin>; /** * Feature flag configuration. * * @public */ type FeatureFlagConfig = { /** Feature flag name */ name: string; }; /** @public */ type ExtensionDataContainer = Iterable ? IConfig['optional'] extends true ? never : ExtensionDataValue : never> & { get(ref: ExtensionDataRef): UExtensionData extends ExtensionDataRef ? IConfig['optional'] extends true ? IData | undefined : IData : never; }; /** @public */ type ExtensionFactoryMiddleware = (originalFactory: (contextOverrides?: { config?: JsonObject; }) => ExtensionDataContainer, context: { node: AppNode; apis: ApiHolder; config?: JsonObject; }) => Iterable>; /** @public */ type FrontendFeature = (Omit & { pluginId?: string; }) | FrontendModule; /** * A function used to define a parameter mapping function in order to facilitate * advanced parameter typing for extension blueprints. * * @remarks * * This function is primarily intended to enable the use of inferred type * parameters for blueprint params, but it can also be used to transoform the * params before they are handed ot the blueprint. * * The function must return an object created with * {@link createExtensionBlueprintParams}. * * @public */ type ExtensionBlueprintDefineParams = (params: TInput) => ExtensionBlueprintParams; /** * An opaque type that represents a set of parameters to be passed to a blueprint. * * @remarks * * Created with {@link createExtensionBlueprintParams}. * * @public */ type ExtensionBlueprintParams = { $$type: '@backstage/BlueprintParams'; T: T; }; /** * Wraps a plain blueprint parameter object in an opaque {@link ExtensionBlueprintParams} object. * * This is used in the definition of the `defineParams` option of {@link ExtensionBlueprint}. * * @public * @param params - The plain blueprint parameter object to wrap. * @returns The wrapped blueprint parameter object. */ declare function createExtensionBlueprintParams(params: T): ExtensionBlueprintParams; /** * @public */ type CreateExtensionBlueprintOptions z.ZodType; }, UFactoryOutput extends ExtensionDataValue, TDataRefs extends { [name in string]: ExtensionDataRef; }, UParentInputs extends ExtensionDataRef> = { kind: TKind; attachTo: ExtensionDefinitionAttachTo & VerifyExtensionAttachTo; disabled?: boolean; inputs?: TInputs; output: Array; config?: { schema: TConfigSchema; }; /** * This option is used to further refine the blueprint params. When this * option is used, the blueprint will require params to be passed in callback * form. This function can both transform the params before they are handed to * the blueprint factory, but importantly it also allows you to define * inferred type parameters for your blueprint params. * * @example * Blueprint definition with inferred type parameters: * ```ts * const ExampleBlueprint = createExtensionBlueprint({ * kind: 'example', * attachTo: { id: 'example', input: 'example' }, * output: [exampleComponentDataRef, exampleFetcherDataRef], * defineParams(params: { * component(props: ExampleProps): JSX.Element | null * fetcher(options: FetchOptions): Promise> * }) { * return createExtensionBlueprintParams(params); * }, * *factory(params) { * yield exampleComponentDataRef(params.component) * yield exampleFetcherDataRef(params.fetcher) * }, * }); * ``` * * @example * Usage of the above example blueprint: * ```ts * const example = ExampleBlueprint.make({ * params: defineParams => defineParams({ * component: ..., * fetcher: ..., * }), * }); * ``` */ defineParams?: TParams extends ExtensionBlueprintDefineParams ? TParams : 'The defineParams option must be a function if provided, see the docs for details'; factory(params: TParams extends ExtensionBlueprintDefineParams ? ReturnType['T'] : TParams, context: { node: AppNode; apis: ApiHolder; config: { [key in keyof TConfigSchema]: z.infer>; }; inputs: Expand>; }): Iterable; dataRefs?: TDataRefs; } & VerifyExtensionFactoryOutput; /** @public */ type ExtensionBlueprintParameters = { kind: string; params?: object | ExtensionBlueprintDefineParams; configInput?: { [K in string]: any; }; config?: { [K in string]: any; }; output?: ExtensionDataRef; inputs?: { [KName in string]: ExtensionInput; }; dataRefs?: { [name in string]: ExtensionDataRef; }; }; /** @ignore */ type ParamsFactory = (defineParams: TDefiner) => ReturnType; /** * Represents any form of params input that can be passed to a blueprint. * This also includes the invalid form of passing a plain params object to a blueprint that uses a definition callback. * * @ignore */ type AnyParamsInput$1 = TParams extends ExtensionBlueprintDefineParams ? IParams | ParamsFactory : TParams | ParamsFactory>; /** * @public */ interface ExtensionBlueprint { dataRefs: T['dataRefs']; make>, UParentInputs extends ExtensionDataRef>(args: { name?: TName; attachTo?: ExtensionDefinitionAttachTo & VerifyExtensionAttachTo, UParentInputs>; disabled?: boolean; params: TParamsInput extends ExtensionBlueprintDefineParams ? TParamsInput : T['params'] extends ExtensionBlueprintDefineParams ? 'Error: This blueprint uses advanced parameter types and requires you to pass parameters as using the following callback syntax: `.make({ params: defineParams => defineParams() })`' : T['params']; }): OverridableExtensionDefinition<{ kind: T['kind']; name: string | undefined extends TName ? undefined : TName; config: T['config']; configInput: T['configInput']; output: T['output']; inputs: T['inputs']; params: T['params']; }>; /** * Creates a new extension from the blueprint. * * You must either pass `params` directly, or define a `factory` that can * optionally call the original factory with the same params. */ makeWithOverrides z.ZodType; }, UFactoryOutput extends ExtensionDataValue, UNewOutput extends ExtensionDataRef, UParentInputs extends ExtensionDataRef, TExtraInputs extends { [inputName in string]: ExtensionInput; } = {}>(args: { name?: TName; attachTo?: ExtensionDefinitionAttachTo & VerifyExtensionAttachTo : UNewOutput, UParentInputs>; disabled?: boolean; inputs?: TExtraInputs & { [KName in keyof T['inputs']]?: `Error: Input '${KName & string}' is already defined in parent definition`; }; output?: Array; config?: { schema: TExtensionConfigSchema & { [KName in keyof T['config']]?: `Error: Config key '${KName & string}' is already defined in parent schema`; }; }; factory(originalFactory: >>(params: TParamsInput extends ExtensionBlueprintDefineParams ? TParamsInput : T['params'] extends ExtensionBlueprintDefineParams ? 'Error: This blueprint uses advanced parameter types and requires you to pass parameters as using the following callback syntax: `originalFactory(defineParams => defineParams())`' : T['params'], context?: { config?: T['config']; inputs?: ResolvedInputValueOverrides>; }) => ExtensionDataContainer>, context: { node: AppNode; apis: ApiHolder; config: T['config'] & { [key in keyof TExtensionConfigSchema]: z.infer>; }; inputs: Expand>; }): Iterable & VerifyExtensionFactoryOutput : UNewOutput, UFactoryOutput>; }): OverridableExtensionDefinition<{ config: Expand<(string extends keyof TExtensionConfigSchema ? {} : { [key in keyof TExtensionConfigSchema]: z.infer>; }) & T['config']>; configInput: Expand<(string extends keyof TExtensionConfigSchema ? {} : z.input; }>>) & T['configInput']>; output: ExtensionDataRef extends UNewOutput ? T['output'] : UNewOutput; inputs: Expand; kind: T['kind']; name: string | undefined extends TName ? undefined : TName; params: T['params']; }>; } /** * Creates a new extension blueprint that encapsulates the creation of * extensions of particular kinds. * * @remarks * * For details on how blueprints work, see the * {@link https://backstage.io/docs/frontend-system/architecture/extension-blueprints | documentation for extension blueprints} * in the frontend system documentation. * * Extension blueprints make it much easier for users to create new extensions * for your plugin. Rather than letting them use {@link createExtension} * directly, you can define a set of parameters and default factory for your * blueprint, removing a lot of the boilerplate and complexity that is otherwise * needed to create an extension. * * Each blueprint has its own `kind` that helps identify and group the * extensions that have been created with it. For example the * {@link PageBlueprint} has the kind `'page'`, and extensions created with it * will be given the ID `'page:[/]'`. Blueprints should always * be exported as `Blueprint`. * * When creating a blueprint the type of the parameters are inferred from the * `factory` function that you provide. The exception to that is when you need * your blueprint to include inferred type parameters, in which case you need to * use the `defineParams` option. See the documentation for the `defineParams` * option for more details on how that works. * * @example * ```tsx * // In your plugin library * export const GreetingBlueprint = createExtensionBlueprint({ * kind: 'greeting', * attachTo: { id: 'example', input: 'greetings' }, * output: [coreExtensionData.reactElement], * factory(params: { greeting: string }) { * return [coreExtensionData.reactElement(

{params.greeting}

)]; * }, * }); * * // Someone using your blueprint in their plugin * const exampleGreeting = GreetingBlueprint.make({ * params: { * greeting: 'Hello, world!', * }, * }); * ``` * @public */ declare function createExtensionBlueprint z.ZodType; }, UFactoryOutput extends ExtensionDataValue, TKind extends string, UParentInputs extends ExtensionDataRef, TDataRefs extends { [name in string]: ExtensionDataRef; } = never>(options: CreateExtensionBlueprintOptions): ExtensionBlueprint<{ kind: TKind; params: TParams; output: UOutput extends ExtensionDataRef ? ExtensionDataRef : never; inputs: string extends keyof TInputs ? {} : TInputs; config: string extends keyof TConfigSchema ? {} : { [key in keyof TConfigSchema]: z.infer>; }; configInput: string extends keyof TConfigSchema ? {} : z.input; }>>; dataRefs: TDataRefs; }>; /** * Convert a single extension input into a matching resolved input. * @public */ type ResolvedExtensionInput = TExtensionInput['extensionData'] extends Array ? { node: AppNode; } & ExtensionDataContainer : never; /** * Converts an extension input map into a matching collection of resolved inputs. * @public */ type ResolvedExtensionInputs = { [InputName in keyof TInputs]: false extends TInputs[InputName]['config']['singleton'] ? Array>> : false extends TInputs[InputName]['config']['optional'] ? Expand> : Expand | undefined>; }; type ToIntersection = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never; type PopUnion = ToIntersection U : never> extends () => infer R ? [rest: Exclude, next: R] : undefined; /** @ignore */ type JoinStringUnion = PopUnion extends [infer IRest extends string, infer INext extends string] ? TResult extends '' ? JoinStringUnion : JoinStringUnion : TResult; /** @ignore */ type RequiredExtensionIds = UExtensionData extends any ? UExtensionData['config']['optional'] extends true ? never : UExtensionData['id'] : never; /** @ignore */ type VerifyExtensionFactoryOutput> = [RequiredExtensionIds] extends [UFactoryOutput['id']] ? [UFactoryOutput['id']] extends [UDeclaredOutput['id']] ? {} : `Error: The extension factory has undeclared output(s): ${JoinStringUnion>}` : `Error: The extension factory is missing the following output(s): ${JoinStringUnion, UFactoryOutput['id']>>}`; /** @ignore */ type VerifyExtensionAttachTo = ExtensionDataRef extends UParentInput ? {} : [RequiredExtensionIds] extends [RequiredExtensionIds] ? {} : `Error: This parent extension input requires the following extension data, but it is not declared as guaranteed output of this extension: ${JoinStringUnion, RequiredExtensionIds>>}`; /** * Specifies where an extension should attach in the extension tree. * * @remarks * * A standard attachment point declaration will specify the ID of the parent extension, as well as the name of the input to attach to. * * There are two more advanced forms that are available for more complex use-cases: * * 1. Relative attachment points: using the `relative` property instead of `id`, the attachment point is resolved relative to the current plugin. * 2. Extension input references: using a reference in code to another extension's input in the same plugin. These references are always relative. * * @example * ```ts * // Attach to a specific extension by full ID * { id: 'app/routes', input: 'routes' } * * // Attach to an extension in the same plugin by kind * { relative: { kind: 'page' }, input: 'actions' } * * // Attach to a specific input of another extension * const page = ParentBlueprint.make({ ... }); * const child = ChildBlueprint.make({ attachTo: page.inputs.children }); * ``` * * @public */ type ExtensionDefinitionAttachTo = { id: string; input: string; relative?: never; } | { relative: { kind?: string; name?: string; }; input: string; id?: never; } | ExtensionInput; /** @public */ type CreateExtensionOptions z.ZodType; }, UFactoryOutput extends ExtensionDataValue, UParentInputs extends ExtensionDataRef> = { kind?: TKind; name?: TName; attachTo: ExtensionDefinitionAttachTo & VerifyExtensionAttachTo; disabled?: boolean; inputs?: TInputs; output: Array; config?: { schema: TConfigSchema; }; factory(context: { node: AppNode; apis: ApiHolder; config: { [key in keyof TConfigSchema]: z.infer>; }; inputs: Expand>; }): Iterable; } & VerifyExtensionFactoryOutput; /** @public */ type ExtensionDefinitionParameters = { kind?: string; name?: string; configInput?: { [K in string]: any; }; config?: { [K in string]: any; }; output?: ExtensionDataRef; inputs?: { [KName in string]: ExtensionInput; }; params?: object | ExtensionBlueprintDefineParams; }; /** * Same as the one in `createExtensionBlueprint`, but with `ParamsFactory` inlined. * It can't be exported because it breaks API reports. * @ignore */ type AnyParamsInput = TParams extends ExtensionBlueprintDefineParams ? IParams | ((define: TParams) => ReturnType) : TParams | ((define: ExtensionBlueprintDefineParams) => ReturnType>); /** @public */ interface ExtensionDefinition { $$type: '@backstage/ExtensionDefinition'; readonly T: TParams; } /** @public */ interface OverridableExtensionDefinition extends ExtensionDefinition { /** * References to the inputs of this extension, which can be used to attach child extensions. */ readonly inputs: { [K in keyof T['inputs']]: ExtensionInput ? IData : never>; }; override z.ZodType; }, UFactoryOutput extends ExtensionDataValue, UNewOutput extends ExtensionDataRef, TExtraInputs extends { [inputName in string]: ExtensionInput; }, TParamsInput extends AnyParamsInput>, UParentInputs extends ExtensionDataRef>(args: Expand<{ attachTo?: ExtensionDefinitionAttachTo & VerifyExtensionAttachTo : UNewOutput, UParentInputs>; disabled?: boolean; inputs?: TExtraInputs & { [KName in keyof T['inputs']]?: `Error: Input '${KName & string}' is already defined in parent definition`; }; output?: Array; config?: { schema: TExtensionConfigSchema & { [KName in keyof T['config']]?: `Error: Config key '${KName & string}' is already defined in parent schema`; }; }; factory?(originalFactory: >>(context?: Expand<{ config?: T['config']; inputs?: ResolvedInputValueOverrides>; } & ([T['params']] extends [never] ? {} : { params?: TFactoryParamsReturn extends ExtensionBlueprintDefineParams ? TFactoryParamsReturn : T['params'] extends ExtensionBlueprintDefineParams ? 'Error: This blueprint uses advanced parameter types and requires you to pass parameters as using the following callback syntax: `originalFactory(defineParams => defineParams())`' : Partial; })>) => ExtensionDataContainer>, context: { node: AppNode; apis: ApiHolder; config: T['config'] & { [key in keyof TExtensionConfigSchema]: z.infer>; }; inputs: Expand>; }): Iterable; } & ([T['params']] extends [never] ? {} : { params?: TParamsInput extends ExtensionBlueprintDefineParams ? TParamsInput : T['params'] extends ExtensionBlueprintDefineParams ? 'Error: This blueprint uses advanced parameter types and requires you to pass parameters as using the following callback syntax: `originalFactory(defineParams => defineParams())`' : Partial; })> & VerifyExtensionFactoryOutput : UNewOutput, UFactoryOutput>): OverridableExtensionDefinition<{ kind: T['kind']; name: T['name']; output: ExtensionDataRef extends UNewOutput ? T['output'] : UNewOutput; inputs: T['inputs'] & TExtraInputs; config: T['config'] & { [key in keyof TExtensionConfigSchema]: z.infer>; }; configInput: T['configInput'] & z.input; }>>; }>; } /** * Creates a new extension definition for installation in a Backstage app. * * @remarks * * This is a low-level function for creation of extensions with arbitrary inputs * and outputs and is typically only intended to be used for advanced overrides * or framework-level extensions. For most extension creation needs, it is * recommended to use existing {@link ExtensionBlueprint}s instead. You can find * blueprints both in the `@backstage/frontend-plugin-api` package as well as * other plugin libraries. There is also a list of * {@link https://backstage.io/docs/frontend-system/building-plugins/common-extension-blueprints | commonly used blueprints} * in the frontend system documentation. * * Extension definitions that are created with this function can be installed in * a Backstage app via a {@link FrontendPlugin} or {@link FrontendModule}. * * For more details on how extensions work, see the * {@link https://backstage.io/docs/frontend-system/architecture/extensions | documentation for extensions}. * * @example * * ```ts * const myExtension = createExtension({ * name: 'example', * attachTo: { id: 'app', input: 'root' }, * output: [coreExtensionData.reactElement], * factory() { * return [coreExtensionData.reactElement(

Hello, world!

)]; * }, * }); * ``` * * @public */ declare function createExtension z.ZodType; }, UFactoryOutput extends ExtensionDataValue, const TKind extends string | undefined = undefined, const TName extends string | undefined = undefined, UParentInputs extends ExtensionDataRef = ExtensionDataRef>(options: CreateExtensionOptions): OverridableExtensionDefinition<{ config: string extends keyof TConfigSchema ? {} : { [key in keyof TConfigSchema]: z.infer>; }; configInput: string extends keyof TConfigSchema ? {} : z.input; }>>; output: UOutput extends ExtensionDataRef ? ExtensionDataRef : never; inputs: TInputs; params: never; kind: string | undefined extends TKind ? undefined : TKind; name: string | undefined extends TName ? undefined : TName; }>; /** @public */ interface CreateFrontendFeatureLoaderOptions { loader(deps: { config: ConfigApi; }): Iterable> | Promise>> | AsyncIterable; } /** @public */ interface FrontendFeatureLoader { readonly $$type: '@backstage/FrontendFeatureLoader'; } /** @public */ declare function createFrontendFeatureLoader(options: CreateFrontendFeatureLoaderOptions): FrontendFeatureLoader; /** * The specification for this {@link AppNode} in the {@link AppTree}. * * @public * @remarks * * The specifications for a collection of app nodes is all the information needed * to build the tree and instantiate the nodes. */ interface AppNodeSpec { readonly id: string; readonly attachTo: ExtensionAttachTo; readonly extension: Extension; readonly disabled: boolean; readonly config?: unknown; readonly plugin: FrontendPlugin; } /** * The connections from this {@link AppNode} to other nodes. * * @public * @remarks * * The app node edges are resolved based on the app node specs, regardless of whether * adjacent nodes are disabled or not. If no parent attachment is present or */ interface AppNodeEdges { readonly attachedTo?: { node: AppNode; input: string; }; readonly attachments: ReadonlyMap; } /** * The instance of this {@link AppNode} in the {@link AppTree}. * * @public * @remarks * * The app node instance is created when the `factory` function of an extension is called. * Instances will only be present for nodes in the app that are connected to the root * node and not disabled */ interface AppNodeInstance { /** Returns a sequence of all extension data refs that were output by this instance */ getDataRefs(): Iterable>; /** Get the output data for a single extension data ref */ getData(ref: ExtensionDataRef): T | undefined; } /** * A node in the {@link AppTree}. * * @public */ interface AppNode { /** The specification for how this node should be instantiated */ readonly spec: AppNodeSpec; /** The edges from this node to other nodes in the app tree */ readonly edges: AppNodeEdges; /** The instance of this node, if it was instantiated */ readonly instance?: AppNodeInstance; } /** * The app tree containing all {@link AppNode}s of the app. * * @public */ interface AppTree { /** The root node of the app */ readonly root: AppNode; /** A map of all nodes in the app by ID, including orphaned or disabled nodes */ readonly nodes: ReadonlyMap; /** A sequence of all nodes with a parent that is not reachable from the app root node */ readonly orphans: Iterable; } /** * The API for interacting with the {@link AppTree}. * * @public */ interface AppTreeApi { /** * Get the {@link AppTree} for the app. */ getTree(): { tree: AppTree; }; /** * Get all nodes in the app that are mounted at a given route path. */ getNodesByRoutePath(routePath: string): { nodes: AppNode[]; }; } /** * The `ApiRef` of {@link AppTreeApi}. * * @public */ declare const appTreeApiRef: _backstage_frontend_plugin_api.ApiRef; /** * API reference. * * @public */ type ApiRef = { id: string; T: T; }; /** * Catch-all {@link ApiRef} type. * * @public */ type AnyApiRef = ApiRef; /** * Wraps a type with API properties into a type holding their respective {@link ApiRef}s. * * @public */ type TypesToApiRefs = { [key in keyof T]: ApiRef; }; /** * Provides lookup of APIs through their {@link ApiRef}s. * * @public */ type ApiHolder = { get(api: ApiRef): T | undefined; }; /** * Describes type returning API implementations. * * @public */ type ApiFactory = { api: ApiRef; deps: TypesToApiRefs; factory(deps: Deps): Impl; }; /** * Catch-all {@link ApiFactory} type. * * @public */ type AnyApiFactory = ApiFactory; /** * React hook for retrieving {@link ApiHolder}, an API catalog. * * @public */ declare function useApiHolder(): ApiHolder; /** * React hook for retrieving APIs. * * @param apiRef - Reference of the API to use. * @public */ declare function useApi(apiRef: ApiRef): T; /** * Wrapper for giving component an API context. * * @param apis - APIs for the context. * @public */ declare function withApis(apis: TypesToApiRefs): (WrappedComponent: ComponentType) => { (props: PropsWithChildren>): react_jsx_runtime.JSX.Element; displayName: string; }; /** * API reference configuration - holds an ID of the referenced API. * * @public */ type ApiRefConfig = { id: string; }; /** * Creates a reference to an API. The provided `id` is a stable identifier for * the API implementation. * * @remarks * * The frontend system infers the owning plugin for an API from the `id`. The * recommended pattern is `plugin..*` (for example, * `plugin.catalog.entity-presentation`). This ensures that other plugins can't * mistakenly override your API implementation. * * @param config - The descriptor of the API to reference. * @returns An API reference. * @public */ declare function createApiRef(config: ApiRefConfig): ApiRef; /** * Used to infer types for a standalone {@link ApiFactory} that isn't immediately passed * to another function. * * @remarks * * This function doesn't actually do anything, it's only used to infer types. * * @public */ declare function createApiFactory(factory: ApiFactory): ApiFactory; /** * Used to infer types for a standalone {@link ApiFactory} that isn't immediately passed * to another function. * * @param api - Ref of the API that will be produced by the factory. * @param instance - Implementation of the API to use. * @public */ declare function createApiFactory(api: ApiRef, instance: Impl): ApiFactory; /** * This file contains declarations for common interfaces of auth-related APIs. * The declarations should be used to signal which type of authentication and * authorization methods each separate auth provider supports. * * For example, a Google OAuth provider that supports OAuth 2 and OpenID Connect, * would be declared as follows: * * const googleAuthApiRef = createApiRef({ ... }) */ /** * Information about the auth provider. * * @remarks * * This information is used both to connect the correct auth provider in the backend, as * well as displaying the provider to the user. * * @public */ type AuthProviderInfo = { /** * The ID of the auth provider. This should match with ID of the provider in the `@backstage/auth-backend`. */ id: string; /** * Title for the auth provider, for example "GitHub" */ title: string; /** * Icon for the auth provider. */ icon: IconComponent; /** * Optional user friendly messaage to display for the auth provider. */ message?: string; }; /** * An array of scopes, or a scope string formatted according to the * auth provider, which is typically a space separated list. * * @remarks * * See the documentation for each auth provider for the list of scopes * supported by each provider. * * @public */ type OAuthScope = string | string[]; /** * Configuration of an authentication request. * * @public */ type AuthRequestOptions = { /** * If this is set to true, the user will not be prompted to log in, * and an empty response will be returned if there is no existing session. * * This can be used to perform a check whether the user is logged in, or if you don't * want to force a user to be logged in, but provide functionality if they already are. * * @defaultValue false */ optional?: boolean; /** * If this is set to true, the request will bypass the regular oauth login modal * and open the login popup directly. * * The method must be called synchronously from a user action for this to work in all browsers. * * @defaultValue false */ instantPopup?: boolean; }; /** * This API provides access to OAuth 2 credentials. It lets you request access tokens, * which can be used to act on behalf of the user when talking to APIs. * * @public */ type OAuthApi = { /** * Requests an OAuth 2 Access Token, optionally with a set of scopes. The access token allows * you to make requests on behalf of the user, and the copes may grant you broader access, depending * on the auth provider. * * Each auth provider has separate handling of scope, so you need to look at the documentation * for each one to know what scope you need to request. * * This method is cheap and should be called each time an access token is used. Do not for example * store the access token in React component state, as that could cause the token to expire. Instead * fetch a new access token for each request. * * Be sure to include all required scopes when requesting an access token. When testing your implementation * it is best to log out the Backstage session and then visit your plugin page directly, as * you might already have some required scopes in your existing session. Not requesting the correct * scopes can lead to 403 or other authorization errors, which can be tricky to debug. * * If the user has not yet granted access to the provider and the set of requested scopes, the user * will be prompted to log in. The returned promise will not resolve until the user has * successfully logged in. The returned promise can be rejected, but only if the user rejects the login request. */ getAccessToken(scope?: OAuthScope, options?: AuthRequestOptions): Promise; }; /** * This API provides access to OpenID Connect credentials. It lets you request ID tokens, * which can be passed to backend services to prove the user's identity. * * @public */ type OpenIdConnectApi = { /** * Requests an OpenID Connect ID Token. * * This method is cheap and should be called each time an ID token is used. Do not for example * store the id token in React component state, as that could cause the token to expire. Instead * fetch a new id token for each request. * * If the user has not yet logged in to Google inside Backstage, the user will be prompted * to log in. The returned promise will not resolve until the user has successfully logged in. * The returned promise can be rejected, but only if the user rejects the login request. */ getIdToken(options?: AuthRequestOptions): Promise; }; /** * This API provides access to profile information of the user from an auth provider. * * @public */ type ProfileInfoApi = { /** * Get profile information for the user as supplied by this auth provider. * * If the optional flag is not set, a session is guaranteed to be returned, while if * the optional flag is set, the session may be undefined. See {@link AuthRequestOptions} for more details. */ getProfile(options?: AuthRequestOptions): Promise; }; /** * This API provides access to the user's identity within Backstage. * * @remarks * * An auth provider that implements this interface can be used to sign-in to backstage. It is * not intended to be used directly from a plugin, but instead serves as a connection between * this authentication method and the app's {@link IdentityApi} * * @public */ type BackstageIdentityApi = { /** * Get the user's identity within Backstage. This should normally not be called directly, * use the {@link IdentityApi} instead. * * If the optional flag is not set, a session is guaranteed to be returned, while if * the optional flag is set, the session may be undefined. See {@link AuthRequestOptions} for more details. */ getBackstageIdentity(options?: AuthRequestOptions): Promise; }; /** * User identity information within Backstage. * * @public */ type BackstageUserIdentity = { /** * The type of identity that this structure represents. In the frontend app * this will currently always be 'user'. */ type: 'user'; /** * The entityRef of the user in the catalog. * For example User:default/sandra */ userEntityRef: string; /** * The user and group entities that the user claims ownership through */ ownershipEntityRefs: string[]; }; /** * Token and Identity response, with the users claims in the Identity. * * @public */ type BackstageIdentityResponse = { /** * The token used to authenticate the user within Backstage. */ token: string; /** * The time at which the token expires. If not set, it can be assumed that the token does not expire. */ expiresAt?: Date; /** * Identity information derived from the token. */ identity: BackstageUserIdentity; }; /** * Profile information of the user. * * @public */ type ProfileInfo = { /** * Email ID. */ email?: string; /** * Display name that can be presented to the user. */ displayName?: string; /** * URL to an avatar image of the user. */ picture?: string; }; /** * Session state values passed to subscribers of the SessionApi. * * @public */ declare const SessionState: { /** * User signed in. */ readonly SignedIn: "SignedIn"; /** * User not signed in. */ readonly SignedOut: "SignedOut"; }; /** * @public */ type SessionState = (typeof SessionState)[keyof typeof SessionState]; /** * @public */ declare namespace SessionState { type SignedIn = typeof SessionState.SignedIn; type SignedOut = typeof SessionState.SignedOut; } /** * The SessionApi provides basic controls for any auth provider that is tied to a persistent session. * * @public */ type SessionApi = { /** * Sign in with a minimum set of permissions. */ signIn(): Promise; /** * Sign out from the current session. This will reload the page. */ signOut(): Promise; /** * Observe the current state of the auth session. Emits the current state on subscription. */ sessionState$(): Observable; }; /** * Provides authentication towards Google APIs and identities. * * @public * @remarks * * See {@link https://developers.google.com/identity/protocols/googlescopes} for a full list of supported scopes. * * Note that the ID token payload is only guaranteed to contain the user's numerical Google ID, * email and expiration information. Do not rely on any other fields, as they might not be present. */ declare const googleAuthApiRef: ApiRef; /** * Provides authentication towards GitHub APIs. * * @public * @remarks * * See {@link https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/} * for a full list of supported scopes. */ declare const githubAuthApiRef: ApiRef; /** * Provides authentication towards Okta APIs. * * @public * @remarks * * See {@link https://developer.okta.com/docs/guides/implement-oauth-for-okta/scopes/} * for a full list of supported scopes. */ declare const oktaAuthApiRef: ApiRef; /** * Provides authentication towards GitLab APIs. * * @public * @remarks * * See {@link https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#limiting-scopes-of-a-personal-access-token} * for a full list of supported scopes. */ declare const gitlabAuthApiRef: ApiRef; /** * Provides authentication towards Microsoft APIs and identities. * * @public * @remarks * * For more info and a full list of supported scopes, see: * - {@link https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-permissions-and-consent} * - {@link https://docs.microsoft.com/en-us/graph/permissions-reference} */ declare const microsoftAuthApiRef: ApiRef; /** * Provides authentication towards OneLogin APIs. * * @public */ declare const oneloginAuthApiRef: ApiRef; /** * Provides authentication towards Bitbucket APIs. * * @public * @remarks * * See {@link https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/} * for a full list of supported scopes. */ declare const bitbucketAuthApiRef: ApiRef; /** * Provides authentication towards Bitbucket Server APIs. * * @public * @remarks * * See {@link https://confluence.atlassian.com/bitbucketserver/bitbucket-oauth-2-0-provider-api-1108483661.html#BitbucketOAuth2.0providerAPI-scopes} * for a full list of supported scopes. */ declare const bitbucketServerAuthApiRef: ApiRef; /** * Provides authentication towards Atlassian APIs. * * @public * @remarks * * See {@link https://developer.atlassian.com/cloud/jira/platform/scopes-for-connect-and-oauth-2-3LO-apps/} * for a full list of supported scopes. */ declare const atlassianAuthApiRef: ApiRef; /** * Provides authentication towards VMware Cloud APIs and identities. * * @public * @remarks * * For more info about VMware Cloud identity and access management: * - {@link https://docs.vmware.com/en/VMware-Cloud-services/services/Using-VMware-Cloud-Services/GUID-53D39337-D93A-4B84-BD18-DDF43C21479A.html} */ declare const vmwareCloudAuthApiRef: ApiRef; /** * Provides authentication towards OpenShift APIs and identities. * * @public * @remarks * * See {@link https://docs.redhat.com/en/documentation/openshift_container_platform/latest/html/authentication_and_authorization/configuring-oauth-clients} * on how to configure the OAuth clients and * {@link https://docs.redhat.com/en/documentation/openshift_container_platform/latest/html-single/authentication_and_authorization/index#tokens-scoping-about_configuring-internal-oauth} * for available scopes. */ declare const openshiftAuthApiRef: ApiRef; /** * Message handled by the {@link AlertApi}. * * @public */ type AlertMessage = { message: string; severity?: 'success' | 'info' | 'warning' | 'error'; display?: 'permanent' | 'transient'; }; /** * The alert API is used to report alerts to the app, and display them to the user. * * @public */ type AlertApi = { /** * Post an alert for handling by the application. */ post(alert: AlertMessage): void; /** * Observe alerts posted by other parts of the application. */ alert$(): Observable; }; /** * The {@link ApiRef} of {@link AlertApi}. * * @public */ declare const alertApiRef: ApiRef; /** @public */ type AppLanguageApi = { getAvailableLanguages(): { languages: string[]; }; setLanguage(language?: string): void; getLanguage(): { language: string; }; language$(): Observable<{ language: string; }>; }; /** * @public */ declare const appLanguageApiRef: ApiRef; /** * Describes a theme provided by the app. * * @public */ type AppTheme = { /** * ID used to remember theme selections. */ id: string; /** * Title of the theme */ title: string; /** * Theme variant */ variant: 'light' | 'dark'; /** * An Icon for the theme mode setting. */ icon?: React.ReactElement; Provider(props: { children: ReactNode; }): JSX.Element | null; }; /** * The AppThemeApi gives access to the current app theme, and allows switching * to other options that have been registered as a part of the App. * * @public */ type AppThemeApi = { /** * Get a list of available themes. */ getInstalledThemes(): AppTheme[]; /** * Observe the currently selected theme. A value of undefined means no specific theme has been selected. */ activeThemeId$(): Observable; /** * Get the current theme ID. Returns undefined if no specific theme is selected. */ getActiveThemeId(): string | undefined; /** * Set a specific theme to use in the app, overriding the default theme selection. * * Clear the selection by passing in undefined. */ setActiveThemeId(themeId?: string): void; }; /** * The {@link ApiRef} of {@link AppThemeApi}. * * @public */ declare const appThemeApiRef: ApiRef; /** @public */ interface ExtensionBoundaryProps { errorPresentation?: 'error-api' | 'error-display'; node: AppNode; children: ReactNode; } /** @public */ declare function ExtensionBoundary(props: ExtensionBoundaryProps): react_jsx_runtime.JSX.Element; /** @public */ declare namespace ExtensionBoundary { function lazy(appNode: AppNode, loader: () => Promise): JSX.Element; function lazyComponent(appNode: AppNode, loader: () => Promise<(props: TProps) => JSX.Element>): (props: TProps) => JSX.Element; } /** @public */ type SwappableComponentRef = { id: string; TProps: TInnerComponentProps; TExternalProps: TExternalComponentProps; $$type: '@backstage/SwappableComponentRef'; }; /** * Options for creating an SwappableComponent. * * @public */ type CreateSwappableComponentOptions = { id: string; loader?: (() => (props: TInnerComponentProps) => JSX.Element | null) | (() => Promise<(props: TInnerComponentProps) => JSX.Element | null>); transformProps?: (props: TExternalComponentProps) => TInnerComponentProps; }; /** * Creates a SwappableComponent that can be used to render the component, optionally overridden by the app. * * @public */ declare function createSwappableComponent(options: CreateSwappableComponentOptions): { (props: TExternalComponentProps): JSX.Element | null; ref: SwappableComponentRef; }; /** * React hook providing access to the current {@link AppNode}. * * @public * @remarks * * This hook will return the {@link AppNode} for the closest extension. This * relies on the extension using the {@link (ExtensionBoundary:function)} component in its * implementation, which is included by default for all common blueprints. * * If the current component is not inside an {@link (ExtensionBoundary:function)}, it will * return `undefined`. */ declare function useAppNode(): AppNode | undefined; /** @public */ type ProgressProps = {}; /** @public */ type NotFoundErrorPageProps = { children?: ReactNode; }; /** @public */ type ErrorDisplayProps = { plugin?: FrontendPlugin; error: Error; resetError: () => void; }; /** * @public */ declare const Progress: { (props: ProgressProps): JSX.Element | null; ref: _backstage_frontend_plugin_api.SwappableComponentRef; }; /** * @public */ declare const NotFoundErrorPage: { (props: NotFoundErrorPageProps): JSX.Element | null; ref: _backstage_frontend_plugin_api.SwappableComponentRef; }; /** * @public */ declare const ErrorDisplay: { (props: ErrorDisplayProps): JSX.Element | null; ref: _backstage_frontend_plugin_api.SwappableComponentRef; }; /** * Tab configuration for page navigation * @public */ interface PageTab { id: string; label: string; icon?: IconElement; href: string; } /** * Props for the PageLayout component * @public */ interface PageLayoutProps { title?: string; icon?: IconElement; noHeader?: boolean; headerActions?: Array; tabs?: PageTab[]; children?: ReactNode; } /** * Swappable component for laying out page content with header and navigation. * The default implementation uses plain HTML elements. * Apps can override this with a custom implementation (e.g., using \@backstage/ui). * * @public */ declare const PageLayout: { (props: PageLayoutProps): JSX.Element | null; ref: _backstage_frontend_plugin_api.SwappableComponentRef; }; /** * API for looking up components based on component refs. * * @public */ interface SwappableComponentsApi { getComponent(ref: SwappableComponentRef): (props: TInnerComponentProps) => JSX.Element | null; } /** * The `ApiRef` of {@link SwappableComponentsApi}. * * @public */ declare const swappableComponentsApiRef: _backstage_frontend_plugin_api.ApiRef; /** * The Config API is used to provide a mechanism to access the * runtime configuration of the system. * * @public */ type ConfigApi = Config; /** * The {@link ApiRef} of {@link ConfigApi}. * * @public */ declare const configApiRef: ApiRef; /** * The discovery API is used to provide a mechanism for plugins to * discover the endpoint to use to talk to their backend counterpart. * * @remarks * * The purpose of the discovery API is to allow for many different deployment * setups and routing methods through a central configuration, instead * of letting each individual plugin manage that configuration. * * Implementations of the discovery API can be a simple as a URL pattern * using the pluginId, but could also have overrides for individual plugins, * or query a separate discovery service. * * @public */ type DiscoveryApi = { /** * Returns the HTTP base backend URL for a given plugin, without a trailing slash. * * This method must always be called just before making a request, as opposed to * fetching the URL when constructing an API client. That is to ensure that more * flexible routing patterns can be supported. * * For example, asking for the URL for `auth` may return something * like `https://backstage.example.com/api/auth` */ getBaseUrl(pluginId: string): Promise; }; /** * The {@link ApiRef} of {@link DiscoveryApi}. * * @public */ declare const discoveryApiRef: ApiRef; /** * Mirrors the JavaScript Error class, for the purpose of * providing documentation and optional fields. * * @public */ type ErrorApiError = { name: string; message: string; stack?: string; }; /** * Provides additional information about an error that was posted to the application. * * @public */ type ErrorApiErrorContext = { /** * If set to true, this error should not be displayed to the user. * * Hidden errors are typically not displayed in the UI, but the ErrorApi * implementation may still report them to error tracking services * or other utilities that care about all errors. * * @defaultValue false */ hidden?: boolean; }; /** * The error API is used to report errors to the app, and display them to the user. * * @remarks * * Plugins can use this API as a method of displaying errors to the user, but also * to report errors for collection by error reporting services. * * If an error can be displayed inline, e.g. as feedback in a form, that should be * preferred over relying on this API to display the error. The main use of this API * for displaying errors should be for asynchronous errors, such as a failing background process. * * Even if an error is displayed inline, it should still be reported through this API * if it would be useful to collect or log it for debugging purposes, but with * the hidden flag set. For example, an error arising from form field validation * should probably not be reported, while a failed REST call would be useful to report. * * @public */ type ErrorApi = { /** * Post an error for handling by the application. */ post(error: ErrorApiError, context?: ErrorApiErrorContext): void; /** * Observe errors posted by other parts of the application. */ error$(): Observable<{ error: ErrorApiError; context?: ErrorApiErrorContext; }>; }; /** * The {@link ApiRef} of {@link ErrorApi}. * * @public */ declare const errorApiRef: ApiRef; /** * Feature flag descriptor. * * @public */ type FeatureFlag = { name: string; pluginId: string; description?: string; }; /** * Enum representing the state of a feature flag (inactive/active). * * @public */ declare const FeatureFlagState: { /** * Feature flag inactive (disabled). */ readonly None: 0; /** * Feature flag active (enabled). */ readonly Active: 1; }; /** * @public */ type FeatureFlagState = (typeof FeatureFlagState)[keyof typeof FeatureFlagState]; /** * @public */ declare namespace FeatureFlagState { type None = typeof FeatureFlagState.None; type Active = typeof FeatureFlagState.Active; } /** * Options to use when saving feature flags. * * @public */ type FeatureFlagsSaveOptions = { /** * The new feature flag states to save. */ states: Record; /** * Whether the saves states should be merged into the existing ones, or replace them. * * Defaults to false. */ merge?: boolean; }; /** * The feature flags API is used to toggle functionality to users across plugins and Backstage. * * @remarks * * Plugins can use this API to register feature flags that they have available * for users to enable/disable, and this API will centralize the current user's * state of which feature flags they would like to enable. * * This is ideal for Backstage plugins, as well as your own App, to trial incomplete * or unstable upcoming features. Although there will be a common interface for users * to enable and disable feature flags, this API acts as another way to enable/disable. * * @public */ interface FeatureFlagsApi { /** * Registers a new feature flag. Once a feature flag has been registered it * can be toggled by users, and read back to enable or disable features. */ registerFlag(flag: FeatureFlag): void; /** * Get a list of all registered flags. */ getRegisteredFlags(): FeatureFlag[]; /** * Whether the feature flag with the given name is currently activated for the user. */ isActive(name: string): boolean; /** * Save the user's choice of feature flag states. */ save(options: FeatureFlagsSaveOptions): void; } /** * The {@link ApiRef} of {@link FeatureFlagsApi}. * * @public */ declare const featureFlagsApiRef: ApiRef; /** * A wrapper for the fetch API, that has additional behaviors such as the * ability to automatically inject auth information where necessary. * * @public */ type FetchApi = { /** * The `fetch` implementation. */ fetch: typeof fetch; }; /** * The {@link ApiRef} of {@link FetchApi}. * * @remarks * * This is a wrapper for the fetch API, that has additional behaviors such as * the ability to automatically inject auth information where necessary. * * Note that the default behavior of this API (unless overridden by your org), * is to require that the user is already signed in so that it has auth * information to inject. Therefore, using the default implementation of this * utility API e.g. on the `SignInPage` or similar, would cause issues. In * special circumstances like those, you can use the regular system `fetch` * instead. * * @public */ declare const fetchApiRef: ApiRef; /** * API for accessing app icons. * * @public */ interface IconsApi { /** * Look up an icon element by key. */ icon(key: string): IconElement | undefined; /** * @deprecated Use {@link IconsApi.icon} instead. */ getIcon(key: string): IconComponent | undefined; listIconKeys(): string[]; } /** * The `ApiRef` of {@link IconsApi}. * * @public */ declare const iconsApiRef: _backstage_frontend_plugin_api.ApiRef; /** * The Identity API used to identify and get information about the signed in user. * * @public */ type IdentityApi = { /** * The profile of the signed in user. */ getProfileInfo(): Promise; /** * User identity information within Backstage. */ getBackstageIdentity(): Promise; /** * Provides credentials in the form of a token which proves the identity of the signed in user. * * The token will be undefined if the signed in user does not have a verified * identity, such as a demo user or mocked user for e2e tests. */ getCredentials(): Promise<{ token?: string; }>; /** * Sign out the current user */ signOut(): Promise; }; /** * The {@link ApiRef} of {@link IdentityApi}. * * @public */ declare const identityApiRef: ApiRef; /** * A handle for an open dialog that can be used to interact with it. * * @remarks * * Dialogs can be opened using either {@link DialogApi.show} or {@link DialogApi.showModal}. * * @public */ interface DialogApiDialog { /** * Closes the dialog with that provided result. * * @remarks * * If the dialog is a modal dialog a result must always be provided. If it's a regular dialog then passing a result is optional. */ close(...args: undefined extends TResult ? [result?: TResult] : [result: TResult]): void; /** * Replaces the content of the dialog with the provided element or component, causing it to be rerenedered. */ update(elementOrComponent: React.JSX.Element | ((props: { dialog: DialogApiDialog; }) => JSX.Element)): void; /** * Wait until the dialog is closed and return the result. * * @remarks * * If the dialog is a modal dialog a result will always be returned. If it's a regular dialog then the result may be `undefined`. */ result(): Promise; } /** * A Utility API for showing dialogs that render in the React tree and return a result. * * @public */ interface DialogApi { /** * Opens a modal dialog and returns a handle to it. * * @remarks * * This dialog can be closed by calling the `close` method on the returned handle, optionally providing a result. * The dialog can also be closed by the user by clicking the backdrop or pressing the escape key. * * If the dialog is closed without a result, the result will be `undefined`. * * @example * * ### Example with inline dialog content * ```tsx * const dialog = dialogApi.show( * * Are you sure? * * * * * * ); * const result = await dialog.result(); * ``` * * @example * * ### Example with separate dialog component * ```tsx * function CustomDialog({ dialog }: { dialog: DialogApiDialog }) { * return ( * * Are you sure? * * * * * * ) * } * const result = await dialogApi.show(CustomDialog).result(); * ``` * * @param elementOrComponent - The element or component to render in the dialog. If a component is provided, it will be provided with a `dialog` prop that contains the dialog handle. * @public */ show(elementOrComponent: JSX.Element | ((props: { dialog: DialogApiDialog; }) => JSX.Element)): DialogApiDialog; /** * Opens a modal dialog and returns a handle to it. * * @remarks * * This dialog can not be closed in any other way than calling the `close` method on the returned handle and providing a result. * * @example * * ### Example with inline dialog content * ```tsx * const dialog = dialogApi.showModal( * * Are you sure? * * * * * * ); * const result = await dialog.result(); * ``` * * @example * * ### Example with separate dialog component * ```tsx * function CustomDialog({ dialog }: { dialog: DialogApiDialog }) { * return ( * * Are you sure? * * * * * * ) * } * const result = await dialogApi.showModal(CustomDialog).result(); * ``` * * @param elementOrComponent - The element or component to render in the dialog. If a component is provided, it will be provided with a `dialog` prop that contains the dialog handle. * @public */ showModal(elementOrComponent: JSX.Element | ((props: { dialog: DialogApiDialog; }) => JSX.Element)): DialogApiDialog; } /** * The `ApiRef` of {@link DialogApi}. * * @public */ declare const dialogApiRef: _backstage_frontend_plugin_api.ApiRef; /** * Describes how to handle auth requests. Both how to show them to the user, and what to do when * the user accesses the auth request. * * @public */ type OAuthRequesterOptions = { /** * Information about the auth provider, which will be forwarded to auth requests. */ provider: AuthProviderInfo; /** * Implementation of the auth flow, which will be called synchronously when * trigger() is called on an auth requests. */ onAuthRequest(scopes: Set): Promise; }; /** * Function used to trigger new auth requests for a set of scopes. * * @remarks * * The returned promise will resolve to the same value returned by the onAuthRequest in the * {@link OAuthRequesterOptions}. Or rejected, if the request is rejected. * * This function can be called multiple times before the promise resolves. All calls * will be merged into one request, and the scopes forwarded to the onAuthRequest will be the * union of all requested scopes. * * @public */ type OAuthRequester = (scopes: Set) => Promise; /** * An pending auth request for a single auth provider. The request will remain in this pending * state until either reject() or trigger() is called. * * @remarks * * Any new requests for the same provider are merged into the existing pending request, meaning * there will only ever be a single pending request for a given provider. * * @public */ type PendingOAuthRequest = { /** * Information about the auth provider, as given in the AuthRequesterOptions */ provider: AuthProviderInfo; /** * Rejects the request, causing all pending AuthRequester calls to fail with "RejectedError". */ reject(): void; /** * Trigger the auth request to continue the auth flow, by for example showing a popup. * * Synchronously calls onAuthRequest with all scope currently in the request. */ trigger(): Promise; }; /** * Provides helpers for implemented OAuth login flows within Backstage. * * @public */ type OAuthRequestApi = { /** * A utility for showing login popups or similar things, and merging together multiple requests for * different scopes into one request that includes all scopes. * * The passed in options provide information about the login provider, and how to handle auth requests. * * The returned AuthRequester function is used to request login with new scopes. These requests * are merged together and forwarded to the auth handler, as soon as a consumer of auth requests * triggers an auth flow. * * See AuthRequesterOptions, AuthRequester, and handleAuthRequests for more info. */ createAuthRequester(options: OAuthRequesterOptions): OAuthRequester; /** * Observers pending auth requests. The returned observable will emit all * current active auth request, at most one for each created auth requester. * * Each request has its own info about the login provider, forwarded from the auth requester options. * * Depending on user interaction, the request should either be rejected, or used to trigger the auth handler. * If the request is rejected, all pending AuthRequester calls will fail with a "RejectedError". * If a auth is triggered, and the auth handler resolves successfully, then all currently pending * AuthRequester calls will resolve to the value returned by the onAuthRequest call. */ authRequest$(): Observable; }; /** * The {@link ApiRef} of {@link OAuthRequestApi}. * * @public */ declare const oauthRequestApiRef: ApiRef; /** * TS magic for handling route parameters. * * @remarks * * The extra TS magic here is to require a single params argument if the RouteRef * had at least one param defined, but require 0 arguments if there are no params defined. * Without this we'd have to pass in empty object to all parameter-less RouteRefs * just to make TypeScript happy, or we would have to make the argument optional in * which case you might forget to pass it in when it is actually required. * * @public */ type RouteFunc = (...[params]: TParams extends undefined ? readonly [] : readonly [params: TParams]) => string; /** * @public */ interface RouteResolutionApi { resolve(anyRouteRef: RouteRef | SubRouteRef | ExternalRouteRef, options?: { /** * An absolute path to use as a starting point when resolving the route. * If no path is provided the route will be resolved from the root of the app. */ sourcePath?: string; }): RouteFunc | undefined; } /** * The `ApiRef` of {@link RouteResolutionApi}. * * @public */ declare const routeResolutionApiRef: _backstage_frontend_plugin_api.ApiRef; /** * A snapshot in time of the current known value of a storage key. * * @public */ type StorageValueSnapshot = { key: string; presence: 'unknown' | 'absent'; value?: undefined; } | { key: string; presence: 'present'; value: TValue; }; /** * Provides a key-value persistence API. * * @public */ interface StorageApi { /** * Create a bucket to store data in. * * @param name - Namespace for the storage to be stored under, * will inherit previous namespaces too */ forBucket(name: string): StorageApi; /** * Remove persistent data. * * @param key - Unique key associated with the data. */ remove(key: string): Promise; /** * Save persistent data, and emit messages to anyone that is using * {@link StorageApi.observe$} for this key. * * @param key - Unique key associated with the data. * @param data - The data to be stored under the key. */ set(key: string, data: T): Promise; /** * Observe the value over time for a particular key in the current bucket. * * @remarks * * The observable will only emit values when the value changes in the underlying * storage, although multiple values with the same shape may be emitted in a row. * * If a {@link StorageApi.snapshot} of a key is retrieved and the presence is * `'unknown'`, then you are guaranteed to receive a snapshot with a known * presence, as long as you observe the key within the same tick. * * Since the emitted values are shared across all subscribers, it is important * not to mutate the returned values. The values may be frozen as a precaution. * * @param key - Unique key associated with the data */ observe$(key: string): Observable>; /** * Returns an immediate snapshot value for the given key, if possible. * * @remarks * * Combine with {@link StorageApi.observe$} to get notified of value changes. * * Note that this method is synchronous, and some underlying storages may be * unable to retrieve a value using this method - the result may or may not * consistently have a presence of 'unknown'. Use {@link StorageApi.observe$} * to be sure to receive an actual value eventually. */ snapshot(key: string): StorageValueSnapshot; } /** * The {@link ApiRef} of {@link StorageApi}. * * @public */ declare const storageApiRef: ApiRef; /** * Represents an event worth tracking in an analytics system that could inform * how users of a Backstage instance are using its features. * * @public */ type AnalyticsEvent = { /** * A string that identifies the event being tracked by the type of action the * event represents. Be careful not to encode extra metadata in this string * that should instead be placed in the Analytics Context or attributes. * Examples include: * * - view * - click * - filter * - search * - hover * - scroll */ action: string; /** * A string that uniquely identifies the object that the action is being * taken on. Examples include: * * - The path of the page viewed * - The url of the link clicked * - The value that was filtered by * - The text that was searched for */ subject: string; /** * An optional numeric value relevant to the event that could be aggregated * by analytics tools. Examples include: * * - The index or position of the clicked element in an ordered list * - The percentage of an element that has been scrolled through * - The amount of time that has elapsed since a fixed point * - A satisfaction score on a fixed scale */ value?: number; /** * Optional, additional attributes (representing dimensions or metrics) * specific to the event that could be forwarded on to analytics systems. */ attributes?: AnalyticsEventAttributes; /** * Contextual metadata relating to where the event was captured and by whom. * This could include information about the route, plugin, or extension in * which an event was captured. */ context: AnalyticsContextValue; }; /** * A structure allowing other arbitrary metadata to be provided by analytics * event emitters. * * @public */ type AnalyticsEventAttributes = { [attribute in string]: string | boolean | number; }; /** * Represents a tracker with methods that can be called to track events in a * configured analytics service. * * @public */ type AnalyticsTracker = { captureEvent: (action: string, subject: string, options?: { value?: number; attributes?: AnalyticsEventAttributes; }) => void; }; /** * Analytics implementations are used to track user behavior in a Backstage * instance. * * @remarks * * To instrument your App or Plugin, retrieve an analytics tracker using the * `useAnalytics()` hook. This will return a pre-configured `AnalyticsTracker` * with relevant methods for instrumentation. * * @public */ type AnalyticsImplementation = { /** * Primary event handler responsible for compiling and forwarding events to * an analytics system. */ captureEvent(event: AnalyticsEvent): void; }; /** * The Analytics API is used to track user behavior in a Backstage instance. * * @remarks * * To instrument your App or Plugin, retrieve an analytics tracker using the * useAnalytics() hook. This will return a pre-configured AnalyticsTracker * with relevant methods for instrumentation. * * @public */ type AnalyticsApi = { /** * Primary event handler responsible for compiling and forwarding events to * an analytics system. */ captureEvent(event: AnalyticsEvent): void; }; /** * The API reference of {@link AnalyticsApi}. * * @remarks * * To define a concrete Analytics Implementation, use * {@link AnalyticsImplementationBlueprint} instead. * * @public */ declare const analyticsApiRef: ApiRef; /** @public */ interface TranslationRef { $$type: '@backstage/TranslationRef'; id: TId; T: TMessages; } /** @ignore */ type AnyNestedMessages = { [key in string]: AnyNestedMessages | string; }; /** * Flattens a nested message declaration into a flat object with dot-separated keys. * * @ignore */ type FlattenedMessages = { [TKey in keyof TMessages]: (_: TMessages[TKey] extends infer TValue ? TValue extends AnyNestedMessages ? FlattenedMessages extends infer TNested ? { [TNestedKey in keyof TNested as `${TKey & string}.${TNestedKey & string}`]: TNested[TNestedKey]; } : never : { [_ in TKey]: TValue; } : never) => void; }[keyof TMessages] extends (_: infer TIntersection) => void ? { readonly [TExpandKey in keyof TIntersection]: TIntersection[TExpandKey]; } : never; /** @public */ interface TranslationRefOptions Promise<{ default: { [key in keyof FlattenedMessages]: string | null; }; }>; }> { id: TId; messages: TNestedMessages; translations?: TTranslations; } /** @public */ declare function createTranslationRef Promise<{ default: { [key in keyof FlattenedMessages]: string | null; }; }>; }>(config: TranslationRefOptions): TranslationRef>; /** * Represents a collection of messages to be provided for a given translation ref. * * @public * @remarks * * This collection of messages can either be used directly as an override for the * default messages, or it can be used to provide translations for a language by * by being referenced by a {@link TranslationResource}. */ interface TranslationMessages { $$type: '@backstage/TranslationMessages'; /** The ID of the translation ref that these messages are for */ id: TId; /** Whether or not these messages override all known messages */ full: TFull; /** The messages provided for the given translation ref */ messages: TMessages; } /** * Options for {@link createTranslationMessages}. * * @public */ interface TranslationMessagesOptions { ref: TranslationRef; full?: TFull; messages: false extends TFull ? { [key in keyof TMessages]?: string | null; } : { [key in keyof TMessages]: string | null; }; } /** * Creates a collection of messages for a given translation ref. * * @public */ declare function createTranslationMessages(options: TranslationMessagesOptions): TranslationMessages; /** @public */ interface TranslationResource { $$type: '@backstage/TranslationResource'; id: TId; } /** @public */ interface TranslationResourceOptions Promise<{ default: TranslationMessages | { [key in keyof TMessages]: string | null; }; }>; }> { ref: TranslationRef; translations: TTranslations; } /** @public */ declare function createTranslationResource Promise<{ default: TranslationMessages | { [key in keyof TMessages]: string | null; }; }>; }>(options: TranslationResourceOptions): TranslationResource; /** @public */ declare const useTranslationRef: (translationRef: TranslationRef) => { t: TranslationFunction; }; /** * Base translation options. * * @alpha */ interface BaseOptions { interpolation?: { /** Whether to HTML escape provided values, defaults to false */ escapeValue?: boolean; }; } /** * All pluralization suffixes supported by i18next * * @ignore */ type TranslationPlural = 'zero' | 'one' | 'two' | 'few' | 'many' | 'other'; /** * A mapping of i18n formatting types to their corresponding types and options. * @ignore */ type I18nextFormatMap = { number: { type: number; options: Intl.NumberFormatOptions; }; currency: { type: number; options: Intl.NumberFormatOptions; }; datetime: { type: Date; options: Intl.DateTimeFormatOptions; }; relativetime: { type: number; options: { range?: Intl.RelativeTimeFormatUnit; } & Intl.RelativeTimeFormatOptions; }; list: { type: string[]; options: Intl.ListFormatOptions; }; }; /** * Extracts all pluralized keys from the message map. * * @example * ``` * { foo: 'foo', bar_one: 'bar', bar_other: 'bars' } -> 'bar' * ``` * * @ignore */ type PluralKeys = { [Key in keyof TMessages]: Key extends `${infer K}_${TranslationPlural}` ? K : never; }[keyof TMessages]; /** * Collapses a message map into normalized keys with union values. * * @example * ``` * { foo_one: 'foo', foo_other: 'foos' } -> { foo: 'foo' | 'foos' } * ``` * * @ignore */ type CollapsedMessages = { [key in keyof TMessages as key extends `${infer K}_${TranslationPlural}` ? K : key]: TMessages[key]; }; /** * Trim away whitespace * * @ignore */ type Trim = T extends ` ${infer U}` ? Trim : T extends `${infer U} ` ? Trim : T; /** * Extracts the key and format from a replacement string. * * @example * ``` * 'foo, number' -> { foo: number }, 'foo' -> { foo: undefined } * ``` */ type ExtractFormat = Replacement extends `${infer Key},${infer FullFormat}` ? { [key in Trim]: Lowercase>; } : { [key in Trim]: undefined; }; /** * Expand the keys in a flat map to nested objects. * * @example * ``` * { 'a.b': 'foo', 'a.c': 'bar' } -> { a: { b: 'foo', c: 'bar' } * ``` * * @ignore */ type ExpandKeys = { [Key in keyof TMap as Key extends `${infer Prefix}.${string}` ? Prefix : Key]: Key extends `${string}.${infer Rest}` ? ExpandKeys<{ [key in Rest]: TMap[Key]; }> : TMap[Key]; }; /** * Extracts all option keys and their format from a message string. * * @example * ``` * 'foo {{bar}} {{baz, number}}' -> { 'bar': undefined, 'baz': 'number' } * ``` * * @ignore */ type ReplaceFormatsFromMessage = TMessage extends `${string}{{${infer Replacement}}}${infer Tail}` ? ExpandKeys> & ReplaceFormatsFromMessage : {}; /** * Generates the replace options structure * * @ignore */ type ReplaceOptionsFromFormats = { [Key in keyof TFormats]: TFormats[Key] extends keyof I18nextFormatMap ? I18nextFormatMap[TFormats[Key]]['type'] : TFormats[Key] extends {} ? Expand> : TValueType; }; /** * Generates the formatParams options structure * * @ignore */ type ReplaceFormatParamsFromFormats = { [Key in keyof TFormats]?: TFormats[Key] extends keyof I18nextFormatMap ? I18nextFormatMap[TFormats[Key]]['options'] : TFormats[Key] extends {} ? Expand> : undefined; }; /** * Extracts all nesting keys from a message string. * * @example * ``` * 'foo $t(bar) $t(baz)' -> 'bar' | 'baz' * ``` * * @ignore */ type NestingKeysFromMessage = TMessage extends `${string}$t(${infer Key})${infer Tail}` ? Trim | NestingKeysFromMessage : never; /** * Find all referenced keys, given a starting key and the full set of messages. * * This will only discover keys up to 3 levels deep. * * @example * ``` * <'x', { x: '$t(y) $t(z)', y: 'y', z: '$t(w)', w: 'w', foo: 'foo' }> -> 'x' | 'y' | 'z' | 'w' * ``` * * @ignore */ type NestedMessageKeys = TKey | NestedMessageKeys2, TMessages>; type NestedMessageKeys2 = TKey | NestedMessageKeys3, TMessages>; type NestedMessageKeys3 = TKey | NestingKeysFromMessage; /** * Converts a union type to an intersection type. * * @example * ``` * { foo: 'foo' } | { bar: 'bar' } -> { foo: 'foo' } & { bar: 'bar' } * ``` * * @ignore */ type UnionToIntersection = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never; /** * Collects different types of options into a single object * * @ignore */ type CollectOptions = TCount & (keyof Omit extends never ? {} : (Expand, 'count'>> | { replace: Expand, 'count'>>; }) & { formatParams?: Expand>; }); /** * Helper type to only require options argument if needed * * @ignore */ type OptionArgs = keyof TOptions extends never ? [options?: Expand] : [options: Expand]; /** * @ignore */ type TranslationFunctionOptions = OptionArgs>>, TValueType>>>; /** @public */ type TranslationFunction = CollapsedMessages extends infer IMessages extends { [key in string]: string; } ? { /** * A translation function that returns a string. */ (key: TKey, ...[args]: TranslationFunctionOptions, PluralKeys, IMessages, string>): IMessages[TKey]; /** * A translation function where at least one JSX.Element has been * provided as an interpolation value, and will therefore return a * JSX.Element. */ (key: TKey, ...[args]: TranslationFunctionOptions, PluralKeys, IMessages, string | JSX$1.Element>): JSX$1.Element; } : never; /** @public */ type TranslationSnapshot = { ready: false; } | { ready: true; t: TranslationFunction; }; /** @public */ type TranslationApi = { getTranslation(translationRef: TranslationRef): TranslationSnapshot; translation$(translationRef: TranslationRef): Observable>; }; /** * @public */ declare const translationApiRef: ApiRef; /** * API for retrieving plugin-scoped header actions. * * @remarks * * Header actions are provided via * {@link @backstage/frontend-plugin-api#PluginHeaderActionBlueprint} * and automatically scoped to the providing plugin. * * @public */ type PluginHeaderActionsApi = { /** * Returns the header actions for a given plugin. */ getPluginHeaderActions(pluginId: string): Array; }; /** * The `ApiRef` of {@link PluginHeaderActionsApi}. * * @public */ declare const pluginHeaderActionsApiRef: _backstage_frontend_plugin_api.ApiRef; /** * Gets a pre-configured analytics tracker. * * @public */ declare function useAnalytics(): AnalyticsTracker; /** @public */ type AnalyticsImplementationFactory = { deps: TypesToApiRefs; factory(deps: Deps): AnalyticsImplementation; }; /** * Creates analytics implementations. * * @public */ declare const AnalyticsImplementationBlueprint: _backstage_frontend_plugin_api.ExtensionBlueprint<{ kind: "analytics"; params: (params: AnalyticsImplementationFactory) => _backstage_frontend_plugin_api.ExtensionBlueprintParams>; output: _backstage_frontend_plugin_api.ExtensionDataRef, "core.analytics.factory", {}>; inputs: {}; config: {}; configInput: {}; dataRefs: { factory: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef, "core.analytics.factory", {}>; }; }>; /** * Creates utility API extensions. * * @public */ declare const ApiBlueprint: _backstage_frontend_plugin_api.ExtensionBlueprint<{ kind: "api"; params: (params: ApiFactory) => _backstage_frontend_plugin_api.ExtensionBlueprintParams; output: _backstage_frontend_plugin_api.ExtensionDataRef; inputs: {}; config: {}; configInput: {}; dataRefs: { factory: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef; }; }>; /** * Creates extensions that render a React element at the app root, outside of * the app layout. This is useful for example for shared popups and similar. * * @public */ declare const AppRootElementBlueprint: _backstage_frontend_plugin_api.ExtensionBlueprint<{ kind: "app-root-element"; params: { element: JSX.Element; }; output: _backstage_frontend_plugin_api.ExtensionDataRef; inputs: {}; config: {}; configInput: {}; dataRefs: never; }>; /** * Creates extensions that make up the items of the nav bar. * * @public */ declare const NavItemBlueprint: _backstage_frontend_plugin_api.ExtensionBlueprint<{ kind: "nav-item"; params: { title: string; icon: IconComponent; routeRef: RouteRef; }; output: _backstage_frontend_plugin_api.ExtensionDataRef<{ title: string; icon: IconComponent; routeRef: RouteRef; }, "core.nav-item.target", {}>; inputs: {}; config: {}; configInput: {}; dataRefs: { target: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<{ title: string; icon: IconComponent; routeRef: RouteRef; }, "core.nav-item.target", {}>; }; }>; /** * Creates extensions that are routable React page components. * * @public */ declare const PageBlueprint: _backstage_frontend_plugin_api.ExtensionBlueprint<{ kind: "page"; params: { /** * @deprecated Use the `path` param instead. */ defaultPath?: [Error: `Use the 'path' param instead`]; path: string; title?: string; icon?: IconElement; loader?: () => Promise; routeRef?: RouteRef; /** * Hide the default plugin page header, making the page fill up all available space. */ noHeader?: boolean; }; output: _backstage_frontend_plugin_api.ExtensionDataRef | _backstage_frontend_plugin_api.ExtensionDataRef, "core.routing.ref", { optional: true; }> | _backstage_frontend_plugin_api.ExtensionDataRef | _backstage_frontend_plugin_api.ExtensionDataRef | _backstage_frontend_plugin_api.ExtensionDataRef; inputs: { pages: _backstage_frontend_plugin_api.ExtensionInput<_backstage_frontend_plugin_api.ConfigurableExtensionDataRef | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef, "core.routing.ref", { optional: true; }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef, { singleton: false; optional: false; internal: false; }>; }; config: { path: string | undefined; title: string | undefined; }; configInput: { title?: string | undefined; path?: string | undefined; }; dataRefs: never; }>; /** * Creates extensions that are sub-page React components attached to a parent page. * Sub-pages are rendered as tabs within the parent page's header. * * @public * @example * ```tsx * const overviewRouteRef = createRouteRef(); * * const mySubPage = SubPageBlueprint.make({ * attachTo: { id: 'page:my-plugin', input: 'pages' }, * name: 'overview', * params: { * path: 'overview', * title: 'Overview', * routeRef: overviewRouteRef, * loader: () => import('./components/Overview').then(m => ), * }, * }); * ``` */ declare const SubPageBlueprint: _backstage_frontend_plugin_api.ExtensionBlueprint<{ kind: "sub-page"; params: { /** * The path for this sub-page, relative to the parent page. Must **not** start with '/'. * * @example 'overview', 'settings', 'details' */ path: string; /** * The title displayed in the tab for this sub-page. */ title: string; /** * Optional icon for this sub-page, displayed in the tab. */ icon?: IconElement; /** * A function that returns a promise resolving to the React element to render. * This enables lazy loading of the sub-page content. */ loader: () => Promise; /** * Optional route reference for this sub-page. */ routeRef?: RouteRef; }; output: _backstage_frontend_plugin_api.ExtensionDataRef | _backstage_frontend_plugin_api.ExtensionDataRef, "core.routing.ref", { optional: true; }> | _backstage_frontend_plugin_api.ExtensionDataRef | _backstage_frontend_plugin_api.ExtensionDataRef | _backstage_frontend_plugin_api.ExtensionDataRef; inputs: {}; config: { path: string | undefined; title: string | undefined; }; configInput: { title?: string | undefined; path?: string | undefined; }; dataRefs: never; }>; /** * Creates extensions that provide plugin-scoped header actions. * * @remarks * * These actions are automatically scoped to the plugin that provides them * and will appear in the header of all pages belonging to that plugin. * * @public */ declare const PluginHeaderActionBlueprint: _backstage_frontend_plugin_api.ExtensionBlueprint<{ kind: "plugin-header-action"; params: (params: { loader: () => Promise; }) => _backstage_frontend_plugin_api.ExtensionBlueprintParams<{ loader: () => Promise; }>; output: _backstage_frontend_plugin_api.ExtensionDataRef; inputs: {}; config: {}; configInput: {}; dataRefs: never; }>; export { AnalyticsContext, AnalyticsImplementationBlueprint, ApiBlueprint, AppRootElementBlueprint, ErrorDisplay, ExtensionBoundary, FeatureFlagState, NavItemBlueprint, NotFoundErrorPage, PageBlueprint, PageLayout, PluginHeaderActionBlueprint, Progress, SessionState, SubPageBlueprint, alertApiRef, analyticsApiRef, appLanguageApiRef, appThemeApiRef, appTreeApiRef, atlassianAuthApiRef, bitbucketAuthApiRef, bitbucketServerAuthApiRef, configApiRef, coreExtensionData, createApiFactory, createApiRef, createExtension, createExtensionBlueprint, createExtensionBlueprintParams, createExtensionDataRef, createExtensionInput, createExternalRouteRef, createFrontendFeatureLoader, createFrontendModule, createFrontendPlugin, createRouteRef, createSubRouteRef, createSwappableComponent, createTranslationMessages, createTranslationRef, createTranslationResource, dialogApiRef, discoveryApiRef, errorApiRef, featureFlagsApiRef, fetchApiRef, githubAuthApiRef, gitlabAuthApiRef, googleAuthApiRef, iconsApiRef, identityApiRef, microsoftAuthApiRef, oauthRequestApiRef, oktaAuthApiRef, oneloginAuthApiRef, openshiftAuthApiRef, pluginHeaderActionsApiRef, routeResolutionApiRef, storageApiRef, swappableComponentsApiRef, translationApiRef, useAnalytics, useApi, useApiHolder, useAppNode, useRouteRef, useRouteRefParams, useTranslationRef, vmwareCloudAuthApiRef, withApis }; export type { AlertApi, AlertMessage, AnalyticsApi, AnalyticsContextValue, AnalyticsEvent, AnalyticsEventAttributes, AnalyticsImplementation, AnalyticsImplementationFactory, AnalyticsTracker, AnyApiFactory, AnyApiRef, AnyExtensionDataRef, AnyRouteRefParams, ApiFactory, ApiHolder, ApiRef, ApiRefConfig, AppLanguageApi, AppNode, AppNodeEdges, AppNodeInstance, AppNodeSpec, AppTheme, AppThemeApi, AppTree, AppTreeApi, AuthProviderInfo, AuthRequestOptions, BackstageIdentityApi, BackstageIdentityResponse, BackstageUserIdentity, ConfigApi, ConfigurableExtensionDataRef, CreateExtensionBlueprintOptions, CreateExtensionOptions, CreateFrontendFeatureLoaderOptions, CreateFrontendModuleOptions, CreateSwappableComponentOptions, DialogApi, DialogApiDialog, DiscoveryApi, ErrorApi, ErrorApiError, ErrorApiErrorContext, ErrorDisplayProps, Extension, ExtensionAttachTo, ExtensionAttachToSpec, ExtensionBlueprint, ExtensionBlueprintDefineParams, ExtensionBlueprintParameters, ExtensionBlueprintParams, ExtensionBoundaryProps, ExtensionDataContainer, ExtensionDataRef, ExtensionDataRefToValue, ExtensionDataValue, ExtensionDefinition, ExtensionDefinitionAttachTo, ExtensionDefinitionParameters, ExtensionFactoryMiddleware, ExtensionInput, ExternalRouteRef, FeatureFlag, FeatureFlagConfig, FeatureFlagsApi, FeatureFlagsSaveOptions, FetchApi, FrontendFeature, FrontendFeatureLoader, FrontendModule, FrontendPlugin, FrontendPluginInfo, FrontendPluginInfoOptions, IconComponent, IconElement, IconsApi, IdentityApi, NotFoundErrorPageProps, OAuthApi, OAuthRequestApi, OAuthRequester, OAuthRequesterOptions, OAuthScope, OpenIdConnectApi, OverridableExtensionDefinition, OverridableFrontendPlugin, PageLayoutProps, PageTab, PendingOAuthRequest, PluginHeaderActionsApi, PluginOptions, PortableSchema, ProfileInfo, ProfileInfoApi, ProgressProps, ResolvedExtensionInput, ResolvedExtensionInputs, RouteFunc, RouteRef, RouteResolutionApi, SessionApi, StorageApi, StorageValueSnapshot, SubRouteRef, SwappableComponentRef, SwappableComponentsApi, TranslationApi, TranslationFunction, TranslationMessages, TranslationMessagesOptions, TranslationRef, TranslationRefOptions, TranslationResource, TranslationResourceOptions, TranslationSnapshot, TypesToApiRefs };