import { lazy, Suspense, useState } from "react"; import { BrowserRouter, Route, Routes, useLocation, } from "react-router-dom"; import { getRoute, routePath } from "../../contracts/routes.js"; import { RouteBoundary } from "../boundaries/render-error-boundary.jsx"; import { AppShell } from "../layouts/app-shell.jsx"; import { PageHeader } from "../components/page-header.jsx"; import { SessionProvider, useSession } from "../providers/session-provider.jsx"; import { ThemeProvider } from "../providers/theme-provider.jsx"; import { decideRouteAccess } from "./navigation-policy.js"; const HomePage = lazy(() => import("../pages/home-page.jsx")); const UiGalleryPage = lazy(() => import("../examples/ui-gallery-page.jsx")); const StateGalleryPage = lazy( () => import("../examples/state-gallery-page.jsx"), ); const AuthExamplePage = lazy( () => import("../examples/auth-example-page.jsx"), ); const SampleContractPage = lazy( () => import("../pages/sample-contract-page.jsx"), ); const NotFoundPage = lazy(() => import("../pages/not-found-page.jsx")); /** @param {{ routeId: string }} props */ function RouteLoadingSurface({ routeId }) { const definition = getRoute(routeId); return (
); } function RouteFailureSurface() { return (
); } /** * @param {{ * routeId: string, * buildId: string, * telemetry?: import("../../application/ports/telemetry-port.js").TelemetryPort, * children: React.ReactNode * }} props */ function RouteSurface({ routeId, buildId, telemetry, children }) { return ( } > }> {children} ); } /** * @param {{ * routeId: string, * children: React.ReactNode * }} props */ function ProtectedRoute({ routeId, children }) { const location = useLocation(); const { sessionState, beginSignIn, recover } = useSession(); const [pending, setPending] = useState(false); const [failed, setFailed] = useState(false); const decision = decideRouteAccess(routeId, sessionState); async function continueSession() { setPending(true); setFailed(false); try { if (decision.action === "wait-for-session") { await recover(); } else { await beginSignIn( `${location.pathname}${location.search}${location.hash}`, ); } } catch { setFailed(true); } finally { setPending(false); } } if (decision.allowed) return children; if (sessionState === "integration-failed") { return (
); } const recovering = decision.action === "wait-for-session"; return (
{failed ? (

세션 작업을 완료하지 못했습니다.

) : null}
); } /** * @param {{ * routeId: string, * buildId: string, * telemetry?: import("../../application/ports/telemetry-port.js").TelemetryPort, * children: React.ReactNode * }} props */ function PublicRoute({ routeId, buildId, telemetry, children }) { return ( {children} ); } /** * @param {{ * authSession: import("../../application/ports/auth-session-port.js").AuthSessionPort, * basename?: string, * buildId?: string, * storage?: import("../../application/ports/storage-port.js").StoragePort, * telemetry?: import("../../application/ports/telemetry-port.js").TelemetryPort * }} props */ export function AppRouter({ authSession, basename = "/", buildId = "local-build", storage, telemetry, }) { return ( }> } /> } /> } /> } /> } /> } /> ); }