Simplify createDevApp options

Accept createApp options at the top level in createDevApp and update the tests, docs, API report, and changeset to match the new shape.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
This commit is contained in:
Patrik Oldsberg
2026-03-16 15:06:05 +01:00
parent 2e5c65120a
commit 1594749d8e
5 changed files with 35 additions and 34 deletions
@@ -18,7 +18,7 @@ import {
PageBlueprint,
createFrontendPlugin,
} from '@backstage/frontend-plugin-api';
import { within, waitFor } from '@testing-library/react';
import { within } from '@testing-library/react';
import { mockApis } from '@backstage/test-utils';
import { createDevApp } from './createDevApp';
@@ -46,19 +46,12 @@ describe('createDevApp', () => {
createDevApp({
features: [testPlugin],
createAppOptions: {
advanced: {
configLoader: async () => ({ config: mockApis.config() }),
},
advanced: {
configLoader: async () => ({ config: mockApis.config() }),
},
});
const body = within(document.body);
await waitFor(
() => {
expect(body.getByText('Test Plugin Page')).toBeDefined();
},
{ timeout: 10000 },
);
await body.findByText('Test Plugin Page', {}, { timeout: 10000 });
}, 15000);
});
@@ -25,21 +25,32 @@ import { createApp, CreateAppOptions } from '@backstage/frontend-defaults';
import appPlugin from '@backstage/plugin-app';
import ReactDOM from 'react-dom/client';
type AppPluginWithSimpleOverrides = {
withOverrides(options: { extensions: unknown[] }): FrontendFeature;
};
// Collapse the deeply nested override types to avoid excessive instantiation.
const appPluginOverride = (
appPlugin as unknown as AppPluginWithSimpleOverrides
).withOverrides({
extensions: [
appPlugin.getExtension('sign-in-page:app').override({
disabled: true,
}),
],
});
/**
* Options for {@link createDevApp}.
*
* @public
*/
export interface CreateDevAppOptions {
export interface CreateDevAppOptions
extends Omit<CreateAppOptions, 'features'> {
/**
* The list of features to load in the dev app.
*/
features: (FrontendFeature | FrontendFeatureLoader)[];
/**
* Additional options to pass through to `createApp`.
*/
createAppOptions?: Omit<CreateAppOptions, 'features'>;
}
/**
@@ -57,19 +68,16 @@ export interface CreateDevAppOptions {
* @public
*/
export function createDevApp(options: CreateDevAppOptions): void {
const app = createApp({
...options.createAppOptions,
features: [
appPlugin.withOverrides({
extensions: [
appPlugin
.getExtension('sign-in-page:app')
.override({ disabled: true }),
],
}),
...options.features,
],
});
const { features, ...createAppOptions } = options;
const devFeatures: CreateAppOptions['features'] = [
appPluginOverride,
...features,
];
const appOptions: CreateAppOptions = {
...createAppOptions,
features: devFeatures,
};
const app = createApp(appOptions);
ReactDOM.createRoot(document.getElementById('root')!).render(
app.createRoot(),