56 lines
1.9 KiB
TypeScript
56 lines
1.9 KiB
TypeScript
import { StrictMode, useEffect } from "react";
|
|
|
|
import { ApplicationProvider } from "../presentation/providers/application-provider.tsx";
|
|
import { ServerStateGenerationProvider } from "../presentation/adapters/query/server-state-generation-provider.tsx";
|
|
import { AppRouter } from "../presentation/routes/app-router.tsx";
|
|
import type { RuntimeComposition } from "./create-runtime-composition.ts";
|
|
|
|
/**
|
|
* Production provider tree. Tests import this component so the validated
|
|
* composition is proven against the same provider order used by main.
|
|
*/
|
|
/**
|
|
* §6.7 step 16 / §17.5. Optional runtime starts from the first committed
|
|
* effect, never during render and never during composition. StrictMode double
|
|
* invocation is safe: `startAfterMount` returns the same in-flight promise.
|
|
*/
|
|
function PostMountRuntimeStarter({
|
|
composition,
|
|
}: Readonly<{ composition: RuntimeComposition }>) {
|
|
useEffect(() => {
|
|
void composition.optional.startAfterMount();
|
|
}, [composition]);
|
|
return null;
|
|
}
|
|
|
|
export function RuntimeApplication({
|
|
composition,
|
|
}: Readonly<{ composition: RuntimeComposition }>) {
|
|
return (
|
|
<StrictMode>
|
|
<ServerStateGenerationProvider
|
|
store={composition.infrastructure.serverStateGeneration}
|
|
scope={composition.infrastructure.serverStateScope}
|
|
mutationIntentFactory={
|
|
composition.infrastructure.mutationIntentFactory
|
|
}
|
|
transitionFallback={
|
|
<div
|
|
aria-busy="true"
|
|
className="state-surface state-surface--loading"
|
|
data-scope-state="scope-transition"
|
|
/>
|
|
}
|
|
>
|
|
<ApplicationProvider application={composition.application}>
|
|
<PostMountRuntimeStarter composition={composition} />
|
|
<AppRouter
|
|
basename={composition.config.build.routerBasePath}
|
|
buildId={composition.release.buildId}
|
|
/>
|
|
</ApplicationProvider>
|
|
</ServerStateGenerationProvider>
|
|
</StrictMode>
|
|
);
|
|
}
|