frontend-app-api: expose bootstrap app state
Expose the prepared bootstrap tree together with subscription-based phase updates so createApp can render from app state directly instead of forcing rerenders through a sign-in callback. Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> Made-with: Cursor
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
*/
|
||||
|
||||
export {
|
||||
type BootstrapSpecializedApp,
|
||||
type FinalizedSpecializedApp,
|
||||
prepareSpecializedApp,
|
||||
type PreparedSpecializedApp,
|
||||
type PreparedSpecializedAppSignInProps,
|
||||
type SpecializedAppSessionState,
|
||||
createSpecializedApp,
|
||||
type CreateSpecializedAppOptions,
|
||||
|
||||
@@ -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 (
|
||||
<SignIn
|
||||
onReady={() => {
|
||||
triggerRerender();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
return bootstrapApp.tree.root.instance!.getData(
|
||||
coreExtensionData.reactElement,
|
||||
)!;
|
||||
}
|
||||
|
||||
const errorPage = maybeCreateErrorPage(finalizedApp);
|
||||
|
||||
Reference in New Issue
Block a user