Merge pull request #21471 from backstage/rugvip/node

frontend-plugin-api: change extension factory to receive app node instead of id and source
This commit is contained in:
Patrik Oldsberg
2023-11-22 13:28:11 +01:00
committed by GitHub
14 changed files with 103 additions and 100 deletions
+3 -5
View File
@@ -339,7 +339,7 @@ export interface CreateExtensionOptions<
disabled?: boolean;
// (undocumented)
factory(options: {
source?: BackstagePlugin;
node: AppNode;
config: TConfig;
inputs: Expand<ExtensionInputValues<TInputs>>;
}): Expand<ExtensionDataValues<TOutput>>;
@@ -493,7 +493,7 @@ export interface Extension<TConfig> {
disabled: boolean;
// (undocumented)
factory(options: {
source?: BackstagePlugin;
node: AppNode;
config: TConfig;
inputs: Record<
string,
@@ -518,11 +518,9 @@ export interface ExtensionBoundaryProps {
// (undocumented)
children: ReactNode;
// (undocumented)
id: string;
node: AppNode;
// (undocumented)
routable?: boolean;
// (undocumented)
source?: BackstagePlugin;
}
// @public (undocumented)
@@ -34,15 +34,11 @@ const wrapInBoundaryExtension = (element: JSX.Element) => {
path: coreExtensionData.routePath,
routeRef: coreExtensionData.routeRef.optional(),
},
factory({ source }) {
factory({ node }) {
return {
routeRef,
path: '/',
element: (
<ExtensionBoundary id={id} source={source}>
{element}
</ExtensionBoundary>
),
element: <ExtensionBoundary node={node}>{element}</ExtensionBoundary>,
};
},
});
@@ -16,11 +16,11 @@
import React, { PropsWithChildren, ReactNode, useEffect } from 'react';
import { AnalyticsContext, useAnalytics } from '@backstage/core-plugin-api';
import { BackstagePlugin } from '../wiring';
import { ErrorBoundary } from './ErrorBoundary';
import { ExtensionSuspense } from './ExtensionSuspense';
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
import { routableExtensionRenderedEvent } from '../../../core-plugin-api/src/analytics/Tracker';
import { AppNode } from '../apis';
type RouteTrackerProps = PropsWithChildren<{
disableTracking?: boolean;
@@ -44,25 +44,24 @@ const RouteTracker = (props: RouteTrackerProps) => {
/** @public */
export interface ExtensionBoundaryProps {
id: string;
source?: BackstagePlugin;
node: AppNode;
routable?: boolean;
children: ReactNode;
}
/** @public */
export function ExtensionBoundary(props: ExtensionBoundaryProps) {
const { id, source, routable, children } = props;
const { node, routable, children } = props;
// Skipping "routeRef" attribute in the new system, the extension "id" should provide more insight
const attributes = {
extension: id,
pluginId: source?.id,
extension: node.spec.id,
pluginId: node.spec.source?.id,
};
return (
<ExtensionSuspense>
<ErrorBoundary plugin={source}>
<ErrorBoundary plugin={node.spec.source}>
<AnalyticsContext attributes={attributes}>
<RouteTracker disableTracking={!routable}>{children}</RouteTracker>
</AnalyticsContext>
@@ -15,16 +15,12 @@
*/
import React from 'react';
import { renderWithEffects, wrapInTestApp } from '@backstage/test-utils';
import { useAnalytics } from '@backstage/core-plugin-api';
import { waitFor } from '@testing-library/react';
import { PortableSchema } from '../schema';
import {
coreExtensionData,
createExtensionInput,
createPlugin,
} from '../wiring';
import { coreExtensionData, createExtensionInput } from '../wiring';
import { createPageExtension } from './createPageExtension';
import { createExtensionTester } from '@backstage/frontend-test-utils';
jest.mock('@backstage/core-plugin-api', () => ({
...jest.requireActual('@backstage/core-plugin-api'),
@@ -120,19 +116,13 @@ describe('createPageExtension', () => {
captureEvent,
});
const extension = createPageExtension({
id: 'plugin.page',
defaultPath: '/',
loader: async () => <div>Component</div>,
});
const output = extension.factory({
source: createPlugin({ id: 'plugin ' }),
config: { path: '/' },
inputs: {},
});
renderWithEffects(wrapInTestApp(output.element as unknown as JSX.Element));
createExtensionTester(
createPageExtension({
id: 'plugin.page',
defaultPath: '/',
loader: async () => <div>Component</div>,
}),
).render();
await waitFor(() =>
expect(captureEvent).toHaveBeenCalledWith(
@@ -75,7 +75,7 @@ export function createPageExtension<
path: coreExtensionData.routePath,
routeRef: coreExtensionData.routeRef.optional(),
},
factory({ config, inputs, source }) {
factory({ config, inputs, node }) {
const ExtensionComponent = lazy(() =>
options
.loader({ config, inputs })
@@ -86,7 +86,7 @@ export function createPageExtension<
path: config.path,
routeRef: options.routeRef,
element: (
<ExtensionBoundary id={id} source={source} routable>
<ExtensionBoundary node={node} routable>
<ExtensionComponent />
</ExtensionBoundary>
),
@@ -14,11 +14,11 @@
* limitations under the License.
*/
import { AppNode } from '../apis';
import { PortableSchema } from '../schema';
import { Expand } from '../types';
import { ExtensionDataRef } from './createExtensionDataRef';
import { ExtensionInput } from './createExtensionInput';
import { BackstagePlugin } from './createPlugin';
/** @public */
export type AnyExtensionDataMap = {
@@ -80,7 +80,7 @@ export interface CreateExtensionOptions<
output: TOutput;
configSchema?: PortableSchema<TConfig>;
factory(options: {
source?: BackstagePlugin;
node: AppNode;
config: TConfig;
inputs: Expand<ExtensionInputValues<TInputs>>;
}): Expand<ExtensionDataValues<TOutput>>;
@@ -96,7 +96,7 @@ export interface Extension<TConfig> {
output: AnyExtensionDataMap;
configSchema?: PortableSchema<TConfig>;
factory(options: {
source?: BackstagePlugin;
node: AppNode;
config: TConfig;
inputs: Record<
string,