- integrace Sentry na serveru (@sentry/node) i klientu (@sentry/react): chyby 5xx, pády a console logy se hlásí do self-hosted Sentry - nový veřejný endpoint GET /api/config — klient si z něj za běhu vyzvedne Sentry DSN (SENTRY_DSN / SENTRY_CLIENT_DSN v env) - ErrorBoundary na klientu a sourcemapy pro čitelné stack traces - oprava mapování stavu waiting_acceptance (zobrazoval se jako Příprava) - mapování stavů kurýra matched/accepted, logování přechodů stavů Bolt objednávek pro postupné zmapování nedokumentovaného API - simulátor Bolt ve vývoji nově prochází celou reálnou sekvenci stavů - vypnuté logování connect/disconnect websocket klientů
65 lines
2.3 KiB
TypeScript
65 lines
2.3 KiB
TypeScript
import React from 'react';
|
|
import ReactDOM from 'react-dom/client';
|
|
import { ProvideAuth } from './context/auth';
|
|
import 'react-toastify/dist/ReactToastify.css';
|
|
import './index.css';
|
|
import AppRoutes from './AppRoutes';
|
|
import { BrowserRouter } from 'react-router';
|
|
import { client } from '../../types/gen/client.gen';
|
|
import { getConfig } from '../../types/gen/sdk.gen';
|
|
import { getToken } from './Utils';
|
|
import { toast } from 'react-toastify';
|
|
import * as Sentry from '@sentry/react';
|
|
|
|
client.setConfig({
|
|
auth: () => getToken(),
|
|
baseUrl: '/api', // openapi-ts si to z nějakého důvodu neumí převzít z api.yml
|
|
});
|
|
|
|
// Sentry se inicializuje až podle runtime konfigurace ze serveru (bez DSN zůstává vypnuté).
|
|
// Klient je statický build, takže DSN nejde zapéct při buildu — server ho zná z env.
|
|
getConfig().then(({ data }) => {
|
|
if (data?.sentry.dsn) {
|
|
Sentry.init({
|
|
dsn: data.sentry.dsn,
|
|
environment: data.sentry.environment,
|
|
enableLogs: true,
|
|
});
|
|
}
|
|
}).catch(() => { /* config endpoint nedostupný — běžíme bez Sentry */ });
|
|
|
|
// Interceptor na vyhození toasteru při chybě
|
|
client.interceptors.response.use(async response => {
|
|
// TODO opravit - login je zatím výjimka, voláme ho "naprázdno" abychom zjistili, zda nás nepřihlásily trusted headers
|
|
if (!response.ok && !response.url.includes("/login")) {
|
|
const json = await response.json();
|
|
toast.error(json.error, { theme: "colored" });
|
|
// Serverové chyby hlásíme do Sentry; 4xx jsou očekávané (chyby uživatele)
|
|
if (response.status >= 500) {
|
|
Sentry.captureMessage(`API ${response.status}: ${new URL(response.url).pathname} — ${json.error}`, 'error');
|
|
}
|
|
}
|
|
return response;
|
|
});
|
|
|
|
const root = ReactDOM.createRoot(
|
|
document.getElementById('root') as HTMLElement
|
|
);
|
|
root.render(
|
|
<React.StrictMode>
|
|
<Sentry.ErrorBoundary fallback={
|
|
<div className="text-center p-5">
|
|
<h4>Něco se pokazilo 😕</h4>
|
|
<p>Chyba byla nahlášena. Zkuste stránku načíst znovu.</p>
|
|
<button className="btn btn-primary" onClick={() => window.location.reload()}>Načíst znovu</button>
|
|
</div>
|
|
}>
|
|
<BrowserRouter>
|
|
<ProvideAuth>
|
|
<AppRoutes />
|
|
</ProvideAuth>
|
|
</BrowserRouter>
|
|
</Sentry.ErrorBoundary>
|
|
</React.StrictMode>
|
|
);
|