Merge pull request #30816 from backstage/camilaibs/make-app-node-spec-plugin-required
[NFS] frontend-plugin-api: make app spec plugin required
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/frontend-app-api': minor
|
||||
---
|
||||
|
||||
Use an app plugin for built-in extension app node specs.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/frontend-app-api': minor
|
||||
---
|
||||
|
||||
The `AppNodeSpec.plugin` property is now required.
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
createExtensionBlueprint,
|
||||
createExtensionDataRef,
|
||||
createExtensionInput,
|
||||
createFrontendPlugin,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
import {
|
||||
createAppNodeInstance,
|
||||
@@ -59,7 +60,7 @@ function makeSpec<TConfig, TConfigInput>(
|
||||
attachTo: extension.attachTo,
|
||||
disabled: extension.disabled,
|
||||
extension: extension as Extension<unknown, unknown>,
|
||||
plugin: undefined,
|
||||
plugin: createFrontendPlugin({ pluginId: 'app' }),
|
||||
...spec,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -68,6 +68,9 @@ describe('resolveAppNodeSpecs', () => {
|
||||
extension: a,
|
||||
attachTo: { id: 'root', input: 'default' },
|
||||
disabled: true,
|
||||
config: undefined,
|
||||
plugin: expect.any(Object),
|
||||
source: expect.any(Object),
|
||||
},
|
||||
]);
|
||||
});
|
||||
@@ -87,12 +90,18 @@ describe('resolveAppNodeSpecs', () => {
|
||||
extension: a,
|
||||
attachTo: { id: 'root', input: 'default' },
|
||||
disabled: false,
|
||||
config: undefined,
|
||||
plugin: expect.any(Object),
|
||||
source: expect.any(Object),
|
||||
},
|
||||
{
|
||||
id: 'b',
|
||||
extension: b,
|
||||
attachTo: { id: 'root', input: 'default' },
|
||||
disabled: false,
|
||||
config: undefined,
|
||||
plugin: expect.any(Object),
|
||||
source: expect.any(Object),
|
||||
},
|
||||
]);
|
||||
});
|
||||
@@ -120,6 +129,9 @@ describe('resolveAppNodeSpecs', () => {
|
||||
extension: b,
|
||||
attachTo: { id: 'derp', input: 'default' },
|
||||
disabled: false,
|
||||
config: undefined,
|
||||
plugin: expect.any(Object),
|
||||
source: expect.any(Object),
|
||||
},
|
||||
{
|
||||
id: 'test/a',
|
||||
@@ -204,12 +216,18 @@ describe('resolveAppNodeSpecs', () => {
|
||||
extension: b,
|
||||
attachTo: { id: 'root', input: 'default' },
|
||||
disabled: false,
|
||||
config: undefined,
|
||||
plugin: expect.any(Object),
|
||||
source: expect.any(Object),
|
||||
},
|
||||
{
|
||||
id: 'a',
|
||||
extension: a,
|
||||
attachTo: { id: 'root', input: 'default' },
|
||||
disabled: false,
|
||||
config: undefined,
|
||||
plugin: expect.any(Object),
|
||||
source: expect.any(Object),
|
||||
},
|
||||
]);
|
||||
});
|
||||
@@ -238,42 +256,63 @@ describe('resolveAppNodeSpecs', () => {
|
||||
extension: e,
|
||||
attachTo: { id: 'root', input: 'default' },
|
||||
disabled: false,
|
||||
config: undefined,
|
||||
plugin: expect.any(Object),
|
||||
source: expect.any(Object),
|
||||
},
|
||||
{
|
||||
id: 'd',
|
||||
extension: d,
|
||||
attachTo: { id: 'root', input: 'default' },
|
||||
disabled: false,
|
||||
config: undefined,
|
||||
plugin: expect.any(Object),
|
||||
source: expect.any(Object),
|
||||
},
|
||||
{
|
||||
id: 'c',
|
||||
extension: c,
|
||||
attachTo: { id: 'root', input: 'default' },
|
||||
disabled: false,
|
||||
config: undefined,
|
||||
plugin: expect.any(Object),
|
||||
source: expect.any(Object),
|
||||
},
|
||||
{
|
||||
id: 'a',
|
||||
extension: a,
|
||||
attachTo: { id: 'root', input: 'default' },
|
||||
disabled: true,
|
||||
config: undefined,
|
||||
plugin: expect.any(Object),
|
||||
source: expect.any(Object),
|
||||
},
|
||||
{
|
||||
id: 'b',
|
||||
extension: b,
|
||||
attachTo: { id: 'root', input: 'default' },
|
||||
disabled: false,
|
||||
config: undefined,
|
||||
plugin: expect.any(Object),
|
||||
source: expect.any(Object),
|
||||
},
|
||||
{
|
||||
id: 'f',
|
||||
extension: f,
|
||||
attachTo: { id: 'root', input: 'default' },
|
||||
disabled: false,
|
||||
config: undefined,
|
||||
plugin: expect.any(Object),
|
||||
source: expect.any(Object),
|
||||
},
|
||||
{
|
||||
id: 'g',
|
||||
extension: g,
|
||||
attachTo: { id: 'root', input: 'default' },
|
||||
disabled: true,
|
||||
config: undefined,
|
||||
plugin: expect.any(Object),
|
||||
source: expect.any(Object),
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -14,7 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Extension, FrontendFeature } from '@backstage/frontend-plugin-api';
|
||||
import {
|
||||
createFrontendPlugin,
|
||||
Extension,
|
||||
FrontendFeature,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
import { ExtensionParameters } from './readAppExtensionsConfig';
|
||||
import { AppNodeSpec } from '@backstage/frontend-plugin-api';
|
||||
import { OpaqueFrontendPlugin } from '@internal/frontend';
|
||||
@@ -87,6 +91,12 @@ export function resolveAppNodeSpecs(options: {
|
||||
);
|
||||
}
|
||||
|
||||
const appPlugin =
|
||||
plugins.find(plugin => plugin.id === 'app') ??
|
||||
createFrontendPlugin({
|
||||
pluginId: 'app',
|
||||
});
|
||||
|
||||
const configuredExtensions = [
|
||||
...pluginExtensions.map(({ plugin, ...extension }) => {
|
||||
const internalExtension = toInternalExtension(extension);
|
||||
@@ -106,8 +116,8 @@ export function resolveAppNodeSpecs(options: {
|
||||
return {
|
||||
extension: internalExtension,
|
||||
params: {
|
||||
source: undefined,
|
||||
plugin: undefined,
|
||||
source: appPlugin,
|
||||
plugin: appPlugin,
|
||||
attachTo: internalExtension.attachTo,
|
||||
disabled: internalExtension.disabled,
|
||||
config: undefined as unknown,
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
coreExtensionData,
|
||||
createExtension,
|
||||
createExtensionInput,
|
||||
createFrontendPlugin,
|
||||
Extension,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
import { resolveAppTree } from './resolveAppTree';
|
||||
@@ -37,6 +38,7 @@ const baseSpec = {
|
||||
extension,
|
||||
attachTo: { id: 'nonexistent', input: 'nonexistent' },
|
||||
disabled: false,
|
||||
plugin: createFrontendPlugin({ pluginId: 'app' }),
|
||||
};
|
||||
|
||||
describe('buildAppTree', () => {
|
||||
@@ -284,8 +286,20 @@ describe('buildAppTree', () => {
|
||||
) as Extension<unknown, unknown>;
|
||||
|
||||
const tree = resolveAppTree('a', [
|
||||
{ attachTo: e1.attachTo, id: 'a', extension: e1, disabled: false },
|
||||
{ attachTo: e2.attachTo, id: 'b', extension: e2, disabled: false },
|
||||
{
|
||||
attachTo: e1.attachTo,
|
||||
id: 'a',
|
||||
extension: e1,
|
||||
disabled: false,
|
||||
plugin: baseSpec.plugin,
|
||||
},
|
||||
{
|
||||
attachTo: e2.attachTo,
|
||||
id: 'b',
|
||||
extension: e2,
|
||||
disabled: false,
|
||||
plugin: baseSpec.plugin,
|
||||
},
|
||||
]);
|
||||
|
||||
expect(tree.root).toMatchInlineSnapshot(`
|
||||
@@ -352,9 +366,27 @@ describe('buildAppTree', () => {
|
||||
) as Extension<unknown, unknown>;
|
||||
|
||||
const tree = resolveAppTree('test-2', [
|
||||
{ attachTo: e1.attachTo, id: e1.id, extension: e1, disabled: false },
|
||||
{ attachTo: e2.attachTo, id: e2.id, extension: e2, disabled: false },
|
||||
{ attachTo: e3.attachTo, id: e3.id, extension: e3, disabled: false },
|
||||
{
|
||||
attachTo: e1.attachTo,
|
||||
id: e1.id,
|
||||
extension: e1,
|
||||
disabled: false,
|
||||
plugin: baseSpec.plugin,
|
||||
},
|
||||
{
|
||||
attachTo: e2.attachTo,
|
||||
id: e2.id,
|
||||
extension: e2,
|
||||
disabled: false,
|
||||
plugin: baseSpec.plugin,
|
||||
},
|
||||
{
|
||||
attachTo: e3.attachTo,
|
||||
id: e3.id,
|
||||
extension: e3,
|
||||
disabled: false,
|
||||
plugin: baseSpec.plugin,
|
||||
},
|
||||
]);
|
||||
|
||||
expect(tree.nodes.get('test-3')?.edges.attachedTo?.node).toBe(
|
||||
|
||||
@@ -268,7 +268,7 @@ export interface AppNodeSpec {
|
||||
// (undocumented)
|
||||
readonly id: string;
|
||||
// (undocumented)
|
||||
readonly plugin?: FrontendPlugin;
|
||||
readonly plugin: FrontendPlugin;
|
||||
}
|
||||
|
||||
// @public
|
||||
|
||||
@@ -37,7 +37,7 @@ export interface AppNodeSpec {
|
||||
readonly extension: Extension<unknown, unknown>;
|
||||
readonly disabled: boolean;
|
||||
readonly config?: unknown;
|
||||
readonly plugin?: FrontendPlugin;
|
||||
readonly plugin: FrontendPlugin;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user