From d84d3e3892e7b69154ae47d23a8103a93db777a7 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 7 Aug 2025 12:13:35 +0200 Subject: [PATCH 1/6] frontend-plugin-api: TsDoc for createExtension Signed-off-by: Patrik Oldsberg --- .../src/wiring/createExtension.ts | 43 ++++++++++++++++++- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/packages/frontend-plugin-api/src/wiring/createExtension.ts b/packages/frontend-plugin-api/src/wiring/createExtension.ts index de97f8084a..b700ae5297 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtension.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtension.ts @@ -27,7 +27,12 @@ import { z } from 'zod'; import { createSchemaFromZod } from '../schema/createSchemaFromZod'; import { OpaqueExtensionDefinition } from '@internal/frontend'; import { ExtensionDataContainer } from './types'; -import { ExtensionBlueprintDefineParams } from './createExtensionBlueprint'; +import { + ExtensionBlueprint, + ExtensionBlueprintDefineParams, +} from './createExtensionBlueprint'; +import { FrontendPlugin } from './createFrontendPlugin'; +import { FrontendModule } from './createFrontendModule'; /** * This symbol is used to pass parameter overrides from the extension override to the blueprint factory @@ -281,7 +286,41 @@ export type ExtensionDefinition< }>; }; -/** @public */ +/** + * 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 + */ export function createExtension< UOutput extends ExtensionDataRef, TInputs extends { From f416e9f499bd7127e96c5573d29afdf5032f2a7e Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 7 Aug 2025 12:35:07 +0200 Subject: [PATCH 2/6] frontend-plugin-api: TsDoc for createExtensionBlueprint Signed-off-by: Patrik Oldsberg --- .../src/wiring/createExtensionBlueprint.ts | 48 ++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts index da7e6a8f02..53179a82d7 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts @@ -34,6 +34,7 @@ import { resolveInputOverrides, } from './resolveInputOverrides'; import { ExtensionDataContainer } from './types'; +import { PageBlueprint } from '../blueprints/PageBlueprint'; /** * A function used to define a parameter mapping function in order to facilitate @@ -403,9 +404,52 @@ function unwrapParams( } /** - * A simpler replacement for wrapping up `createExtension` inside a kind or type. This allows for a cleaner API for creating - * types and instances of those types. + * 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 identity 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 */ export function createExtensionBlueprint< From 5a29c86a9290ce510cc4b6dd7d78bbd71b6bc64c Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 7 Aug 2025 13:45:31 +0200 Subject: [PATCH 3/6] frontend-plugin-api: TsDoc for createFrontendPlugin Signed-off-by: Patrik Oldsberg --- .../src/wiring/createFrontendPlugin.ts | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/packages/frontend-plugin-api/src/wiring/createFrontendPlugin.ts b/packages/frontend-plugin-api/src/wiring/createFrontendPlugin.ts index f0d923d3f9..07280818e9 100644 --- a/packages/frontend-plugin-api/src/wiring/createFrontendPlugin.ts +++ b/packages/frontend-plugin-api/src/wiring/createFrontendPlugin.ts @@ -135,7 +135,36 @@ export interface PluginOptions< info?: FrontendPluginInfoOptions; } -/** @public */ +/** + * Creates a new plugin instance that can be installed in a Backstage app. + * + * @remarks + * + * Every plugin instance 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 + */ export function createFrontendPlugin< TId extends string, TRoutes extends { [name in string]: RouteRef | SubRouteRef } = {}, From bd55cc941f802b331778bc9064b61b5caa8b8078 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 7 Aug 2025 13:59:13 +0200 Subject: [PATCH 4/6] frontend-plugin-api: TsDoc for createFrontendModule Signed-off-by: Patrik Oldsberg --- .../src/wiring/createFrontendModule.ts | 40 ++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/packages/frontend-plugin-api/src/wiring/createFrontendModule.ts b/packages/frontend-plugin-api/src/wiring/createFrontendModule.ts index bece1539fa..00b569657f 100644 --- a/packages/frontend-plugin-api/src/wiring/createFrontendModule.ts +++ b/packages/frontend-plugin-api/src/wiring/createFrontendModule.ts @@ -45,7 +45,45 @@ export interface InternalFrontendModule extends FrontendModule { readonly featureFlags: FeatureFlagConfig[]; } -/** @public */ +/** + * Creates a new module instance 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 presedence. + * + * Every module instance 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 + */ export function createFrontendModule< TId extends string, TExtensions extends readonly ExtensionDefinition[] = [], From 24558f0e3d31162e240d5296a4183f096f6e38c3 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 7 Aug 2025 14:00:21 +0200 Subject: [PATCH 5/6] changesets: add changesets for frontend-plugin-api tsdocs Signed-off-by: Patrik Oldsberg --- .changeset/whole-glasses-visit.md | 5 +++++ packages/frontend-plugin-api/report.api.md | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 .changeset/whole-glasses-visit.md diff --git a/.changeset/whole-glasses-visit.md b/.changeset/whole-glasses-visit.md new file mode 100644 index 0000000000..e318ce5956 --- /dev/null +++ b/.changeset/whole-glasses-visit.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-plugin-api': patch +--- + +Added inline documentation for `createExtension`, `createExtensionBlueprint`, `createFrontendPlugin`, and `createFrontendModule`. diff --git a/packages/frontend-plugin-api/report.api.md b/packages/frontend-plugin-api/report.api.md index 5cc679815d..78c2ba361f 100644 --- a/packages/frontend-plugin-api/report.api.md +++ b/packages/frontend-plugin-api/report.api.md @@ -393,7 +393,7 @@ export { createApiFactory }; export { createApiRef }; -// @public (undocumented) +// @public export function createExtension< UOutput extends ExtensionDataRef, TInputs extends { @@ -688,7 +688,7 @@ export interface CreateFrontendFeatureLoaderOptions { >; } -// @public (undocumented) +// @public export function createFrontendModule< TId extends string, TExtensions extends readonly ExtensionDefinition[] = [], @@ -707,7 +707,7 @@ export interface CreateFrontendModuleOptions< pluginId: TPluginId; } -// @public (undocumented) +// @public export function createFrontendPlugin< TId extends string, TRoutes extends { From 3bc9c965724eaef50a2c0e33f5018599d8aaba03 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 8 Aug 2025 16:48:47 +0200 Subject: [PATCH 6/6] frontend-plugin-api: tsdoc review fixes Signed-off-by: Patrik Oldsberg --- .../src/wiring/createExtension.ts | 20 ++++++------ .../src/wiring/createExtensionBlueprint.ts | 2 +- .../src/wiring/createFrontendModule.ts | 32 +++++++++---------- .../src/wiring/createFrontendPlugin.ts | 4 +-- 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/packages/frontend-plugin-api/src/wiring/createExtension.ts b/packages/frontend-plugin-api/src/wiring/createExtension.ts index b700ae5297..0c0b75a572 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtension.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtension.ts @@ -308,16 +308,16 @@ export type ExtensionDefinition< * * @example * - *```ts - *const myExtension = createExtension({ - * name: 'example', - * attachTo: { id: 'app', input: 'root' }, - * output: [coreExtensionData.reactElement], - * factory() { - * return [coreExtensionData.reactElement(

