import { ExternalRouteRef, RouteRef, SubRouteRef, FrontendPluginInfo, FrontendPlugin, AppNode, FrontendFeature, ExtensionFactoryMiddleware, AppTree } from '@backstage/frontend-plugin-api'; import { ConfigApi, ApiHolder } from '@backstage/core-plugin-api'; import { JsonObject } from '@backstage/types'; /** * Extracts a union of the keys in a map whose value extends the given type * * @ignore */ type KeysWithType = { [key in keyof Obj]: Obj[key] extends Type ? key : never; }[keyof Obj]; /** * Takes a map Map required values and makes all keys matching Keys optional * * @ignore */ type PartialKeys = Partial> & Required>; /** * Creates a map of target routes with matching parameters based on a map of external routes. * * @ignore */ type TargetRouteMap = { [name in keyof ExternalRoutes]: ExternalRoutes[name] extends ExternalRouteRef ? RouteRef | SubRouteRef | false : never; }; /** * A function that can bind from external routes of a given plugin, to concrete * routes of other plugins. See {@link @backstage/frontend-defaults#createApp}. * * @public */ type CreateAppRouteBinder = (externalRoutes: TExternalRoutes, targetRoutes: PartialKeys, KeysWithType>>) => void; /** * A function that resolves plugin info from a plugin manifest and package.json. * * @public */ type FrontendPluginInfoResolver = (ctx: { packageJson(): Promise; manifest(): Promise; defaultResolver(sources: { packageJson: JsonObject | undefined; manifest: JsonObject | undefined; }): Promise<{ info: FrontendPluginInfo; }>; }) => Promise<{ info: FrontendPluginInfo; }>; /** * @public */ type AppErrorTypes = { EXTENSION_IGNORED: { context: { plugin: FrontendPlugin; extensionId: string; }; }; INVALID_EXTENSION_CONFIG_KEY: { context: { extensionId: string; }; }; EXTENSION_INPUT_REDIRECT_CONFLICT: { context: { node: AppNode; inputName: string; }; }; EXTENSION_INPUT_DATA_IGNORED: { context: { node: AppNode; inputName: string; }; }; EXTENSION_INPUT_DATA_MISSING: { context: { node: AppNode; inputName: string; }; }; EXTENSION_ATTACHMENT_CONFLICT: { context: { node: AppNode; inputName: string; }; }; EXTENSION_ATTACHMENT_MISSING: { context: { node: AppNode; inputName: string; }; }; EXTENSION_CONFIGURATION_INVALID: { context: { node: AppNode; }; }; EXTENSION_INVALID: { context: { node: AppNode; }; }; EXTENSION_OUTPUT_CONFLICT: { context: { node: AppNode; dataRefId: string; }; }; EXTENSION_OUTPUT_MISSING: { context: { node: AppNode; dataRefId: string; }; }; EXTENSION_OUTPUT_IGNORED: { context: { node: AppNode; dataRefId: string; }; }; EXTENSION_FACTORY_ERROR: { context: { node: AppNode; }; }; API_EXTENSION_INVALID: { context: { node: AppNode; }; }; ROUTE_DUPLICATE: { context: { routeId: string; }; }; ROUTE_BINDING_INVALID_VALUE: { context: { routeId: string; }; }; ROUTE_NOT_FOUND: { context: { routeId: string; }; }; }; /** * @public */ type AppError = keyof AppErrorTypes extends infer ICode extends keyof AppErrorTypes ? ICode extends any ? { code: ICode; message: string; context: AppErrorTypes[ICode]['context']; } : never : never; /** * Options for {@link createSpecializedApp}. * * @public */ type CreateSpecializedAppOptions = { /** * The list of features to load. */ features?: FrontendFeature[]; /** * The config API implementation to use. For most normal apps, this should be * specified. * * If none is given, a new _empty_ config will be used during startup. In * later stages of the app lifecycle, the config API in the API holder will be * used. */ config?: ConfigApi; /** * Allows for the binding of plugins' external route refs within the app. */ bindRoutes?(context: { bind: CreateAppRouteBinder; }): void; /** * Advanced, more rarely used options. */ advanced?: { /** * A replacement API holder implementation to use. * * By default, a new API holder will be constructed automatically based on * the other inputs. If you pass in a custom one here, none of that * automation will take place - so you will have to take care to supply all * those APIs yourself. */ apis?: ApiHolder; /** * If set to true, the system will silently accept and move on if * encountering config for extensions that do not exist. The default is to * reject such config to help catch simple mistakes. * * This flag can be useful in some scenarios where you have a dynamic set of * extensions enabled at different times, but also increases the risk of * accidentally missing e.g. simple typos in your config. */ allowUnknownExtensionConfig?: boolean; /** * Applies one or more middleware on every extension, as they are added to * the application. * * This is an advanced use case for modifying extension data on the fly as * it gets emitted by extensions being instantiated. */ extensionFactoryMiddleware?: ExtensionFactoryMiddleware | ExtensionFactoryMiddleware[]; /** * Allows for customizing how plugin info is retrieved. */ pluginInfoResolver?: FrontendPluginInfoResolver; }; }; /** * Creates an empty app without any default features. This is a low-level API is * intended for use in tests or specialized setups. Typically you want to use * `createApp` from `@backstage/frontend-defaults` instead. * * @public */ declare function createSpecializedApp(options?: CreateSpecializedAppOptions): { apis: ApiHolder; tree: AppTree; errors?: AppError[]; }; export { type AppError, type AppErrorTypes, type CreateAppRouteBinder, type CreateSpecializedAppOptions, type FrontendPluginInfoResolver, createSpecializedApp };