diff --git a/.changeset/prepare-specialized-app-signin-flow.md b/.changeset/prepare-specialized-app-signin-flow.md index 746df0d4fe..be7ddca934 100644 --- a/.changeset/prepare-specialized-app-signin-flow.md +++ b/.changeset/prepare-specialized-app-signin-flow.md @@ -3,4 +3,4 @@ '@backstage/frontend-defaults': patch --- -Adds `prepareSpecializedApp` as a new two-phase app wiring API for rendering a sign-in page before full app finalization. The sign-in step is now exposed as a bootstrap component whose `onReady` callback signals that the prepared app can now be finalized, while the opaque reusable `sessionState` is stored internally on the prepared app and returned from `tryFinalize()` and `finalize()`. That session state can also be passed into a future `prepareSpecializedApp` call to skip sign-in and reuse the prepared session. The existing `createSpecializedApp` API is now deprecated and backed by `prepareSpecializedApp().finalize()`, while `createApp` has been updated to use the same prepare/finalize flow. +Adds `prepareSpecializedApp` as a new two-phase app wiring API for rendering a bootstrap tree before full app finalization. The bootstrap phase is now exposed as a partial app tree that consumers can render while subscribing to phase transitions, while the opaque reusable `sessionState` is stored internally on the prepared app and returned from `getFinalizedApp()` and `finalize()`. That session state can also be passed into a future `prepareSpecializedApp` call to skip sign-in and reuse the prepared session. The existing `createSpecializedApp` API is now deprecated and backed by `prepareSpecializedApp().finalize()`, while `createApp` has been updated to use the same prepare/finalize flow. diff --git a/packages/frontend-app-api/src/wiring/index.ts b/packages/frontend-app-api/src/wiring/index.ts index d4db40bfee..8f55d1f3cf 100644 --- a/packages/frontend-app-api/src/wiring/index.ts +++ b/packages/frontend-app-api/src/wiring/index.ts @@ -15,10 +15,10 @@ */ export { + type BootstrapSpecializedApp, type FinalizedSpecializedApp, prepareSpecializedApp, type PreparedSpecializedApp, - type PreparedSpecializedAppSignInProps, type SpecializedAppSessionState, createSpecializedApp, type CreateSpecializedAppOptions, diff --git a/packages/frontend-defaults/src/createApp.tsx b/packages/frontend-defaults/src/createApp.tsx index 310cd48f17..41c70adcf5 100644 --- a/packages/frontend-defaults/src/createApp.tsx +++ b/packages/frontend-defaults/src/createApp.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { JSX, lazy, ReactNode, Suspense, useReducer } from 'react'; +import { JSX, lazy, ReactNode, Suspense, useSyncExternalStore } from 'react'; import { ConfigApi, coreExtensionData, @@ -149,21 +149,17 @@ export function createApp(options?: CreateAppOptions): { function PreparedAppRoot(props: { preparedApp: PreparedSpecializedApp; }): JSX.Element { - const signIn = props.preparedApp.getSignIn(); - const SignIn = signIn.Component; - const [, triggerRerender] = useReducer((count: number) => count + 1, 0); - + const bootstrapApp = props.preparedApp.getBootstrapApp(); const finalizedApp: FinalizedSpecializedApp | undefined = - props.preparedApp.tryFinalize(); + useSyncExternalStore( + props.preparedApp.subscribe, + props.preparedApp.getFinalizedApp, + ); if (!finalizedApp) { - return ( - { - triggerRerender(); - }} - /> - ); + return bootstrapApp.tree.root.instance!.getData( + coreExtensionData.reactElement, + )!; } const errorPage = maybeCreateErrorPage(finalizedApp);