From b8cb7804c83dd114fcb9162c7199b9cc7869c348 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 15 Nov 2023 13:03:59 +0100 Subject: [PATCH] frontend-app-api: split out and export createSpecializedApp Signed-off-by: Patrik Oldsberg --- .changeset/sixty-adults-kiss.md | 5 + packages/frontend-app-api/api-report.md | 9 ++ .../frontend-app-api/src/wiring/createApp.tsx | 109 +++++++++++------- packages/frontend-app-api/src/wiring/index.ts | 1 + 4 files changed, 84 insertions(+), 40 deletions(-) create mode 100644 .changeset/sixty-adults-kiss.md diff --git a/.changeset/sixty-adults-kiss.md b/.changeset/sixty-adults-kiss.md new file mode 100644 index 0000000000..eb73387308 --- /dev/null +++ b/.changeset/sixty-adults-kiss.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': patch +--- + +Added `createSpecializedApp`, which is a synchronous version of `createApp` where config and features already need to be loaded. diff --git a/packages/frontend-app-api/api-report.md b/packages/frontend-app-api/api-report.md index 3d6d936018..3ca51f6331 100644 --- a/packages/frontend-app-api/api-report.md +++ b/packages/frontend-app-api/api-report.md @@ -41,6 +41,15 @@ export function createApp(options?: { // @public (undocumented) export function createExtensionTree(options: { config: Config }): ExtensionTree; +// @public +export function createSpecializedApp(options?: { + features?: (BackstagePlugin | ExtensionOverrides)[]; + config?: ConfigApi; + bindRoutes?(context: { bind: AppRouteBinder }): void; +}): { + createRoot(): JSX_2.Element; +}; + // @public (undocumented) export interface ExtensionTree { // (undocumented) diff --git a/packages/frontend-app-api/src/wiring/createApp.tsx b/packages/frontend-app-api/src/wiring/createApp.tsx index ca0e1d60d1..dd20604e8c 100644 --- a/packages/frontend-app-api/src/wiring/createApp.tsx +++ b/packages/frontend-app-api/src/wiring/createApp.tsx @@ -244,49 +244,18 @@ export function createApp(options?: { const discoveredFeatures = getAvailableFeatures(config); const loadedFeatures = (await options?.featureLoader?.({ config })) ?? []; - const allFeatures = deduplicateFeatures([ - ...discoveredFeatures, - ...loadedFeatures, - ...(options?.features ?? []), - ]); - const tree = createAppTree({ - features: allFeatures, - builtinExtensions, + const app = createSpecializedApp({ config, - }); + features: [ + ...discoveredFeatures, + ...loadedFeatures, + ...(options?.features ?? []), + ], + bindRoutes: options?.bindRoutes, + }).createRoot(); - const appContext = createLegacyAppContext( - allFeatures.filter( - (f): f is BackstagePlugin => f.$$type === '@backstage/BackstagePlugin', - ), - ); - - const routeIds = collectRouteIds(allFeatures); - - const App = () => ( - - - - - {/* TODO: set base path using the logic from AppRouter */} - - {tree.root.instance!.getData(coreExtensionData.reactElement)} - - - - - - ); - - return { default: App }; + return { default: () => app }; } return { @@ -301,6 +270,66 @@ export function createApp(options?: { }; } +/** + * Synchronous version of {@link createApp}, expecting all features and + * config to have been loaded already. + * @public + */ +export function createSpecializedApp(options?: { + features?: (BackstagePlugin | ExtensionOverrides)[]; + config?: ConfigApi; + bindRoutes?(context: { bind: AppRouteBinder }): void; +}): { createRoot(): JSX.Element } { + const { + features: duplicatedFeatures = [], + config = new ConfigReader({}, 'empty-config'), + } = options ?? {}; + + const features = deduplicateFeatures(duplicatedFeatures); + + const tree = createAppTree({ + features, + builtinExtensions, + config, + }); + + const appContext = createLegacyAppContext( + features.filter( + (f): f is BackstagePlugin => f.$$type === '@backstage/BackstagePlugin', + ), + ); + + const routeIds = collectRouteIds(features); + + const App = () => ( + + + + + {/* TODO: set base path using the logic from AppRouter */} + + {tree.root.instance!.getData(coreExtensionData.reactElement)} + + + + + + ); + + return { + createRoot() { + return ; + }, + }; +} + // Make sure that we only convert each new plugin instance to its legacy equivalent once const legacyPluginStore = getOrCreateGlobalSingleton( 'legacy-plugin-compatibility-store', diff --git a/packages/frontend-app-api/src/wiring/index.ts b/packages/frontend-app-api/src/wiring/index.ts index dc1ba3bc13..412e643523 100644 --- a/packages/frontend-app-api/src/wiring/index.ts +++ b/packages/frontend-app-api/src/wiring/index.ts @@ -16,6 +16,7 @@ export { createApp, + createSpecializedApp, createExtensionTree, type ExtensionTreeNode, type ExtensionTree,