# 03 - Architektura a mapa kodu ## Technologie | Vrstva | Technologie | | ------- | ---------------------------------------------------- | | Server | Node.js 20, Express 4, TypeScript, ESM | | Web | React 18, Vite 6, TypeScript, Tailwind 4, React Router 6 | | Auth | JWT (jsonwebtoken), hesla bcrypt | | Validace| zod | | Docs | swagger-ui-express nad rucne psanou OpenAPI definici | Jeden `package.json`. Runtime zavislosti jsou v `dependencies`, nastroje pro build webu v `devDependencies` - runtime image je pak instaluje pres `--omit=dev`. ## Build ``` tsc src/**.ts -> dist/*.js vite web/ -> dist/public/ ``` Server obsluhuje `dist/public` jako statiku. Dockerfile kopiruje do vysledneho image jen `dist`, takze staci jedna slozka. ## Mapa kodu - server | Cesta | K cemu je | | --------------------------- | -------------------------------------------------------- | | `src/index.ts` | vstupni bod: middleware, mount routeru, statika, SPA, Swagger | | `src/config.ts` | cteni environment variables, normalizace `ROOT_PATH` | | `src/openapi.ts` | OpenAPI definice vcetne `servers` s prefixem proxy | | `src/types.ts` | typy uzivatele a JWT payloadu | | `src/middleware/auth.ts` | `requireAuth`, `requireRole` | | `src/events/bus.ts` | sbernice udalosti, ze ktere cerpa SSE stream | | `src/routes/auth.ts` | prihlaseni, odhlaseni, kdo jsem | | `src/routes/dashboard.ts` | data portalu, katalog konektoru, CRUD automatizaci | | `src/routes/stream.ts` | SSE stream zmen | | `src/routes/simulate.ts` | vyvolani provoznich udalosti | | `src/routes/webhook.ts` | verejny prijem dat do automatizace | | `src/routes/contact.ts` | poptavkovy formular z webu | | `src/data/ticketStore.ts` | tickety, jejich resitele, log prubehu, prehled vytizeni | | `src/data/people.ts` | resitele ticketu - oddeleni od uzivatelu portalu | | `src/data/tenants.ts` | firmy, ktere portal pouzivaji | | `src/data/access.ts` | kdo co vidi - jedno misto pro cely portal | | `src/data/widgets.ts` | katalog widgetu prehledu | | `src/data/dashboardLayouts.ts` | rozlozeni dashboardu za dvojici uzivatel a firma | | `src/data/incidentStore.ts` | incidenty vcetne zmen a udalosti | | `src/data/automationStore.ts` | automatizace, strom akci, tokeny webhooku | | `src/data/connectors.ts` | katalog konektoru, jejich spousteču a akci | | `src/data/conditions.ts` | typy parametru a operatory podminek | | `src/data/templates.ts` | sablony `{{parametr}}` v nastaveni kroku | | `src/data/flowScope.ts` | co je videt v kterem miste stromu | | `src/data/users.ts` | demo uzivatele | | `src/data/mock.ts` | souhrn pro prehled a casova rada grafu | ## Mapa kodu - web | Cesta | K cemu je | | ---------------------------------- | -------------------------------------------------- | | `web/src/main.tsx` | vstupni bod, `basename` routeru podle prefixu proxy | | `web/src/App.tsx` | routovani, portal se nacita lazy | | `web/src/index.css` | design tokeny a vlastni utility Tailwindu | | `web/src/config/brand.ts` | vsechny firemni udaje na jednom miste | | `web/src/lib/api.ts` | fetch wrapper, sprava tokenu, skladani adres | | `web/src/lib/eventStream.ts` | cteni SSE streamu pres fetch | | `web/src/lib/useApiQuery.ts` | nacitani dat vcetne obnoveni pri udalosti | | `web/src/lib/flow.ts` | ciste funkce nad stromem automatizace | | `web/src/components/dashboard/` | shell portalu, dlazdice, graf, stream, simulace | | `web/src/components/dashboard/flow/` | strom akci, vyber kroku, nastaveni poli akce | | `web/src/components/dashboard/TicketTrace.tsx` | log ticketu jako strom | | `web/src/components/dashboard/TicketWorkload.tsx` | prehled, kdo co ma u sebe | | `web/src/components/home/` | sekce homepage | | `web/src/pages/` | jedna stranka je jeden soubor | ## Klicova rozhodnuti **Jeden container misto dvou.** AppFactory nasazuje jednu aplikaci, proto Express obsluhuje i statiku. Odpada CORS i druha deploy jednotka. **SSE misto WebSocketu.** Tok dat je jednosmerny, server ke klientovi. Klient posila zmeny beznym REST volanim. SSE prochazi reverse proxy bez zvlastni konfigurace. **Stream pres fetch, ne pres EventSource.** EventSource neumi poslat hlavicku `Authorization` a token by musel byt v adrese, odkud se dostane do access logu. Cenou je rucni parsovani a rucni znovupripojeni v `web/src/lib/eventStream.ts`. **Ceske cesty v URL.** `/sluzby`, `/o-nas`, `/prihlaseni`, `/dashboard/tickety`. Kod zustava anglicky. **Data v pameti.** Vedome zjednoduseni prototypu. Uloziste jsou oddelena od rout, takze napojeni na databazi znamena prepsat soubory v `src/data/`, ne endpointy. **Filtr na firmu je povinny argument.** `listTickets`, `listPeople` i `listAutomations` vyzaduji `tenantIds`. Zapomenuty filtr tak neznamena "vse", ale nezkompiluje se. Podrobnosti v [07-firmy-a-prava.md](07-firmy-a-prava.md). **Prava se nikdy nedovozuji na klientovi.** Server vraci `GET /api/dashboard/access` s tim, co uzivatel smi. Kdyby si to klient pocital sam, pocitalo by se to na dvou mistech a jednou se to rozejde. **Resitel neni uzivatel.** Uzivatel se prihlasuje do portalu, resitel ma u sebe tickety. Technik muze mit tickety a ucet nikdy nemit. Spojka je e-mail, podrobnosti v [06-tickety.md](06-tickety.md). **Filtrovani ticketu dela server.** Klient posila query parametry a dostane hotovy seznam. Kdyby filtroval sam, ukazoval by jina cisla nez prehled vytizeni. **Krok vidi jen to, co je pred nim.** Parametry spoustece plus vystupy predchozich kroku. Vetev podminky nepridava nic do sekvence za podminkou, protoze nemusela probehnout. Vypocet je v `flowScope.ts`, priklady v [06-tickety.md](06-tickety.md). **Sablony odkazuji jmenem, ne ID.** Opak podminek, a je to zamer: `{{subject}}` uzivatel napise a precte, `{{f_42}}` ne. Rozbite odkazy po prejmenovani se hlasi jako nedodelek. **Zadna ticha selhani.** Kazdy `catch` loguje a uzivatel se o chybe dozvi.