44 lines
1.7 KiB
TypeScript
44 lines
1.7 KiB
TypeScript
import '@fontsource-variable/inter';
|
|
import '@fontsource-variable/jetbrains-mono';
|
|
import './tokens/reset.css'; // first: the cascade layer order is declared in its header
|
|
import './tokens/tokens.css';
|
|
|
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
import { StrictMode } from 'react';
|
|
import { createRoot } from 'react-dom/client';
|
|
import { RouterProvider, createBrowserRouter } from 'react-router';
|
|
|
|
import { ApiError, startMocking } from './api';
|
|
import { routes } from './routes';
|
|
import { Locale } from './ui/Locale';
|
|
|
|
const client = new QueryClient({
|
|
defaultOptions: {
|
|
queries: {
|
|
// A refusal is not a hiccup: retrying a 4xx repeats a request the platform already answered.
|
|
// Anything else gets two more tries, because a dropped connection usually is a hiccup.
|
|
retry: (attempt, error) =>
|
|
!(error instanceof ApiError && error.status >= 400 && error.status < 500) && attempt < 2,
|
|
// Refetch on window focus stays ON deliberately. It is the race the contract's revision guard
|
|
// exists for, and turning it off would hide the race instead of handling it.
|
|
staleTime: 15_000,
|
|
},
|
|
},
|
|
});
|
|
|
|
const root = document.getElementById('root');
|
|
if (!root) throw new Error('Root node #root not found in index.html');
|
|
|
|
// Awaited before the first render: a request that leaves before the mock is intercepting goes to
|
|
// the real network instead, and the failure looks like a broken fixture rather than a race.
|
|
await startMocking(window.location.pathname);
|
|
|
|
createRoot(root).render(
|
|
<StrictMode>
|
|
<QueryClientProvider client={client}>
|
|
<Locale>
|
|
<RouterProvider router={createBrowserRouter(routes)} />
|
|
</Locale>
|
|
</QueryClientProvider>
|
|
</StrictMode>,
|
|
);
|