diff --git a/.changeset/silver-kiwis-float.md b/.changeset/silver-kiwis-float.md
new file mode 100644
index 0000000000..6a45dfb1a6
--- /dev/null
+++ b/.changeset/silver-kiwis-float.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-plugin-api': minor
+---
+
+Extensions now return their output from the factory function rather than calling `bind(...)`.
diff --git a/.changeset/strange-gifts-try.md b/.changeset/strange-gifts-try.md
new file mode 100644
index 0000000000..7f9aa89ad4
--- /dev/null
+++ b/.changeset/strange-gifts-try.md
@@ -0,0 +1,9 @@
+---
+'@backstage/frontend-app-api': patch
+'@backstage/plugin-catalog': patch
+'@backstage/plugin-catalog-react': patch
+'@backstage/plugin-graphiql': patch
+'@backstage/plugin-search-react': patch
+---
+
+Internal updates to match changes in the experimental `@backstage/frontend-plugin-api`.
diff --git a/packages/app-next/src/App.tsx b/packages/app-next/src/App.tsx
index 1275722da4..978c40ef44 100644
--- a/packages/app-next/src/App.tsx
+++ b/packages/app-next/src/App.tsx
@@ -79,8 +79,8 @@ const homePageExtension = createExtension({
children: coreExtensionData.reactElement,
title: titleExtensionDataRef,
},
- factory({ bind }) {
- bind({ children: homePage, title: 'just a title' });
+ factory() {
+ return { children: homePage, title: 'just a title' };
},
});
diff --git a/packages/core-compat-api/src/convertLegacyApp.ts b/packages/core-compat-api/src/convertLegacyApp.ts
index 59cb136c65..93521b3955 100644
--- a/packages/core-compat-api/src/convertLegacyApp.ts
+++ b/packages/core-compat-api/src/convertLegacyApp.ts
@@ -113,18 +113,18 @@ export function convertLegacyApp(
output: {
element: coreExtensionData.reactElement,
},
- factory({ bind, inputs }) {
+ factory({ inputs }) {
// Clone the root element, this replaces the FlatRoutes declared in the app with out content input
- bind({
+ return {
element: React.cloneElement(rootEl, undefined, inputs.content.element),
- });
+ };
},
});
const CoreNavOverride = createExtension({
id: 'core.nav',
attachTo: { id: 'core.layout', input: 'nav' },
output: {},
- factory() {},
+ factory: () => ({}),
disabled: true,
});
diff --git a/packages/frontend-app-api/src/extensions/Core.tsx b/packages/frontend-app-api/src/extensions/Core.tsx
index f48aa2ea6b..60772d435c 100644
--- a/packages/frontend-app-api/src/extensions/Core.tsx
+++ b/packages/frontend-app-api/src/extensions/Core.tsx
@@ -40,9 +40,9 @@ export const Core = createExtension({
output: {
root: coreExtensionData.reactElement,
},
- factory({ bind, inputs }) {
- bind({
+ factory({ inputs }) {
+ return {
root: inputs.root.element,
- });
+ };
},
});
diff --git a/packages/frontend-app-api/src/extensions/CoreLayout.tsx b/packages/frontend-app-api/src/extensions/CoreLayout.tsx
index bf0f382cfc..97f49acac9 100644
--- a/packages/frontend-app-api/src/extensions/CoreLayout.tsx
+++ b/packages/frontend-app-api/src/extensions/CoreLayout.tsx
@@ -42,14 +42,14 @@ export const CoreLayout = createExtension({
output: {
element: coreExtensionData.reactElement,
},
- factory({ bind, inputs }) {
- bind({
+ factory({ inputs }) {
+ return {
element: (
{inputs.nav.element}
{inputs.content.element}
),
- });
+ };
},
});
diff --git a/packages/frontend-app-api/src/extensions/CoreNav.tsx b/packages/frontend-app-api/src/extensions/CoreNav.tsx
index cd12ca129a..37ce50276b 100644
--- a/packages/frontend-app-api/src/extensions/CoreNav.tsx
+++ b/packages/frontend-app-api/src/extensions/CoreNav.tsx
@@ -82,8 +82,8 @@ export const CoreNav = createExtension({
output: {
element: coreExtensionData.reactElement,
},
- factory({ bind, inputs }) {
- bind({
+ factory({ inputs }) {
+ return {
element: (
@@ -93,6 +93,6 @@ export const CoreNav = createExtension({
))}
),
- });
+ };
},
});
diff --git a/packages/frontend-app-api/src/extensions/CoreRoutes.tsx b/packages/frontend-app-api/src/extensions/CoreRoutes.tsx
index 8d22b40eec..985fd07be9 100644
--- a/packages/frontend-app-api/src/extensions/CoreRoutes.tsx
+++ b/packages/frontend-app-api/src/extensions/CoreRoutes.tsx
@@ -35,7 +35,7 @@ export const CoreRoutes = createExtension({
output: {
element: coreExtensionData.reactElement,
},
- factory({ bind, inputs }) {
+ factory({ inputs }) {
const Routes = () => {
const element = useRoutes(
inputs.routes.map(route => ({
@@ -46,8 +46,8 @@ export const CoreRoutes = createExtension({
return element;
};
- bind({
+ return {
element: ,
- });
+ };
},
});
diff --git a/packages/frontend-app-api/src/graph/createAppGraph.test.ts b/packages/frontend-app-api/src/graph/createAppGraph.test.ts
index 2c9f062199..1a046b210b 100644
--- a/packages/frontend-app-api/src/graph/createAppGraph.test.ts
+++ b/packages/frontend-app-api/src/graph/createAppGraph.test.ts
@@ -26,7 +26,7 @@ const extBase = {
id: 'test',
attachTo: { id: 'core', input: 'root' },
output: {},
- factory() {},
+ factory: () => ({}),
};
describe('createAppGraph', () => {
@@ -62,7 +62,7 @@ describe('createAppGraph', () => {
attachTo: { id: 'core.routes', input: 'route' },
inputs: {},
output: {},
- factory() {},
+ factory: () => ({}),
}),
],
}),
diff --git a/packages/frontend-app-api/src/graph/instantiateAppNodeTree.test.ts b/packages/frontend-app-api/src/graph/instantiateAppNodeTree.test.ts
index 21f364dda2..9be3482b5d 100644
--- a/packages/frontend-app-api/src/graph/instantiateAppNodeTree.test.ts
+++ b/packages/frontend-app-api/src/graph/instantiateAppNodeTree.test.ts
@@ -45,8 +45,8 @@ const simpleExtension = createExtension({
other: z.number().optional(),
}),
),
- factory({ bind, config }) {
- bind({ test: config.output, other: config.other });
+ factory({ config }) {
+ return { test: config.output, other: config.other };
},
});
@@ -114,8 +114,8 @@ describe('instantiateAppNodeTree', () => {
output: {
inputMirror: inputMirrorDataRef,
},
- factory({ bind, inputs }) {
- bind({ inputMirror: inputs });
+ factory({ inputs }) {
+ return { inputMirror: inputs };
},
}),
),
@@ -158,8 +158,8 @@ describe('instantiateAppNodeTree', () => {
output: {
inputMirror: inputMirrorDataRef,
},
- factory({ bind, inputs }) {
- bind({ inputMirror: inputs });
+ factory({ inputs }) {
+ return { inputMirror: inputs };
},
}),
),
@@ -264,8 +264,8 @@ describe('createAppNodeInstance', () => {
output: {
inputMirror: inputMirrorDataRef,
},
- factory({ bind, inputs }) {
- bind({ inputMirror: inputs });
+ factory({ inputs }) {
+ return { inputMirror: inputs };
},
}),
),
@@ -326,8 +326,8 @@ describe('createAppNodeInstance', () => {
test1: testDataRef,
test2: testDataRef,
},
- factory({ bind }) {
- bind({ test1: 'test', test2: 'test2' });
+ factory({}) {
+ return { test1: 'test', test2: 'test2' };
},
}),
),
@@ -348,8 +348,8 @@ describe('createAppNodeInstance', () => {
output: {
test: testDataRef,
},
- factory({ bind }) {
- bind({ nonexistent: 'test' } as any);
+ factory({}) {
+ return { nonexistent: 'test' } as any;
},
}),
),
@@ -376,7 +376,7 @@ describe('createAppNodeInstance', () => {
),
},
output: {},
- factory() {},
+ factory: () => ({}),
}),
),
attachments: new Map(),
@@ -417,7 +417,7 @@ describe('createAppNodeInstance', () => {
}),
},
output: {},
- factory() {},
+ factory: () => ({}),
}),
),
}),
@@ -447,7 +447,7 @@ describe('createAppNodeInstance', () => {
id: 'core.test',
attachTo: { id: 'ignored', input: 'ignored' },
output: {},
- factory() {},
+ factory: () => ({}),
}),
),
}),
@@ -481,7 +481,7 @@ describe('createAppNodeInstance', () => {
),
},
output: {},
- factory() {},
+ factory: () => ({}),
}),
),
}),
@@ -515,7 +515,7 @@ describe('createAppNodeInstance', () => {
),
},
output: {},
- factory() {},
+ factory: () => ({}),
}),
),
}),
@@ -543,7 +543,7 @@ describe('createAppNodeInstance', () => {
),
},
output: {},
- factory() {},
+ factory: () => ({}),
}),
),
}),
diff --git a/packages/frontend-app-api/src/graph/instantiateAppNodeTree.ts b/packages/frontend-app-api/src/graph/instantiateAppNodeTree.ts
index ba0c85692e..bf6028554b 100644
--- a/packages/frontend-app-api/src/graph/instantiateAppNodeTree.ts
+++ b/packages/frontend-app-api/src/graph/instantiateAppNodeTree.ts
@@ -113,26 +113,25 @@ export function createAppNodeInstance(options: {
}
try {
- extension.factory({
+ const namedOutputs = extension.factory({
source,
config: parsedConfig,
- bind: namedOutputs => {
- for (const [name, output] of Object.entries(namedOutputs)) {
- const ref = extension.output[name];
- if (!ref) {
- throw new Error(`unknown output provided via '${name}'`);
- }
- if (extensionData.has(ref.id)) {
- throw new Error(
- `duplicate extension data '${ref.id}' received via output '${name}'`,
- );
- }
- extensionData.set(ref.id, output);
- extensionDataRefs.add(ref);
- }
- },
inputs: resolveInputs(extension.inputs, attachments),
});
+
+ for (const [name, output] of Object.entries(namedOutputs)) {
+ const ref = extension.output[name];
+ if (!ref) {
+ throw new Error(`unknown output provided via '${name}'`);
+ }
+ if (extensionData.has(ref.id)) {
+ throw new Error(
+ `duplicate extension data '${ref.id}' received via output '${name}'`,
+ );
+ }
+ extensionData.set(ref.id, output);
+ extensionDataRefs.add(ref);
+ }
} catch (e) {
throw new Error(
`Failed to instantiate extension '${id}'${
diff --git a/packages/frontend-app-api/src/graph/resolveAppGraph.test.ts b/packages/frontend-app-api/src/graph/resolveAppGraph.test.ts
index 2668c51863..2b7257446e 100644
--- a/packages/frontend-app-api/src/graph/resolveAppGraph.test.ts
+++ b/packages/frontend-app-api/src/graph/resolveAppGraph.test.ts
@@ -21,7 +21,7 @@ const extBaseConfig = {
id: 'test',
attachTo: { id: 'nonexistent', input: 'nonexistent' },
output: {},
- factory() {},
+ factory: () => ({}),
};
const extension = createExtension(extBaseConfig);
diff --git a/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.test.ts b/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.test.ts
index e0adf3062a..c6b025e8b3 100644
--- a/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.test.ts
+++ b/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.test.ts
@@ -62,12 +62,12 @@ function createTestExtension(options: {
element: coreExtensionData.reactElement,
}),
},
- factory({ bind }) {
- bind({
+ factory() {
+ return {
path: options.path,
routeRef: options.routeRef,
element: React.createElement('div'),
- });
+ };
},
});
}
diff --git a/packages/frontend-plugin-api/api-report.md b/packages/frontend-plugin-api/api-report.md
index ac8d164fae..250ce5f676 100644
--- a/packages/frontend-plugin-api/api-report.md
+++ b/packages/frontend-plugin-api/api-report.md
@@ -170,10 +170,9 @@ export interface CreateExtensionOptions<
// (undocumented)
factory(options: {
source?: BackstagePlugin;
- bind(values: Expand>): void;
config: TConfig;
inputs: Expand>;
- }): void;
+ }): Expand>;
// (undocumented)
id: string;
// (undocumented)
@@ -313,13 +312,12 @@ export interface Extension {
// (undocumented)
factory(options: {
source?: BackstagePlugin;
- bind(values: ExtensionInputValues): void;
config: TConfig;
inputs: Record<
string,
undefined | Record | Array>
>;
- }): void;
+ }): ExtensionDataValues;
// (undocumented)
id: string;
// (undocumented)
diff --git a/packages/frontend-plugin-api/src/components/ExtensionBoundary.test.tsx b/packages/frontend-plugin-api/src/components/ExtensionBoundary.test.tsx
index 704cafda2d..7b27c79360 100644
--- a/packages/frontend-plugin-api/src/components/ExtensionBoundary.test.tsx
+++ b/packages/frontend-plugin-api/src/components/ExtensionBoundary.test.tsx
@@ -66,8 +66,8 @@ const wrapInBoundaryExtension = (element: JSX.Element) => {
path: coreExtensionData.routePath,
routeRef: coreExtensionData.routeRef.optional(),
},
- factory({ bind, source }) {
- bind({
+ factory({ source }) {
+ return {
routeRef,
path: '/',
element: (
@@ -75,7 +75,7 @@ const wrapInBoundaryExtension = (element: JSX.Element) => {
{element}
),
- });
+ };
},
});
};
diff --git a/packages/frontend-plugin-api/src/extensions/createApiExtension.ts b/packages/frontend-plugin-api/src/extensions/createApiExtension.ts
index f728261072..7b6dded022 100644
--- a/packages/frontend-plugin-api/src/extensions/createApiExtension.ts
+++ b/packages/frontend-plugin-api/src/extensions/createApiExtension.ts
@@ -58,12 +58,11 @@ export function createApiExtension<
output: {
api: coreExtensionData.apiFactory,
},
- factory({ bind, config, inputs }) {
+ factory({ config, inputs }) {
if (typeof factory === 'function') {
- bind({ api: factory({ config, inputs }) });
- } else {
- bind({ api: factory });
+ return { api: factory({ config, inputs }) };
}
+ return { api: factory };
},
});
}
diff --git a/packages/frontend-plugin-api/src/extensions/createNavItemExtension.tsx b/packages/frontend-plugin-api/src/extensions/createNavItemExtension.tsx
index ee38dda016..84fbe5ffee 100644
--- a/packages/frontend-plugin-api/src/extensions/createNavItemExtension.tsx
+++ b/packages/frontend-plugin-api/src/extensions/createNavItemExtension.tsx
@@ -41,14 +41,12 @@ export function createNavItemExtension(options: {
output: {
navTarget: coreExtensionData.navTarget,
},
- factory: ({ bind, config }) => {
- bind({
- navTarget: {
- title: config.title,
- icon,
- routeRef,
- },
- });
- },
+ factory: ({ config }) => ({
+ navTarget: {
+ title: config.title,
+ icon,
+ routeRef,
+ },
+ }),
});
}
diff --git a/packages/frontend-plugin-api/src/extensions/createPageExtension.test.tsx b/packages/frontend-plugin-api/src/extensions/createPageExtension.test.tsx
index 37d97e7621..81843558da 100644
--- a/packages/frontend-plugin-api/src/extensions/createPageExtension.test.tsx
+++ b/packages/frontend-plugin-api/src/extensions/createPageExtension.test.tsx
@@ -20,7 +20,6 @@ import { useAnalytics } from '@backstage/core-plugin-api';
import { waitFor } from '@testing-library/react';
import { PortableSchema } from '../schema';
import {
- ExtensionInputValues,
coreExtensionData,
createExtensionInput,
createPlugin,
@@ -127,16 +126,14 @@ describe('createPageExtension', () => {
loader: async () => Component
,
});
- extension.factory({
- bind: (values: ExtensionInputValues) =>
- renderWithEffects(
- wrapInTestApp(values.element as unknown as JSX.Element),
- ),
+ const output = extension.factory({
source: createPlugin({ id: 'plugin ' }),
config: { path: '/' },
inputs: {},
});
+ renderWithEffects(wrapInTestApp(output.element as unknown as JSX.Element));
+
await waitFor(() =>
expect(captureEvent).toHaveBeenCalledWith(
'_ROUTABLE-EXTENSION-RENDERED',
diff --git a/packages/frontend-plugin-api/src/extensions/createPageExtension.tsx b/packages/frontend-plugin-api/src/extensions/createPageExtension.tsx
index f05182149b..f5e258a1e4 100644
--- a/packages/frontend-plugin-api/src/extensions/createPageExtension.tsx
+++ b/packages/frontend-plugin-api/src/extensions/createPageExtension.tsx
@@ -75,14 +75,14 @@ export function createPageExtension<
path: coreExtensionData.routePath,
routeRef: coreExtensionData.routeRef.optional(),
},
- factory({ bind, config, inputs, source }) {
+ factory({ config, inputs, source }) {
const ExtensionComponent = lazy(() =>
options
.loader({ config, inputs })
.then(element => ({ default: () => element })),
);
- bind({
+ return {
path: config.path,
routeRef: options.routeRef,
element: (
@@ -90,7 +90,7 @@ export function createPageExtension<
),
- });
+ };
},
});
}
diff --git a/packages/frontend-plugin-api/src/extensions/createThemeExtension.ts b/packages/frontend-plugin-api/src/extensions/createThemeExtension.ts
index 38763688a4..d41121d51c 100644
--- a/packages/frontend-plugin-api/src/extensions/createThemeExtension.ts
+++ b/packages/frontend-plugin-api/src/extensions/createThemeExtension.ts
@@ -25,8 +25,6 @@ export function createThemeExtension(theme: AppTheme) {
output: {
theme: coreExtensionData.theme,
},
- factory({ bind }) {
- bind({ theme });
- },
+ factory: () => ({ theme }),
});
}
diff --git a/packages/frontend-plugin-api/src/wiring/createExtension.test.ts b/packages/frontend-plugin-api/src/wiring/createExtension.test.ts
index 757bcd7e3d..071272d58f 100644
--- a/packages/frontend-plugin-api/src/wiring/createExtension.test.ts
+++ b/packages/frontend-plugin-api/src/wiring/createExtension.test.ts
@@ -24,71 +24,211 @@ function unused(..._any: any[]) {}
describe('createExtension', () => {
it('should create an extension with a simple output', () => {
- const extension = createExtension({
+ const baseConfig = {
id: 'test',
attachTo: { id: 'root', input: 'default' },
output: {
foo: stringData,
},
- factory({ bind }) {
- bind({
+ };
+ const extension = createExtension({
+ ...baseConfig,
+ factory() {
+ return {
foo: 'bar',
- });
- bind({
- // @ts-expect-error
- foo: 3,
- });
- bind({
- // @ts-expect-error
- bar: 'bar',
- });
- // @ts-expect-error
- bind({});
- // @ts-expect-error
- bind();
- // @ts-expect-error
- bind('bar');
+ };
},
});
expect(extension.id).toBe('test');
+
+ // When declared as an error function without a block the TypeScript errors
+ // are a more specific and will point at the property that is problematic.
+ createExtension({
+ ...baseConfig,
+ factory: () => ({
+ // @ts-expect-error
+ foo: 3,
+ }),
+ });
+ createExtension({
+ ...baseConfig,
+ factory: () =>
+ // @ts-expect-error
+ ({
+ bar: 'bar',
+ }),
+ });
+ createExtension({
+ ...baseConfig,
+ factory: () =>
+ // @ts-expect-error
+ ({}),
+ });
+ createExtension({
+ ...baseConfig,
+ factory: () =>
+ // @ts-expect-error
+ undefined,
+ });
+ createExtension({
+ ...baseConfig,
+ factory: () =>
+ // @ts-expect-error
+ 'bar',
+ });
+
+ // When declared as a function with a block the TypeScript error will instead
+ // be tied to the factory function declaration itself, but the error messages
+ // is still helpful and points to part of the return type that is problematic.
+ createExtension({
+ ...baseConfig,
+ // @ts-expect-error
+ factory() {
+ return {
+ foo: 3,
+ };
+ },
+ });
+ createExtension({
+ ...baseConfig,
+ // @ts-expect-error
+ factory() {
+ return {
+ bar: 'bar',
+ };
+ },
+ });
+ createExtension({
+ ...baseConfig,
+ // @ts-expect-error
+ factory() {
+ return {};
+ },
+ });
+ createExtension({
+ ...baseConfig,
+ // @ts-expect-error
+ factory() {
+ return {};
+ },
+ });
+ createExtension({
+ ...baseConfig,
+ // @ts-expect-error
+ factory() {
+ return 'bar';
+ },
+ });
+
+ createExtension({
+ ...baseConfig,
+ // @ts-expect-error
+ factory: () => {
+ return {
+ foo: 3,
+ };
+ },
+ });
+ createExtension({
+ ...baseConfig,
+ // @ts-expect-error
+ factory: () => {
+ return {
+ bar: 'bar',
+ };
+ },
+ });
+ createExtension({
+ ...baseConfig,
+ // @ts-expect-error
+ factory: () => {
+ return {};
+ },
+ });
+ createExtension({
+ ...baseConfig,
+ // @ts-expect-error
+ factory: () => {
+ return {};
+ },
+ });
+ createExtension({
+ ...baseConfig,
+ // @ts-expect-error
+ factory: () => {
+ return 'bar';
+ },
+ });
});
it('should create an extension with a some optional output', () => {
- const extension = createExtension({
+ const baseConfig = {
id: 'test',
attachTo: { id: 'root', input: 'default' },
output: {
foo: stringData,
bar: stringData.optional(),
},
- factory({ bind }) {
- bind({
- foo: 'bar',
- });
- bind({
- foo: 'bar',
- bar: 'baz',
- });
- bind({
- // @ts-expect-error
- foo: 3,
- });
- bind({
- foo: 'bar',
- // @ts-expect-error
- bar: 3,
- });
- // @ts-expect-error
- bind({ bar: 'bar' });
- // @ts-expect-error
- bind({});
- // @ts-expect-error
- bind();
- // @ts-expect-error
- bind('bar');
- },
+ };
+ const extension = createExtension({
+ ...baseConfig,
+ factory: () => ({
+ foo: 'bar',
+ }),
});
expect(extension.id).toBe('test');
+
+ createExtension({
+ ...baseConfig,
+ factory: () => ({
+ foo: 'bar',
+ bar: 'baz',
+ }),
+ });
+ createExtension({
+ ...baseConfig,
+ factory: () => ({
+ // @ts-expect-error
+ foo: 3,
+ }),
+ });
+ createExtension({
+ ...baseConfig,
+ factory: () => ({
+ foo: 'bar',
+ // @ts-expect-error
+ bar: 3,
+ }),
+ });
+ createExtension({
+ ...baseConfig,
+ factory: () =>
+ // @ts-expect-error
+ ({ bar: 'bar' }),
+ });
+ createExtension({
+ ...baseConfig,
+ factory: () =>
+ // @ts-expect-error
+ ({}),
+ });
+ createExtension({
+ ...baseConfig,
+ factory: () =>
+ // @ts-expect-error
+ undefined,
+ });
+ createExtension({
+ ...baseConfig,
+ // @ts-expect-error
+ factory: () => {},
+ });
+ createExtension({
+ ...baseConfig,
+ factory: () =>
+ // @ts-expect-error
+ 'bar',
+ });
});
it('should create an extension with input', () => {
@@ -110,7 +250,7 @@ describe('createExtension', () => {
output: {
foo: stringData,
},
- factory({ bind, inputs }) {
+ factory({ inputs }) {
const a1: string = inputs.mixed?.[0].required;
// @ts-expect-error
const a2: number = inputs.mixed?.[0].required;
@@ -141,9 +281,9 @@ describe('createExtension', () => {
const d4: number | undefined = inputs.onlyOptional?.[0].optional;
unused(d1, d2, d3, d4);
- bind({
+ return {
foo: 'bar',
- });
+ };
},
});
expect(extension.id).toBe('test');
diff --git a/packages/frontend-plugin-api/src/wiring/createExtension.ts b/packages/frontend-plugin-api/src/wiring/createExtension.ts
index fa24a24797..ff011a5875 100644
--- a/packages/frontend-plugin-api/src/wiring/createExtension.ts
+++ b/packages/frontend-plugin-api/src/wiring/createExtension.ts
@@ -81,10 +81,9 @@ export interface CreateExtensionOptions<
configSchema?: PortableSchema;
factory(options: {
source?: BackstagePlugin;
- bind(values: Expand>): void;
config: TConfig;
inputs: Expand>;
- }): void;
+ }): Expand>;
}
/** @public */
@@ -98,13 +97,12 @@ export interface Extension {
configSchema?: PortableSchema;
factory(options: {
source?: BackstagePlugin;
- bind(values: ExtensionInputValues): void;
config: TConfig;
inputs: Record<
string,
undefined | Record | Array>
>;
- }): void;
+ }): ExtensionDataValues;
}
/** @public */
@@ -120,12 +118,11 @@ export function createExtension<
disabled: options.disabled ?? false,
$$type: '@backstage/Extension',
inputs: options.inputs ?? {},
- factory({ bind, config, inputs }) {
+ factory({ inputs, ...rest }) {
// TODO: Simplify this, but TS wouldn't infer the input type for some reason
return options.factory({
- bind,
- config,
inputs: inputs as Expand>,
+ ...rest,
});
},
};
diff --git a/packages/frontend-plugin-api/src/wiring/createExtensionOverrides.test.ts b/packages/frontend-plugin-api/src/wiring/createExtensionOverrides.test.ts
index fa430a7834..eb69f954e4 100644
--- a/packages/frontend-plugin-api/src/wiring/createExtensionOverrides.test.ts
+++ b/packages/frontend-plugin-api/src/wiring/createExtensionOverrides.test.ts
@@ -39,7 +39,7 @@ describe('createExtensionOverrides', () => {
id: 'a',
attachTo: { id: 'core', input: 'apis' },
output: {},
- factory() {},
+ factory: () => ({}),
}),
],
}),
@@ -72,7 +72,7 @@ describe('createExtensionOverrides', () => {
id: 'a',
attachTo: { id: 'core', input: 'apis' },
output: {},
- factory() {},
+ factory: () => ({}),
}),
],
});
diff --git a/packages/frontend-plugin-api/src/wiring/createPlugin.test.ts b/packages/frontend-plugin-api/src/wiring/createPlugin.test.ts
index 7f73c45544..42648fcd96 100644
--- a/packages/frontend-plugin-api/src/wiring/createPlugin.test.ts
+++ b/packages/frontend-plugin-api/src/wiring/createPlugin.test.ts
@@ -34,8 +34,8 @@ const TechRadarPage = createExtension({
output: {
name: nameExtensionDataRef,
},
- factory({ bind }) {
- bind({ name: 'TechRadar' });
+ factory() {
+ return { name: 'TechRadar' };
},
});
@@ -48,8 +48,8 @@ const CatalogPage = createExtension({
configSchema: createSchemaFromZod(z =>
z.object({ name: z.string().default('Catalog') }),
),
- factory({ bind, config }) {
- bind({ name: config.name });
+ factory({ config }) {
+ return { name: config.name };
},
});
@@ -62,8 +62,8 @@ const TechDocsAddon = createExtension({
configSchema: createSchemaFromZod(z =>
z.object({ name: z.string().default('TechDocsAddon') }),
),
- factory({ bind, config }) {
- bind({ name: config.name });
+ factory({ config }) {
+ return { name: config.name };
},
});
@@ -78,8 +78,8 @@ const TechDocsPage = createExtension({
output: {
name: nameExtensionDataRef,
},
- factory({ bind, inputs }) {
- bind({ name: `TechDocs-${inputs.addons.map(n => n.name).join('-')}` });
+ factory({ inputs }) {
+ return { name: `TechDocs-${inputs.addons.map(n => n.name).join('-')}` };
},
});
@@ -94,12 +94,12 @@ const outputExtension = createExtension({
output: {
element: coreExtensionData.reactElement,
},
- factory({ bind, inputs }) {
- bind({
+ factory({ inputs }) {
+ return {
element: React.createElement('span', {}, [
`Names: ${inputs.names.map(n => n.name).join(', ')}`,
]),
- });
+ };
},
});
diff --git a/plugins/catalog-react/src/alpha.tsx b/plugins/catalog-react/src/alpha.tsx
index 8ea477d573..8d0436e4be 100644
--- a/plugins/catalog-react/src/alpha.tsx
+++ b/plugins/catalog-react/src/alpha.tsx
@@ -113,21 +113,21 @@ export function createEntityCardExtension<
.optional(),
}),
),
- factory({ bind, config, inputs, source }) {
+ factory({ config, inputs, source }) {
const ExtensionComponent = lazy(() =>
options
.loader({ inputs })
.then(element => ({ default: () => element })),
);
- bind({
+ return {
element: (
),
filter: buildFilter(config, options.filter),
- });
+ };
},
});
}
@@ -179,14 +179,14 @@ export function createEntityContentExtension<
.optional(),
}),
),
- factory({ bind, config, inputs, source }) {
+ factory({ config, inputs, source }) {
const ExtensionComponent = lazy(() =>
options
.loader({ inputs })
.then(element => ({ default: () => element })),
);
- bind({
+ return {
path: config.path,
title: config.title,
routeRef: options.routeRef,
@@ -196,7 +196,7 @@ export function createEntityContentExtension<
),
filter: buildFilter(config, options.filter),
- });
+ };
},
});
}
diff --git a/plugins/catalog/src/alpha/createCatalogFilterExtension.tsx b/plugins/catalog/src/alpha/createCatalogFilterExtension.tsx
index 5a6328078c..cf3dbd318a 100644
--- a/plugins/catalog/src/alpha/createCatalogFilterExtension.tsx
+++ b/plugins/catalog/src/alpha/createCatalogFilterExtension.tsx
@@ -43,20 +43,20 @@ export function createCatalogFilterExtension<
output: {
element: coreExtensionData.reactElement,
},
- factory({ bind, config, source }) {
+ factory({ config, source }) {
const ExtensionComponent = lazy(() =>
options
.loader({ config })
.then(element => ({ default: () => element })),
);
- bind({
+ return {
element: (
),
- });
+ };
},
});
}
diff --git a/plugins/graphiql/src/alpha.tsx b/plugins/graphiql/src/alpha.tsx
index 58b6686daa..8b2b962355 100644
--- a/plugins/graphiql/src/alpha.tsx
+++ b/plugins/graphiql/src/alpha.tsx
@@ -88,10 +88,10 @@ export function createEndpointExtension(options: {
output: {
endpoint: endpointDataRef,
},
- factory({ bind, config }) {
- bind({
+ factory({ config }) {
+ return {
endpoint: options.factory({ config }).endpoint,
- });
+ };
},
});
}
diff --git a/plugins/search-react/src/alpha.tsx b/plugins/search-react/src/alpha.tsx
index f937ef99cc..80e464fe4e 100644
--- a/plugins/search-react/src/alpha.tsx
+++ b/plugins/search-react/src/alpha.tsx
@@ -107,14 +107,14 @@ export function createSearchResultListItemExtension<
output: {
item: searchResultItemExtensionData,
},
- factory({ bind, config, source }) {
+ factory({ config, source }) {
const ExtensionComponent = lazy(() =>
options
.component({ config })
.then(component => ({ default: component })),
) as unknown as SearchResultItemExtensionComponent;
- bind({
+ return {
item: {
predicate: options.predicate,
component: props => (
@@ -129,7 +129,7 @@ export function createSearchResultListItemExtension<
),
},
- });
+ };
},
});
}