Struktura podle zasad: rozdeleni souboru, lint, testy, prisny TypeScript

Projekt srovnan se zasadami v D:\GitHubRepository\CLAUDE.md bez zmeny chovani.

Struktura: scripts/ (skripty konektoru) -> connectors/, src/scripts ->
src/runtime/scripts; src/index.ts jen startuje, novy src/app.ts s createApp();
routes/dashboard.ts a routes/settings.ts rozdeleny do slozek; openapi.ts
rozdelen na openapi/{index,helpers,components} a paths/* (98 cest overeno
shodnych); ticketStore, automationStore a services jsou fasady nad slozkami
data/tickets, data/automations a data/services/catalog. process.env se cte
jen v config.ts. Web: hooky v hooks/, sdilena ui/Table a ui/ServiceIcon,
surove inputy nahrazeny komponentami, sedm velkych souboru rozdeleno.

Nastroje: eslint (typescript-eslint, react-hooks v7), prettier, editorconfig,
nvmrc, .env.example, vitest; skripty lint, format, test. Lint je cisty bez
jedineho eslint-disable (nove hooky useLatest a useSyncFromSource, odvozeny
stav misto setState v effectu). noUncheckedIndexedAccess v obou tsconfig,
84 mist zuzeno bez non-null operatoru; odhalilo zalohu backoffu fronty pri
nule pokusu a Retry-After NaN pri max 0. Cely kod naformatovan prettierem.

Testy: 8 souboru, 105 testu (prava, viditelnost, podminky a opakovani
v executoru, redaktor tajemstvi, sitove guardy, migrace resitelu, tickety,
health a prihlaseni pres supertest). Testy odhalily dve chyby ve vyhodnoceni
podminek, obe opravene: chybejici castka se porovnavala jako nula a podminka
nad vystupem druheho kroku cetla hodnotu prvniho se stejnym nazvem.

Pojmenovane konstanty misto magickych hodnot, ctx.util.base64 pro skripty
konektoru, README a dokumentace aktualizovany vcetne znamych odchylek.
This commit is contained in:
JiriUhlir
2026-09-09 15:11:02 +02:00
parent 42b3da8303
commit 22dda2d139
312 changed files with 21085 additions and 15319 deletions
+113
View File
@@ -2,6 +2,119 @@
Nejnovejsi nahore.
## 2026-09-09 - Struktura podle zasad: rozdeleni souboru, lint, testy
`D:\GitHubRepository\CLAUDE.md` dostal zasady pro vsechny projekty (struktura
Node a React, jedno cteni `process.env`, lint a format v repu, testy
v `tests/`, soubor nad 500 radku je signal k rozdeleni). Projekt se od nich
lisil na nekolika mistech naraz: `index.ts` skladal aplikaci i poslouchal,
`routes/dashboard.ts` mel pres tisic radku a `openapi.ts` skoro tri tisice,
katalog sluzeb byl jeden soubor, lint ani testy neexistovaly a `process.env`
se cetl na sesti mistech. Tahle zmena to srovnava; nic z toho nemeni chovani
aplikace, az na dve skryte chyby nize a dve chyby, ktere nasly prvni testy.
### Co se presunulo
| Driv | Ted | Proc |
| --------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------ |
| `scripts/*.js` | `connectors/*.js` | `scripts/` je podle zasad pro pomocne skripty vyvoje, ne pro kod nacitany za behu |
| `src/scripts/` | `src/runtime/scripts/` | je to runtime, ktery skripty spousti, patri k fronte a executoru |
| `src/index.ts` | `src/index.ts` (jen start) a `src/app.ts` (`createApp()`) | aplikace jde postavit v testu bez portu (supertest) |
| `src/routes/dashboard.ts` | `src/routes/dashboard/` (10 souboru po domenach a `shared.ts`) | jeden router = jedna domena, mount v `index.ts` |
| `src/routes/settings.ts` | `src/routes/settings/` (jedna entita = jeden soubor) | totez |
| `src/openapi.ts` | `src/openapi/{index,helpers,components}.ts` a `paths/*.ts` | popis endpointu lezi u sveho routeru; slozeny dokument ma stejnych 98 cest |
| `src/data/ticketStore.ts` | `src/data/tickets/` (model, state, persist, queries, store, intake, trace, stats, seed, remap) | fasada zustava, importy se nemeni |
| `src/data/automationStore.ts` | `src/data/automations/` (model, state, persist, store, validation, webhook, runs, seed, seedDemo, remap) | totez |
| `src/data/services.ts` | `src/data/services/index.ts` a `catalog/<skupina>.ts` | jeden soubor na skupinu sluzeb, `catalog/index.ts` drzi poradi |
| `web/src/lib/use*.ts` | `web/src/hooks/` | hooky maji vlastni slozku, `lib/` jsou ciste funkce |
`config.scriptsDir` ma vychozi `./connectors`, Dockerfile slozku kopiruje,
promenna `SCRIPTS_DIR` se nemeni. `process.env` se ted cte **jen**
v `src/config.ts`; pro `<SLUZBA>_BASE_URL` pribylo
`config.serviceBaseUrlOverride(variable)`, protoze nazev promenne sklada
katalog a vypisovat kazdou sluzbu do konfigurace by znamenalo dve mista.
Skripty konektoru dostaly `ctx.util.base64`, `google.send-email` uz nesaha na
`Buffer`.
### Web
Sdilene prvky: `components/ui/Table.tsx` (ctyri seznamy kreslily tabulku
kazdy jinak: `EntityAdmin`, `InvitePanel`, `People`, `AuditView`),
`components/ui/ServiceIcon.tsx`, vstupy v `Overview` a `TriggerConfig` z
`ui/form` misto vlastnich `<input>`. Rozdelene soubory:
`components/dashboard/scripts/{TestPanel,CodeEditor}`,
`dashboard/settings/{FeaturesAdmin,AuditView,types}`, `flow/{SampleBody,ModelTree,WebhookCalls}`,
`lib/exampleBody.ts`, `components/dashboard/EntityForm.tsx`, `widgets/EditBar.tsx`.
Nad 500 radku zustavaji `AutomationDetail`, `TicketDetail`, `MappingEditor`
a na serveru `data/services/catalog/ticket.ts`; duvody jsou
v [03-architektura-a-mapa-kodu.md](03-architektura-a-mapa-kodu.md).
Magicka cisla na obou stranach dostala pojmenovane konstanty s komentarem
(`JSON_BODY_LIMIT`, `STATIC_MAX_AGE_SEC`, `MAX_PAGE_LIMIT`, `KEEP_DAYS`,
`WEBHOOK_TOKEN_BYTES`, `MD_UP`, ...), hodnoty se nezmenily.
### Nastroje
`eslint.config.js` (typescript-eslint, `react-hooks` v7 pro web, `connectors/`
jako obycejny JS bez globalu, zadne `any`, zadny prazdny `catch`),
`.prettierrc`, `.prettierignore`, `.editorconfig`, `.nvmrc` (20),
`.env.example` se vsemi promennymi a komentarem, `vitest.config.ts`. Skripty
`npm run lint`, `format`, `format:check`, `test`, `test:watch` vedle
`typecheck`.
**Lint je cisty na celem repu bez jedineho `eslint-disable`.** Pravidla hooku
Reactu v7 hlasi zapis do refu pri vykresleni, `setState` v effectu
a komponentu vytvorenou pri vykresleni. Reseni je vzdy zmena navrhu, ne
vyjimka: `hooks/useLatest.ts` (ref s posledni hodnotou, zapis v layout
effectu), `hooks/useSyncFromSource.ts` (prevzeti dat ze zdroje pri vykresleni
misto `useEffect`), odvozeny stav misto kopie ve stavu, dialogy jako vlastni
komponenty, ktere se pri zavreni odmontuji (stav se resetuje sam),
`useMediaQuery` pres `useSyncExternalStore`, `ServiceIcon` pres
`createElement`.
### Prisnejsi TypeScript
Oba `tsconfig` maji `noUncheckedIndexedAccess`. Opraveno 55 mist na serveru
a 29 na webu, vzdy osetrenim `undefined`, nikde `!`. Dve z nich byly skutecne
chyby:
- `BACKOFF_MS[attempts - 1]` v `src/runtime/queue.ts` je pri `attempts = 0`
`undefined` a `new Date(NaN)` by beh naplanoval na nikdy; cteni ma zalohu
`MAX_BACKOFF_MS`.
- `rateLimit` s `max: 0` posilal `Retry-After: NaN`; ted aspon 1 sekunda.
### Testy
`tests/` zrcadli `src/`: 8 souboru, 105 testu, vsechny prochazi.
`tests/setup.ts` nastavi rezim pameti (`DATA_DIR=''`, `DATABASE_URL=''`,
pevny `SECRETS_KEY` a `JWT_SECRET`, `SEED_DEMO=0`) a umlci `console.info`
a `console.warn`; test migrace si bere docasny `DATA_DIR`.
| Soubor | Co hlida |
| ----------------------------------- | ------------------------------------------------------------------------ |
| `data/access.test.ts` | `accessFor`, `visibilityFor`, `resolveScope`: pohledy, strop viditelnosti, cizi firma je 404 |
| `data/permissions.test.ts` | `permissionsOf` za firmu, `syncSystemRoles` |
| `data/tickets.test.ts` | `intakeEvent` (externi ID za firmu), `listTickets` s povinnym filtrem, `updateTicketStatus` |
| `data/migratePeople.test.ts` | prevod `ppl_` na ucty vcetne ticketu, skupin a stromu; zapis na disk |
| `net/guard.test.ts` | `urlProblem` (privatni rozsahy), `readBodyLimited`, `readJsonLimited` |
| `routes/health.test.ts` | `createApp()` pres supertest: health, 404 jako JSON, 401, prihlaseni, `/access` za firmu |
| `runtime/executor.test.ts` | podminky (retezce, cisla, data, seznamy, `all`/`any`), stara podoba, stropy `MAX_STEPS`, `MAX_ACTIONS`, `MAX_LOOP_ITEMS`, vystupy, `retryable` |
| `runtime/scripts/util.test.ts` | `createRedactor` ve ctyrech tvarech, `parseBool`, `parseNumber`, `pick`, `truncate` |
Prvni testy executoru nasly dve chyby v podminkach, obe opravene: prazdna
hodnota se pri `gt`/`lt` porovnavala jako nula (`Number('')` je `0`) a hole
jmeno vystupu melo prednost pred `krok.jmeno`, takze podminka nad druhym
krokem se stejnym vystupem cetla hodnotu z prvniho. Podrobne
v [20-fronta-a-runtime.md](20-fronta-a-runtime.md).
### Znamy stav proti zasadam
Jeden `package.json` pro server i web (workspaces az bude mit kazda strana
vlastni build), logovani `console.*` s prefixem modulu misto strukturovaneho
loggeru, zadny soubor CI. Prettier prosel celym kodem (`npm run format`,
se svolenim); markdown je z formatovani vyjmuty (`.prettierignore`), protoze
dokumentace ma vlastni styl tabulek. Zapsano v [01-prehled-a-stav.md](01-prehled-a-stav.md).
## 2026-09-09 - Incident jde otevrit a posunout do dalsiho stavu
Seznam incidentu ukazoval jen titulek, sluzbu a casy. Server pritom uz posilal