Nahrazeni sablony kompletnim webem a klientskym portalem

Web a portal Automia v jednom containeru. Express obsluhuje API
i zbuildovanou React aplikaci z dist/public.

Obsah:
- verejny web: homepage, sluzby, o nas, kontakt, 404
- prihlaseni pres JWT, demo ucty
- portal: prehled s grafem, tickety, incidenty, automatizace, konektory
- builder automatizaci: strom akci, vetveni podminkou
- katalog 25 konektoru v 8 kategoriich
- webhook s registrovanou adresou, token generuje server
- zivy dashboard pres SSE vcetne simulace provozu
- Swagger UI na /docs a OpenAPI na /openapi.json

Soulad s AGENTS.md:
- ROOT_PATH z prostredi, prefix proxy nikde nehardcodovan
- mount na koren i na prefix, funguje s handle_path i bez nej
- base tag a window.__BASE_PATH__ vkladane do index.html za behu
- OpenAPI servers obsahuje prefix, Try it out vola spravnou adresu
- povinne /health a /docs, port 3000, naslouchani na 0.0.0.0
- secrets jen z environment variables, nikdy v logu

Dokumentace ve slozce documentation/.
This commit is contained in:
JiriUhlir
2026-07-31 17:00:37 +02:00
parent 46f2f0b07e
commit 7b045a9f20
100 changed files with 15409 additions and 35 deletions
+58
View File
@@ -0,0 +1,58 @@
/**
* Konfigurace z environment variables.
* AppFactory je predava containeru, viz AGENTS.md, sekce Variables a secrets.
* Zadna hodnota se nehardcoduje a zadny secret se neloguje.
*/
const isProduction = process.env.NODE_ENV === 'production';
function requiredInProduction(name: string, fallback: string): string {
const value = process.env[name];
if (value && value.trim().length > 0) return value;
if (isProduction) {
// Zamerne padame pri startu - tichy fallback na dev secret by byl bezpecnostni dira.
throw new Error(`Chybi povinna promenna prostredi ${name} (NODE_ENV=production).`);
}
console.warn(`[config] ${name} neni nastavena, pouzivam DEV fallback. Nepouzivat v produkci.`);
return fallback;
}
/**
* Prefix verejne adresy, napr. "/apps/csbot-prototype".
* Caddy ho pred predanim do containeru odstranuje (handle_path), ale prohlizec
* ho vidi - proto se z nej sklada base pro SPA, odkazy, Swagger i webhooky.
*/
function normalizeRootPath(value: string | undefined): string {
const trimmed = (value ?? '').trim();
if (trimmed.length === 0 || trimmed === '/') return '';
const withSlash = trimmed.startsWith('/') ? trimmed : `/${trimmed}`;
return withSlash.replace(/\/+$/, '');
}
export const config = {
isProduction,
/** Port urcuje AppFactory sablona, vychozi 3000. Nemenit bez upravy metadat. */
port: Number(process.env.PORT ?? 3000),
rootPath: normalizeRootPath(process.env.ROOT_PATH),
jwtSecret: requiredInProduction('JWT_SECRET', 'dev-only-secret-nepouzivat-v-produkci'),
jwtExpiresIn: process.env.JWT_EXPIRES_IN ?? '8h',
/**
* Povolene originy pro CORS. V nasazeni bezi web i API na stejne domene,
* takze se CORS neuplatni. Je tu kvuli lokalnimu vyvoji s Vite dev serverem.
*/
corsOrigins: (process.env.CORS_ORIGIN ?? 'http://localhost:5173,http://localhost:4173')
.split(',')
.map((o) => o.trim())
.filter(Boolean),
/**
* Verejna adresa bez prefixu, napr. "https://services.csbot.cz".
* Sklada se z ni absolutni URL webhooku. Kdyz neni vyplnena, pouzije se
* relativni tvar - nikdy se nehardcoduje produkcni domena.
*/
publicOrigin: (process.env.PUBLIC_ORIGIN ?? '').trim().replace(/\/+$/, ''),
};
/** Zaklad verejne adresy aplikace vcetne prefixu proxy. */
export function publicBaseUrl(): string {
return `${config.publicOrigin}${config.rootPath}`;
}