diff --git a/client/package.json b/client/package.json index ac5e33b..15cee77 100644 --- a/client/package.json +++ b/client/package.json @@ -10,6 +10,7 @@ "@fortawesome/free-regular-svg-icons": "^7.1.0", "@fortawesome/free-solid-svg-icons": "^7.1.0", "@fortawesome/react-fontawesome": "^3.1.0", + "@sentry/react": "^10.65.0", "@types/jest": "^30.0.0", "@types/node": "^24.10.0", "@types/react": "^19.2.2", diff --git a/client/src/components/BoltOrderProgress.tsx b/client/src/components/BoltOrderProgress.tsx index 86546ee..a29d0be 100644 --- a/client/src/components/BoltOrderProgress.tsx +++ b/client/src/components/BoltOrderProgress.tsx @@ -14,6 +14,7 @@ const STEPS = ['Přijato', 'Příprava', 'Vyzvedávání', 'Na cestě', 'Doruče const ORDER_STATE_TO_STEP: Record = { created: 0, pending: 0, + waiting_acceptance: 0, accepted: 0, waiting_preparation: 0, preparing: 1, @@ -31,6 +32,8 @@ const ORDER_STATE_TO_STEP: Record = { /** Stavy kurýra z Bolt API → index kroku. Kurýr u podniku ještě neznamená "na cestě". */ const COURIER_STATE_TO_STEP: Record = { + matched: 0, + accepted: 0, heading_to_provider: 1, arrived_to_provider: 1, picked_up: 3, @@ -49,6 +52,7 @@ function stepForOrderState(state: string): number | 'cancelled' { if (s in ORDER_STATE_TO_STEP) return ORDER_STATE_TO_STEP[s]; if (/cancel|reject|fail/.test(s)) return 'cancelled'; if (/delivered|finished/.test(s)) return 4; + if (/accept|pending|created/.test(s)) return 0; if (/^waiting|prepar|ready|cook/.test(s)) return 1; if (/picked|delivering|heading_to_client|transport/.test(s)) return 3; return 0; diff --git a/client/src/index.tsx b/client/src/index.tsx index 291f77c..b37f9f7 100644 --- a/client/src/index.tsx +++ b/client/src/index.tsx @@ -6,20 +6,38 @@ 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; }); @@ -29,10 +47,18 @@ const root = ReactDOM.createRoot( ); root.render( - - - - - + +

Něco se pokazilo 😕

+

Chyba byla nahlášena. Zkuste stránku načíst znovu.

+ + + }> + + + + + +
); diff --git a/client/vite.config.ts b/client/vite.config.ts index 31e4154..0bb988d 100644 --- a/client/vite.config.ts +++ b/client/vite.config.ts @@ -6,6 +6,10 @@ export default defineConfig({ // depending on your application, base can also be "/" base: '', plugins: [react(), viteTsconfigPaths()], + build: { + // Veřejné sourcemapy, aby Sentry umělo přeložit minifikované stack traces + sourcemap: true, + }, server: { open: true, host: '0.0.0.0', diff --git a/client/yarn.lock b/client/yarn.lock index 45ea971..dfecb29 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -854,6 +854,70 @@ resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.55.1.tgz#f79437939020b83057faf07e98365b1fa51c458b" integrity sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw== +"@sentry/browser-utils@10.65.0": + version "10.65.0" + resolved "https://registry.yarnpkg.com/@sentry/browser-utils/-/browser-utils-10.65.0.tgz#e3b67c6b9dd05dad2ad7eee82ad873bfc9f8ab12" + integrity sha512-4J0mkfNJAGUOkpg1ZggizyftFTn9N20b+Jl87UnWsDUkNG0Ic1l/FIzMPTVxXrAnhBGu0ULO0TFWMoQ5s3QtZw== + dependencies: + "@sentry/conventions" "^0.15.1" + "@sentry/core" "10.65.0" + +"@sentry/browser@10.65.0": + version "10.65.0" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-10.65.0.tgz#e2734a2effe051a9005afdd914fc07c68262f627" + integrity sha512-XUDDsx0qxzeIlcOu1fDEqTcDl0eiOqghsgV+ReuuNP4jYjZ9kUQxE3rXWM5mlT1pBi4VaQ4FHqvQZZrRXy+oDw== + dependencies: + "@sentry/browser-utils" "10.65.0" + "@sentry/conventions" "^0.15.1" + "@sentry/core" "10.65.0" + "@sentry/feedback" "10.65.0" + "@sentry/replay" "10.65.0" + "@sentry/replay-canvas" "10.65.0" + +"@sentry/conventions@^0.15.1": + version "0.15.1" + resolved "https://registry.yarnpkg.com/@sentry/conventions/-/conventions-0.15.1.tgz#5b8888862d1e444678938f5afdd7842bca42f7cc" + integrity sha512-ZLP8bRdMON3prWE2tJyImuYscCxdcJeIPIhrOs/rgyFm3C1nCh1B6gdvPj3AZ5zW08oSFFCsq7T+tYEW3h8MNA== + +"@sentry/core@10.65.0": + version "10.65.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-10.65.0.tgz#a98cfd6e138d9658dd42d050902837ff591452e8" + integrity sha512-3aqtmM5NgNGo45BNaaBzi0LPQZAw//NEL4HKS5fXm12pJMa4KEkze8DEKnkTEIrGnWaOJKamecHKlnNg/Mqf/Q== + dependencies: + "@sentry/conventions" "^0.15.1" + +"@sentry/feedback@10.65.0": + version "10.65.0" + resolved "https://registry.yarnpkg.com/@sentry/feedback/-/feedback-10.65.0.tgz#a9418cc77c835e3a74cdc3fad2fb1098ecbc3887" + integrity sha512-ck8h7wgd3F3bYNk0v1OgohmyLBeXcKxqlfBJRtQq4k6KZUq+pXimOG7ckNguVMYjCo3PEfuG+ckKc21yqotKug== + dependencies: + "@sentry/core" "10.65.0" + +"@sentry/react@^10.65.0": + version "10.65.0" + resolved "https://registry.yarnpkg.com/@sentry/react/-/react-10.65.0.tgz#83552b6e136d827782915bf4002ff5916dc11ccc" + integrity sha512-fvHxpuvid0wt9/1N3itcKDyKOjqmYHw3MBSt5Pki3Iz4CL2CmgQp9ZFv/CA7UhMnEvn2Gd+Qc2UKxujZWd8FLg== + dependencies: + "@sentry/browser" "10.65.0" + "@sentry/conventions" "^0.15.1" + "@sentry/core" "10.65.0" + +"@sentry/replay-canvas@10.65.0": + version "10.65.0" + resolved "https://registry.yarnpkg.com/@sentry/replay-canvas/-/replay-canvas-10.65.0.tgz#5ff20832ae8acacd38fe7f154dd7ac6c6cad1af2" + integrity sha512-A7X3RVk1Gk+knK8Ip/2EjejckNCLgCfRZo6eGlsy6qyz904KBpYmys1a0o7QkzFRjhIndjHAfcVxwt6jSLJlrQ== + dependencies: + "@sentry/core" "10.65.0" + "@sentry/replay" "10.65.0" + +"@sentry/replay@10.65.0": + version "10.65.0" + resolved "https://registry.yarnpkg.com/@sentry/replay/-/replay-10.65.0.tgz#8ed1255349e32faeac786e4ca2f4c2f56b98e64e" + integrity sha512-aW988CcQBNArbOMzOFOziipHz6uQyXSa4i5CPWsu+nhVPTJHafosi5Lv9n6NM/icDX5e23VdnX6mZd8SyJuo8A== + dependencies: + "@sentry/browser-utils" "10.65.0" + "@sentry/core" "10.65.0" + "@sinclair/typebox@^0.34.0": version "0.34.41" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.34.41.tgz#aa51a6c1946df2c5a11494a2cdb9318e026db16c" diff --git a/server/.env.template b/server/.env.template index 108594f..767efc9 100644 --- a/server/.env.template +++ b/server/.env.template @@ -56,3 +56,9 @@ # Interval (ms) scheduleru sledování objednávek Bolt Food. Výchozí 60000 (60 s). # Pro vývoj se simulací lze zkrátit (min. 1000), aby se změny stavu projevily rychleji. # BOLT_POLL_INTERVAL_MS=3000 + +# Sentry (volitelné) — když není vyplněno, Sentry se vůbec neaktivuje. +# Server hlásí chyby (5xx, pády) a přeposílá console logy jako Sentry Logs. +# SENTRY_DSN=https://...@sentry.example.com/1 +# DSN pro prohlížeč (klient si ho vyzvedne z GET /api/config). Když není vyplněno, použije se SENTRY_DSN. +# SENTRY_CLIENT_DSN=https://...@sentry.example.com/2 diff --git a/server/changelogs/2026-07-14.json b/server/changelogs/2026-07-14.json new file mode 100644 index 0000000..5418180 --- /dev/null +++ b/server/changelogs/2026-07-14.json @@ -0,0 +1,3 @@ +[ + "Oprava zobrazení stavu objednávky Bolt Food — objednávka čekající na přijetí podnikem se už nezobrazuje jako v přípravě" +] diff --git a/server/package.json b/server/package.json index e07de94..c86d57a 100644 --- a/server/package.json +++ b/server/package.json @@ -30,6 +30,7 @@ "typescript": "^5.9.3" }, "dependencies": { + "@sentry/node": "^10.65.0", "@socket.io/redis-adapter": "^8.3.0", "axios": "^1.13.2", "cheerio": "^1.1.2", diff --git a/server/src/boltSimulator.ts b/server/src/boltSimulator.ts index 5a7cf38..bef7d09 100644 --- a/server/src/boltSimulator.ts +++ b/server/src/boltSimulator.ts @@ -44,8 +44,10 @@ interface Simulation { * (Přijato → Příprava → Vyzvedávání → Na cestě → Doručeno). */ export const DEFAULT_SCENARIO: SimStep[] = [ + { order_state: 'waiting_acceptance', etaSeconds: 2100 }, { order_state: 'accepted', etaSeconds: 1800 }, - { order_state: 'preparing', etaSeconds: 1500 }, + { order_state: 'waiting_preparation', courier_state: 'accepted', etaSeconds: 1800 }, + { order_state: 'preparing', courier_state: 'heading_to_provider', etaSeconds: 1500 }, { order_state: 'waiting_delivery', courier_state: 'arrived_to_provider', etaSeconds: 900 }, { order_state: 'in_delivery', courier_state: 'heading_to_client', etaSeconds: 300 }, { order_state: 'delivered', courier_state: 'delivered', etaSeconds: 0 }, diff --git a/server/src/boltTracking.ts b/server/src/boltTracking.ts index ede2e98..8719a4d 100644 --- a/server/src/boltTracking.ts +++ b/server/src/boltTracking.ts @@ -66,14 +66,14 @@ export async function pollBoltOrder(token: string): Promise { } const res = await axios.post(BOLT_POLLING_URL, { token }, { params: { - version: 'FW.1.111', + version: 'FW.1.113', language: 'cs-CZ', country: 'cz', device_name: 'web', device_os_version: 'web', deviceType: 'web', session_id: DEVICE_ID, - distinct_id: DEVICE_ID, + distinct_id: `$device:${DEVICE_ID}`, deviceId: DEVICE_ID, }, headers: { 'Content-Type': 'application/json' }, @@ -143,6 +143,15 @@ export async function checkBoltTracking(): Promise { const courierChanged = courierState !== group.boltCourierState && !clearToken; if (!clearToken && !timeChanged && !stateChanged && !courierChanged) continue; + // Log každého přechodu stavu — Bolt API není dokumentované, takže si takhle + // průběžně mapujeme jeho stavový automat (viz mapování v BoltOrderProgress.tsx). + if (stateChanged || courierChanged) { + console.log( + `Bolt tracking: skupina "${group.name}" stav ${group.boltOrderState ?? '(žádný)'} → ${orderState ?? '(žádný)'}` + + `, kurýr ${group.boltCourierState ?? '(žádný)'} → ${courierState ?? '(žádný)'}` + ); + } + updated = await storage.updateData(key, current => { const d = current ?? data!; const g = d.groups?.find(x => x.id === group.id); diff --git a/server/src/index.ts b/server/src/index.ts index 2d20e95..754822d 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -1,3 +1,5 @@ +import './instrument'; // Sentry — musí být první import (auto-instrumentace) +import * as Sentry from '@sentry/node'; import express from "express"; import bodyParser from "body-parser"; import cors from 'cors'; @@ -98,6 +100,9 @@ async function shutdown(signal: string) { await shutdownRedisStorage(); } + // Flush zbývajících Sentry eventů/logů (no-op, když Sentry není inicializované) + await Sentry.close(2000); + console.log('Graceful shutdown complete'); process.exit(0); } @@ -122,6 +127,16 @@ app.get("/api/health/ready", async (_req, res) => { res.status(200).json({ ok: true }); }); +/** Veřejná runtime konfigurace pro klienta (Sentry DSN apod.). */ +app.get("/api/config", (_req, res) => { + res.status(200).json({ + sentry: { + dsn: process.env.SENTRY_CLIENT_DSN ?? process.env.SENTRY_DSN ?? null, + environment: ENVIRONMENT, + }, + }); +}); + app.get("/api/whoami", (req, res) => { if (!HTTP_REMOTE_USER_ENABLED) { res.status(403).json({ error: 'Není zapnuté přihlášení z hlaviček' }); @@ -264,6 +279,10 @@ app.get('*splat', (_req, res) => { res.sendFile(path.join(process.cwd(), 'public', 'index.html')); }); +// Sentry error handler — hlásí jen 5xx (výchozí shouldHandleError), očekávané +// chyby (403/409) do Sentry nepadají. Musí být před vlastním error middlewarem. +Sentry.setupExpressErrorHandler(app); + // Error handling middleware app.use((err: any, req: any, res: any, next: any) => { if (err instanceof InsufficientPermissions) { diff --git a/server/src/instrument.ts b/server/src/instrument.ts new file mode 100644 index 0000000..e6a13b9 --- /dev/null +++ b/server/src/instrument.ts @@ -0,0 +1,19 @@ +import * as Sentry from '@sentry/node'; +import dotenv from 'dotenv'; +import path from 'path'; + +// Sentry se musí inicializovat před načtením ostatních modulů (auto-instrumentace), +// proto si tento soubor načítá .env sám — index.ts na to dojde až po importech. +dotenv.config({ path: path.resolve(__dirname, `../.env.${process.env.NODE_ENV ?? 'production'}`) }); + +// Bez SENTRY_DSN (dev, Jest, E2E) zůstává Sentry úplně vypnuté. +if (process.env.SENTRY_DSN) { + Sentry.init({ + dsn: process.env.SENTRY_DSN, + environment: process.env.NODE_ENV ?? 'production', + enableLogs: true, + // Přeposílá console.log/warn/error jako Sentry Logs — mj. přechody stavů Bolt trackingu + integrations: [Sentry.consoleLoggingIntegration({ levels: ['log', 'warn', 'error'] })], + }); + console.log('Sentry: inicializováno'); +} diff --git a/server/src/tests/boltTracking.test.ts b/server/src/tests/boltTracking.test.ts index 97ff677..85bec33 100644 --- a/server/src/tests/boltTracking.test.ts +++ b/server/src/tests/boltTracking.test.ts @@ -291,18 +291,18 @@ describe('DEV simulace (boltSimulator + checkBoltTracking)', () => { expect(mockedAxios.post).not.toHaveBeenCalled(); }); - test('první poll nastaví stav accepted a ETA', async () => { + test('první poll nastaví stav waiting_acceptance a ETA', async () => { await checkBoltTracking(); const g = await getGroup(); - expect(g.boltOrderState).toBe('accepted'); - expect(g.deliveryAt).toBe(computeDeliveryHHMM(1800)); + expect(g.boltOrderState).toBe('waiting_acceptance'); + expect(g.deliveryAt).toBe(computeDeliveryHHMM(2100)); }); - test('advance posune sekvenci na preparing', async () => { + test('advance posune sekvenci na accepted', async () => { await checkBoltTracking(); advanceBoltSimulation(groupId); await checkBoltTracking(); - expect((await getGroup()).boltOrderState).toBe('preparing'); + expect((await getGroup()).boltOrderState).toBe('accepted'); }); test('ruční nastavení stavu (override) se projeví při pollu', async () => { diff --git a/server/src/websocket.ts b/server/src/websocket.ts index 39403cb..394b9b7 100644 --- a/server/src/websocket.ts +++ b/server/src/websocket.ts @@ -12,7 +12,7 @@ export const initWebsocket = (server: any) => { transports: ["websocket"], }); io.on("connection", (socket) => { - console.log(`New client connected: ${socket.id}`); + // console.log(`New client connected: ${socket.id}`); socket.on("join", (login: string) => { if (login && typeof login === "string") { @@ -25,7 +25,7 @@ export const initWebsocket = (server: any) => { }); socket.on("disconnect", () => { - console.log(`Client disconnected: ${socket.id}`); + // console.log(`Client disconnected: ${socket.id}`); }); }); return io; diff --git a/server/yarn.lock b/server/yarn.lock index 3fecb88..c006898 100644 --- a/server/yarn.lock +++ b/server/yarn.lock @@ -10,6 +10,37 @@ "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.24" +"@apm-js-collab/code-transformer-bundler-plugins@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@apm-js-collab/code-transformer-bundler-plugins/-/code-transformer-bundler-plugins-0.5.0.tgz#8a08136e8281f7e8e36ac6810d2b122c5917de93" + integrity sha512-YxLBY5nGlurL7QeJLq6e5g0ouBpAp0pwgyA/5rHXEXwhiPLn9ZHbT+Y2LlP90GT872cSocfjWRYu/fnpuBudNQ== + dependencies: + "@apm-js-collab/code-transformer" "^0.15.0" + es-module-lexer "^2.1.0" + magic-string "^0.30.21" + module-details-from-path "^1.0.4" + +"@apm-js-collab/code-transformer@^0.15.0": + version "0.15.0" + resolved "https://registry.yarnpkg.com/@apm-js-collab/code-transformer/-/code-transformer-0.15.0.tgz#a3a1b6c7b92db16f8277636b4a72a1626e2fa52a" + integrity sha512-XmXYVs8CzJ1Aj79noVbn2weUO/XWtRyURpGqx7aU7DOXlUQhR0WKOQNF0okh7PCeY37vxf7kU3v57OAkEPm3ww== + dependencies: + "@types/estree" "^1.0.8" + astring "^1.9.0" + esquery "^1.7.0" + meriyah "^6.1.4" + semifies "^1.0.0" + source-map "^0.6.0" + +"@apm-js-collab/tracing-hooks@^0.10.1": + version "0.10.1" + resolved "https://registry.yarnpkg.com/@apm-js-collab/tracing-hooks/-/tracing-hooks-0.10.1.tgz#52a463f6dd03e99582a7dde9816257efabdf63b9" + integrity sha512-w2OWXR7FWrKqSziuE9+QclaZrStxO/8+OwbXM635s/zs0Eez1Qo3ivSPdB2WsaPY/iznKTytONPx/PitD7IXcA== + dependencies: + "@apm-js-collab/code-transformer" "^0.15.0" + debug "^4.4.1" + module-details-from-path "^1.0.4" + "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.25.9", "@babel/code-frame@^7.26.0", "@babel/code-frame@^7.26.2": version "7.26.2" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85" @@ -1410,7 +1441,7 @@ resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0", "@jridgewell/sourcemap-codec@^1.5.5": version "1.5.5" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba" integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== @@ -1453,6 +1484,66 @@ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.8.0.tgz#cee43d801fcef9644b11b8194857695acd5f815a" integrity sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A== +"@opentelemetry/api-logs@0.220.0": + version "0.220.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/api-logs/-/api-logs-0.220.0.tgz#b2ed235de4b5f3c1769adfa5f3bc247d82cdfbc9" + integrity sha512-CmVa4ImJ+ynfrPMNaAXHET6Bhb44SwzmfyVJFq9ni2jgXJR/l7C6gfVFddNmHP+ZOkP9cf4f9DBe68qVLTHc9w== + dependencies: + "@opentelemetry/api" "^1.3.0" + +"@opentelemetry/api@^1.3.0", "@opentelemetry/api@^1.9.1": + version "1.9.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.9.1.tgz#c1b0346de336ba55af2d5a7970882037baedec05" + integrity sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q== + +"@opentelemetry/core@2.9.0": + version "2.9.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-2.9.0.tgz#49de86106f86255b471b2ff035ef1003a851b252" + integrity sha512-m2nckMT80NnmjTYSPjJQObBJ+8dgkoajEOUbznL8AHZ3T3yHRk2P7gI1PhEBc1+lOnrYE9UWrWHqJDsmqjmNbw== + dependencies: + "@opentelemetry/semantic-conventions" "^1.29.0" + +"@opentelemetry/instrumentation@^0.220.0": + version "0.220.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.220.0.tgz#542b36bf4871dd83dc84e1373ac4bbcd35a8bfb8" + integrity sha512-xQx3E2WxP1mDvKzxLxX+CTCtNLa560YJZ3087qYHerl2YmiKpv7AH+dAy7vmx+eVrZ5BwhfWUAVoKOoxCNHcpw== + dependencies: + "@opentelemetry/api-logs" "0.220.0" + import-in-the-middle "^3.0.0" + require-in-the-middle "^8.0.0" + +"@opentelemetry/resources@2.9.0": + version "2.9.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-2.9.0.tgz#81e1ce946eec661857a9d6c4fa507b3750ae500f" + integrity sha512-jyA5MBLQ+Dkl3+JsZkUoUvL7yHvU64kLsvpXKarWm6347Sl1t1bXFTFykUePNpT5WH5pm9a2Qtt03iIYQhZ1Fg== + dependencies: + "@opentelemetry/core" "2.9.0" + "@opentelemetry/semantic-conventions" "^1.29.0" + +"@opentelemetry/sdk-trace-base@^2.9.0": + version "2.9.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.9.0.tgz#34e314486127ce0ad596757a10c4c6f8ed435385" + integrity sha512-cp9zmTl62R8PJrpvFcmc8N2JQU/xfa0S+61q511Nji+QxCfZ8Ifvg7H27G8cANe4crg4RTrWsVvanHiXjSp6ag== + dependencies: + "@opentelemetry/core" "2.9.0" + "@opentelemetry/resources" "2.9.0" + "@opentelemetry/sdk-trace" "2.9.0" + "@opentelemetry/semantic-conventions" "^1.29.0" + +"@opentelemetry/sdk-trace@2.9.0": + version "2.9.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace/-/sdk-trace-2.9.0.tgz#c82103a11a712b31ac9281b706fc5dc76d126ae6" + integrity sha512-sGA19HvtrrSKYsseHphluH6j3p6Xa3fqc7c7y8f/7mYWejc1lyDFcpSdD1kYa50HCLUeEo4zA5bW0pniaPszuw== + dependencies: + "@opentelemetry/core" "2.9.0" + "@opentelemetry/resources" "2.9.0" + "@opentelemetry/semantic-conventions" "^1.29.0" + +"@opentelemetry/semantic-conventions@^1.29.0": + version "1.43.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.43.0.tgz#f3f467e36c27332f0e735ec86cdcd78dd6f27865" + integrity sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg== + "@paralleldrive/cuid2@^2.2.2": version "2.3.1" resolved "https://registry.yarnpkg.com/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz#3d62ea9e7be867d3fa94b9897fab5b0ae187d784" @@ -1497,6 +1588,63 @@ resolved "https://registry.yarnpkg.com/@redis/time-series/-/time-series-5.10.0.tgz#9c7de35fe023e36233fba5c8478ce25832ead64c" integrity sha512-cPkpddXH5kc/SdRhF0YG0qtjL+noqFT0AcHbQ6axhsPsO7iqPi1cjxgdkE9TNeKiBUUdCaU1DbqkR/LzbzPBhg== +"@sentry/conventions@^0.15.1": + version "0.15.1" + resolved "https://registry.yarnpkg.com/@sentry/conventions/-/conventions-0.15.1.tgz#5b8888862d1e444678938f5afdd7842bca42f7cc" + integrity sha512-ZLP8bRdMON3prWE2tJyImuYscCxdcJeIPIhrOs/rgyFm3C1nCh1B6gdvPj3AZ5zW08oSFFCsq7T+tYEW3h8MNA== + +"@sentry/core@10.65.0": + version "10.65.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-10.65.0.tgz#a98cfd6e138d9658dd42d050902837ff591452e8" + integrity sha512-3aqtmM5NgNGo45BNaaBzi0LPQZAw//NEL4HKS5fXm12pJMa4KEkze8DEKnkTEIrGnWaOJKamecHKlnNg/Mqf/Q== + dependencies: + "@sentry/conventions" "^0.15.1" + +"@sentry/node-core@10.65.0": + version "10.65.0" + resolved "https://registry.yarnpkg.com/@sentry/node-core/-/node-core-10.65.0.tgz#76a59b08947da74d0037d0e84d8074818b4a4aa1" + integrity sha512-U01X9mPT+jZnsLPmPWfBU67Ka+t/Sdd9RGAuvGoKdrI6N47a/9PDkM9oCW+kj0fmZwogZHTgSnzJU5oi3pImgA== + dependencies: + "@sentry/conventions" "^0.15.1" + "@sentry/core" "10.65.0" + "@sentry/opentelemetry" "10.65.0" + import-in-the-middle "^3.0.0" + +"@sentry/node@^10.65.0": + version "10.65.0" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-10.65.0.tgz#770bf37552d04f649eaa3a7e2ac6e568aed9b8ba" + integrity sha512-t35dcdyksysVch/m/XdLgGJqGKJhr9eMD30Ctn3TeQ8yMB0wNXySfjPR5Yg93fpjmfaHtzc6iYIXRAvgNVfrvA== + dependencies: + "@opentelemetry/api" "^1.9.1" + "@opentelemetry/instrumentation" "^0.220.0" + "@opentelemetry/sdk-trace-base" "^2.9.0" + "@sentry/conventions" "^0.15.1" + "@sentry/core" "10.65.0" + "@sentry/node-core" "10.65.0" + "@sentry/opentelemetry" "10.65.0" + "@sentry/server-utils" "10.65.0" + import-in-the-middle "^3.0.0" + +"@sentry/opentelemetry@10.65.0": + version "10.65.0" + resolved "https://registry.yarnpkg.com/@sentry/opentelemetry/-/opentelemetry-10.65.0.tgz#ffdef3b3dd2b06707a2c0bc5313a4414f2f549d8" + integrity sha512-8C6FPvm3XBvUrkM52dX3Gz0p2H0Ij8t4sahUA+GTiCz0WM0fnyPeQPGC/b6I4jamV9UXyCZRnE1UEEGCoD+c7A== + dependencies: + "@sentry/conventions" "^0.15.1" + "@sentry/core" "10.65.0" + +"@sentry/server-utils@10.65.0": + version "10.65.0" + resolved "https://registry.yarnpkg.com/@sentry/server-utils/-/server-utils-10.65.0.tgz#7a261a5591c7451a82ce06ed95af5e2c4dbd6ab0" + integrity sha512-80toEFD6s+0Le7jrYB6pHWLF703WSg0WyavAWqrBGWG8JkREHgedAxzFYgoY5GlMI756qk6Ea7UzhJTHd2zAXA== + dependencies: + "@apm-js-collab/code-transformer" "^0.15.0" + "@apm-js-collab/code-transformer-bundler-plugins" "^0.5.0" + "@apm-js-collab/tracing-hooks" "^0.10.1" + "@sentry/conventions" "^0.15.1" + "@sentry/core" "10.65.0" + magic-string "~0.30.0" + "@sinclair/typebox@^0.34.0": version "0.34.41" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.34.41.tgz#aa51a6c1946df2c5a11494a2cdb9318e026db16c" @@ -1627,6 +1775,11 @@ dependencies: "@types/node" "*" +"@types/estree@^1.0.8": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.9.tgz#cf3f0e876d7bee15a93ab925b82bf570a3904a24" + integrity sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg== + "@types/express-serve-static-core@^5.0.0": version "5.1.1" resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-5.1.1.tgz#1a77faffee9572d39124933259be2523837d7eaa" @@ -2004,6 +2157,11 @@ asn1.js@^5.3.0: minimalistic-assert "^1.0.0" safer-buffer "^2.1.0" +astring@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/astring/-/astring-1.9.0.tgz#cc73e6062a7eb03e7d19c22d8b0b3451fd9bfeef" + integrity sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg== + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -2305,6 +2463,11 @@ cjs-module-lexer@^2.1.0: resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-2.1.0.tgz#586e87d4341cb2661850ece5190232ccdebcff8b" integrity sha512-UX0OwmYRYQQetfrLEZeewIFFI+wSTofC+pMBLNuH3RUuu/xzG1oz84UCEDOSoQlN3fZ4+AzmV50ZYvGqkMh9yA== +cjs-module-lexer@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz#b3ca5101843389259ade7d88c77bd06ce55849ca" + integrity sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ== + cliui@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" @@ -2433,7 +2596,7 @@ css-what@^6.1.0: resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== -debug@4, debug@^4, debug@^4.1.0, debug@^4.3.1, debug@^4.3.7, debug@^4.4.0, debug@^4.4.1, debug@^4.4.3, debug@~4.4.1: +debug@4, debug@^4, debug@^4.1.0, debug@^4.3.1, debug@^4.3.5, debug@^4.3.7, debug@^4.4.0, debug@^4.4.1, debug@^4.4.3, debug@~4.4.1: version "4.4.3" resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== @@ -2642,6 +2805,11 @@ es-errors@^1.3.0: resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== +es-module-lexer@^2.1.0, es-module-lexer@^2.2.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-2.3.1.tgz#5bf2df06999dbbe5f006a5f46a11fb9f5b7b391b" + integrity sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA== + es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" @@ -2679,6 +2847,18 @@ esprima@^4.0.0: resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== +esquery@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.7.0.tgz#08d048f261f0ddedb5bae95f46809463d9c9496d" + integrity sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g== + dependencies: + estraverse "^5.1.0" + +estraverse@^5.1.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -3060,6 +3240,15 @@ ignore-by-default@^1.0.1: resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" integrity sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA== +import-in-the-middle@^3.0.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-3.3.1.tgz#4fe3b46cc1b4573b00bc69343e5f9bbf25679743" + integrity sha512-0rymlHSFLwZ0ixx8DaQkoIyZojJPY2a0K2nEYslhKJ6jIYO/m0IcCb7iQsFPmS7WmKwISZiIrv5Icstrw/CmqA== + dependencies: + cjs-module-lexer "^2.2.0" + es-module-lexer "^2.2.0" + module-details-from-path "^1.0.4" + import-local@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.2.0.tgz#c3d5c745798c02a6f8b897726aba5100186ee260" @@ -3689,6 +3878,13 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" +magic-string@^0.30.21, magic-string@~0.30.0: + version "0.30.21" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.21.tgz#56763ec09a0fa8091df27879fd94d19078c00d91" + integrity sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.5" + make-dir@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" @@ -3728,6 +3924,11 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== +meriyah@^6.1.4: + version "6.1.4" + resolved "https://registry.yarnpkg.com/meriyah/-/meriyah-6.1.4.tgz#2d49a8934fbcd9205c20564579c3560d9b1e077b" + integrity sha512-Sz8FzjzI0kN13GK/6MVEsVzMZEPvOhnmmI1lU5+/1cGOiK3QUahntrNNtdVeihrO7t9JpoH75iMNXg6R6uWflQ== + methods@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" @@ -3804,6 +4005,11 @@ minimist@^1.2.5: resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== +module-details-from-path@^1.0.3, module-details-from-path@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.4.tgz#b662fdcd93f6c83d3f25289da0ce81c8d9685b94" + integrity sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w== + ms@^2.1.1, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" @@ -4163,6 +4369,14 @@ require-directory@^2.1.1: resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== +require-in-the-middle@^8.0.0: + version "8.0.1" + resolved "https://registry.yarnpkg.com/require-in-the-middle/-/require-in-the-middle-8.0.1.tgz#dbde2587f669398626d56b20c868ab87bf01cce4" + integrity sha512-QT7FVMXfWOYFbeRBF6nu+I6tr2Tf3u0q8RIEjNob/heKY/nh7drD/k7eeMFmSQgnTtCzLDcCu/XEnpW2wk4xCQ== + dependencies: + debug "^4.3.5" + module-details-from-path "^1.0.3" + resolve-cwd@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" @@ -4205,6 +4419,11 @@ safe-buffer@^5.0.1, safe-buffer@^5.2.1: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== +semifies@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/semifies/-/semifies-1.0.0.tgz#b69569f32c2ba2ac04f705ea82831364289b2ae2" + integrity sha512-xXR3KGeoxTNWPD4aBvL5NUpMTT7WMANr3EWnaS190QVkY52lqqcVRD7Q05UVbBhiWDGWMlJEUam9m7uFFGVScw== + semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" diff --git a/types/api.yml b/types/api.yml index 3d85cc2..835d343 100644 --- a/types/api.yml +++ b/types/api.yml @@ -14,6 +14,8 @@ paths: $ref: "./paths/qr/generate.yml" /data: $ref: "./paths/getData.yml" + /config: + $ref: "./paths/config/config.yml" # Restaurace a jídla (/api/food) /food/addChoice: diff --git a/types/paths/config/config.yml b/types/paths/config/config.yml new file mode 100644 index 0000000..467298c --- /dev/null +++ b/types/paths/config/config.yml @@ -0,0 +1,24 @@ +get: + operationId: getConfig + summary: Vrátí veřejnou runtime konfiguraci pro klienta (např. Sentry DSN). Nevyžaduje autentizaci. + security: [] # Nevyžaduje autentizaci + responses: + "200": + description: Veřejná konfigurace klienta + content: + application/json: + schema: + type: object + required: [sentry] + properties: + sentry: + type: object + required: [dsn, environment] + properties: + dsn: + type: string + nullable: true + description: Sentry DSN pro prohlížeč (null = Sentry vypnuté) + environment: + type: string + description: Prostředí serveru (development/production)