Continuous Integration / config (pull_request) Successful in 11s
Continuous Integration / changes (pull_request) Successful in 21s
Continuous Integration / backend-build (pull_request) Skipped
Continuous Integration / backend-test (pull_request) Skipped
Continuous Integration / vulnerability-scan (pull_request) Skipped
Continuous Integration / frontend-prepare (pull_request) Successful in 1m37s
Continuous Integration / frontend-build (pull_request) Successful in 2m12s
Continuous Integration / frontend-test (pull_request) Successful in 4m42s
Continuous Integration / frontend-lint (pull_request) Successful in 2m2s
Continuous Integration / publish-production (pull_request) Skipped
Continuous Integration / deploy-production (pull_request) Skipped
Continuous Integration / publish-test (pull_request) Successful in 6m51s
Continuous Integration / deploy-test (pull_request) Skipped
Groups auth, setup, invitation, profile, users, cms, availability and system code (services/hooks, components, schemas, mocks, pages) under src/features/<name> instead of splitting by technical layer (api/, components/, lib/schemas/, mocks/, pages/). Renames the old connection-oriented `api` layer to `services` per feature, and splits the monolithic api/types.ts into per-feature types.ts files (with ProblemDetails/ApiResult merged into lib/api-client.ts as shared infra). Layout-agnostic code (ui primitives, app shell, i18n, test utils, lib) stays at the top level. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
80 lines
2.8 KiB
TypeScript
80 lines
2.8 KiB
TypeScript
import { StrictMode } from 'react';
|
|
import { createRoot } from 'react-dom/client';
|
|
import { RouterProvider } from '@tanstack/react-router';
|
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
import './index.css';
|
|
import './i18n/config';
|
|
import { AuthProvider } from '@/features/auth/context/AuthProvider';
|
|
import { useAuth } from '@/features/auth/context/auth-context';
|
|
import { Toaster } from '@/components/ui/sonner';
|
|
import { router } from '@/router';
|
|
import { getAppConfig } from '@/lib/config';
|
|
import { initSentry } from '@/lib/sentry';
|
|
import { SentryErrorBoundary } from '@/components/SentryErrorBoundary';
|
|
import { UmamiAnalytics } from '@/components/UmamiAnalytics';
|
|
|
|
// First, before the query client and before render, so an error during startup is still captured.
|
|
// A no-op when no DSN is configured.
|
|
initSentry();
|
|
|
|
document.title = getAppConfig().appTitle;
|
|
|
|
const queryClient = new QueryClient({
|
|
defaultOptions: {
|
|
queries: { retry: 1, refetchOnWindowFocus: true },
|
|
},
|
|
});
|
|
|
|
function BootstrapSplash() {
|
|
return (
|
|
<div className="flex min-h-svh items-center justify-center text-muted-foreground">
|
|
<span className="h-6 w-6 animate-spin rounded-full border-2 border-primary border-t-transparent" />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Renders the router only once the initial silent refresh has settled, so the
|
|
* route guards see a definitive auth state rather than the transient loading one.
|
|
*/
|
|
function InnerApp() {
|
|
const auth = useAuth();
|
|
if (auth.status === 'loading') {
|
|
return <BootstrapSplash />;
|
|
}
|
|
return <RouterProvider router={router} context={{ auth }} />;
|
|
}
|
|
|
|
async function enableMocking(): Promise<void> {
|
|
if (import.meta.env.VITE_ENABLE_MSW !== 'true') {
|
|
return;
|
|
}
|
|
const { worker } = await import('@/mocks/browser');
|
|
await worker.start({ onUnhandledRequest: 'bypass' });
|
|
}
|
|
|
|
void enableMocking().then(() => {
|
|
const rootElement = document.getElementById('root');
|
|
if (rootElement === null) {
|
|
throw new Error('Root element #root not found');
|
|
}
|
|
createRoot(rootElement).render(
|
|
<StrictMode>
|
|
<QueryClientProvider client={queryClient}>
|
|
<AuthProvider>
|
|
{/*
|
|
* Inside AuthProvider, not outermost: the fallback has to be reachable for a
|
|
* logged-in user, and a render error inside a page must not tear down the
|
|
* session context — otherwise recovering would also log the user out.
|
|
*/}
|
|
<SentryErrorBoundary>
|
|
<InnerApp />
|
|
<UmamiAnalytics />
|
|
</SentryErrorBoundary>
|
|
<Toaster />
|
|
</AuthProvider>
|
|
</QueryClientProvider>
|
|
</StrictMode>,
|
|
);
|
|
});
|