Skip to main content

创建实用程序应用程序接口

**注意:新的前台系统处于alpha阶段,只有少数插件支持。

本节将介绍如何从零开始创建实用程序应用程序接口,或为现有的应用程序接口添加可配置性和输入。 如果您想从旧的前端系统迁移现有的实用程序应用程序接口,请查阅迁移部分.

创建实用程序应用程序接口合同

公开实用程序编程接口(utility API)的第一步是定义其 TypeScript 合约,以及供消费者用于访问实现的 API 引用。 如果您希望其他插件也能访问您的 API,则应在您插件的如果您只想在自己的插件中使用 API,可以将定义放在插件本身中。 在本例中,我们有一个 Example 插件,它希望公开一个用于执行某种工作的实用 API。

in @internal/plugin-example-react
import { createApiRef } from '@backstage/frontend-plugin-api';

/**
* The work interface for the Example plugin.
* @public
*/
export interface WorkApi {
/**
* Performs some work.
*/
doWork(): Promise<void>;
}

/**
* API Reference for {@link WorkApi}.
* @public
*/
export const workApiRef = createApiRef<WorkApi>({
id: 'plugin.example.work',
});

这两项功能都可以从软件包中公开导出,以便消费者可以接触到它们。

通过插件提供扩展功能

现在,插件本身希望以 API 扩展的形式提供该 API 及其默认实现。 这样做意味着,当用户安装 Example 插件时,其应用程序中也将自动提供 Work utility API 实例,包括 Example 插件本身和其他应用程序。 我们在主插件包中,而不是在-react包装

in @internal/plugin-example
import {
createApiExtension,
createApiFactory,
createPlugin,
storageApiRef,
StorageApi,
} from '@backstage/frontend-plugin-api';
import { WorkApi, workApiRef } from '@internal/plugin-example-react';

class WorkImpl implements WorkApi {
constructor(options: { storageApiRef: StorageApi }) {
/* TODO */
}
async doWork() {
/* TODO */
}
}

const exampleWorkApi = createApiExtension({
factory: createApiFactory({
api: workApiRef,
deps: { storageApi: storageApiRef },
factory: ({ storageApi }) => {
return new WorkImpl({ storageApi });
},
}),
});

/**
* The Example plugin.
* @public
*/
export default createPlugin({
id: 'example',
extensions: [exampleWorkApi],
});

为了便于说明,我们在同一个文件中创建了一个骨架实现类以及 API 扩展和工厂。 这些都不会导出到插件包的公共表面;只有插件才会导出,因为这是默认导出。 现在,安装插件的用户也会自动获得实用 API。

代码还说明了 API 工厂如何声明对另一个实用程序 API(本例中为核心存储 API)的依赖性。 然后向工厂函数提供该实用程序 API 的实例。

由此产生的工作应用程序接口扩展 ID 将是一种api:之后的插件 ID 作为命名空间,在本例中,最终命名空间为api:plugin.example.work查看命名模式文档现在您可以使用此 ID 在应用程序配置和其他地方引用 API。

增加可配置性

在这里,我们将介绍如何修改实用程序接口,使其具有扩展配置功能,该功能由您的应用程序配置您可以通过向 API 扩展工厂函数提供扩展配置模式来实现这一点。 让我们对原始工作示例 API 进行必要的添加。

in @internal/plugin-example
import { createSchemaFromZod } from '@backstage/frontend-plugin-api';

const exampleWorkApi = createApiExtension({
api: workApiRef,
configSchema: createSchemaFromZod(z =>
z.object({
goSlow: z.boolean().default(false),
}),
),
factory: createApiFactory({
factory: ({ config }) => createApiFactory({
api: workApiRef,
deps: { storageApi: storageApiRef },
factory: ({ storageApi }) => {
if (config.goSlow) {
/* ... */
}
},
}),
});

我们希望用户能够设置goSlow扩展配置参数。 因此,我们将一个configSchemacreateApiExtension本例使用佐德library实际的扩展配置值将以类型安全的方式传递给factory现在是一个回调,我们可以随心所欲地使用它们。 当改为回调形式时,我们还必须添加一个顶层的api: workApiRef根据createApiExtension.

请注意,这里使用的 "扩展配置 "是指不是与configApi可以访问完整的应用程序配置。 这里讨论的扩展配置是为实用程序应用程序接口实例提供的特定配置设置。 下面将详细讨论在 "配置 "部分.

还要注意的是,扩展配置模式中包含了一个默认值,即goSlow这是一个重要的考虑因素。 您希望您的 API 用户能够从中获得最大的价值,而无需深入研究如何配置。 因此,您通常希望提供尽可能多的合理默认值,同时让用户很少但有目的地覆盖它们,只有在需要时才会这样做。 如果您有一个没有默认值的扩展配置模式,框架将拒绝在启动时实例化实用 API,除非用户明确配置了这些值。 由于它有一个默认值,TypeScript 代码和接口也不必防御性地允许undefined- 我们知道,当我们开始使用扩展配置数据时,它要么是默认值,要么是重载值。

添加输入

公用程序接口的输入添加方式与其他扩展类型相同:

  • 在扩展上声明一组 "输入" * 如果需要,创建自定义扩展数据类型,用于这些输入 * 如果需要,导出扩展创建器函数,用于创建特定附件类型

这是一种功率用例,并不常用。

下一步

参见消费部分来了解如何以各种方式使用这一新的实用程序 API。 如果您希望对其进行配置并添加输入,请查看配置部分.