Hello, world!

)]; - * }, - *}); - *``` + * ```ts + * const myExtension = createExtension({ + * name: 'example', + * attachTo: { id: 'app', input: 'root' }, + * output: [coreExtensionData.reactElement], + * factory() { + * return [coreExtensionData.reactElement(

Hello, world!

)]; + * }, + * }); + * ``` * * @public */ diff --git a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts index 53179a82d7..1a24eed712 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts @@ -419,7 +419,7 @@ function unwrapParams( * 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 identity and group the + * 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 diff --git a/packages/frontend-plugin-api/src/wiring/createFrontendModule.ts b/packages/frontend-plugin-api/src/wiring/createFrontendModule.ts index 00b569657f..7921f98635 100644 --- a/packages/frontend-plugin-api/src/wiring/createFrontendModule.ts +++ b/packages/frontend-plugin-api/src/wiring/createFrontendModule.ts @@ -46,15 +46,15 @@ export interface InternalFrontendModule extends FrontendModule { } /** - * Creates a new module instance that can be installed in a Backstage app. + * 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 presedence. + * the extension provided by the module will always take precedence. * - * Every module instance is created for a specific plugin by providing the + * 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. @@ -67,20 +67,20 @@ export interface InternalFrontendModule extends FrontendModule { * * @example * - *```tsx - *import { createFrontendModule } from '@backstage/frontend-plugin-api'; + * ```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 => ), - * }), - * ], - *}); - *``` + * 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 */ diff --git a/packages/frontend-plugin-api/src/wiring/createFrontendPlugin.ts b/packages/frontend-plugin-api/src/wiring/createFrontendPlugin.ts index 07280818e9..f545195e81 100644 --- a/packages/frontend-plugin-api/src/wiring/createFrontendPlugin.ts +++ b/packages/frontend-plugin-api/src/wiring/createFrontendPlugin.ts @@ -136,11 +136,11 @@ export interface PluginOptions< } /** - * Creates a new plugin instance that can be installed in a Backstage app. + * Creates a new plugin that can be installed in a Backstage app. * * @remarks * - * Every plugin instance is created with a unique ID and a set of extensions + * 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