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:
@@ -2,4 +2,4 @@
|
||||
'@backstage/frontend-dev-utils': minor
|
||||
---
|
||||
|
||||
Added `@backstage/frontend-dev-utils`, a new package that provides a minimal helper for wiring up a development app for frontend plugins using the new frontend system. It exports a `createDevApp` function that handles creating and rendering a development app from a `dev/` entry point. The dev app automatically bypasses the sign-in page and loads the `@backstage/ui` CSS.
|
||||
Added `@backstage/frontend-dev-utils`, a new package that provides a minimal helper for wiring up a development app for frontend plugins using the new frontend system. It exports a `createDevApp` function that handles creating and rendering a development app from a `dev/` entry point. The dev app automatically bypasses the sign-in page and loads the `@backstage/ui` CSS. The options interface extends all `createApp` options from `@backstage/frontend-defaults` (except `features`), such as `bindRoutes` and `advanced`.
|
||||
|
||||
@@ -121,7 +121,7 @@ import myPlugin from '../src';
|
||||
createDevApp({ features: [myPlugin] });
|
||||
```
|
||||
|
||||
This will create and render a Backstage app with only your plugin installed. If you need to include additional features that your plugin depends on, pass them along in the `features` array. You can also forward additional options to `createApp` from `@backstage/frontend-defaults` using the `createAppOptions` option.
|
||||
This will create and render a Backstage app with only your plugin installed. If you need to include additional features that your plugin depends on, pass them along in the `features` array. The options also accept all other `createApp` options from `@backstage/frontend-defaults`, such as `bindRoutes` and `advanced`.
|
||||
|
||||
The dev setup is started by running `yarn start` in the plugin directory, which uses the `backstage-cli package start` command. It sets up a local development server with hot reloading, just like a full app.
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ import { FrontendFeatureLoader } from '@backstage/frontend-plugin-api';
|
||||
export function createDevApp(options: CreateDevAppOptions): void;
|
||||
|
||||
// @public
|
||||
export interface CreateDevAppOptions {
|
||||
createAppOptions?: Omit<CreateAppOptions, 'features'>;
|
||||
export interface CreateDevAppOptions
|
||||
extends Omit<CreateAppOptions, 'features'> {
|
||||
features: (FrontendFeature | FrontendFeatureLoader)[];
|
||||
}
|
||||
```
|
||||
|
||||
@@ -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(),
|
||||
|
||||
Reference in New Issue
Block a user