Backend Fejlesztés¶
Áttekintés¶
A FormFiller backend egy Node.js és TypeScript alapú szerver alkalmazás, amely Express keretrendszerre épül. A backend felelős az űrlap konfigurációk kezeléséért, az adatok validálásáért és tárolásáért, a workflow-k végrehajtásáért, valamint a felhasználói jogosultságok kezeléséért.
Architektúra Előnyei¶
Service-Alapú Felépítés¶
flowchart TB
subgraph ROUTER["Express Router"]
R["HTTP kérések fogadása<br/>Middleware-ek végrehajtása"]
end
subgraph SERVICE["Service Layer"]
direction TB
CS["ConfigService"]
DS["DataService"]
WS["WorkflowService"]
BS["BaseService"]
CS --> BS
DS --> BS
WS --> BS
end
subgraph MODELS["Mongoose Models"]
M["Adatséma definíciók<br/>Validáció, indexek"]
end
subgraph DB["MongoDB"]
D["Adattárolás<br/>Lekérdezések"]
end
ROUTER --> SERVICE
SERVICE --> MODELS
MODELS --> DB
style ROUTER fill:#e6f3ff,stroke:#0066cc
style SERVICE fill:#fff3cd,stroke:#856404
style BS fill:#ccffcc,stroke:#00cc00
Főbb Előnyök¶
| Előny | Leírás |
|---|---|
| Modularitás | Minden funkció külön service-ben, könnyű karbantartás és tesztelés |
| BaseService öröklődés | Közös CRUD műveletek egyszer implementálva, minden service örökli |
| Típusbiztonság | TypeScript típusok végig az alkalmazásban |
| Middleware lánc | Autentikáció, jogosultság, validáció middleware-ekben |
| Centralizált hibakezelés | AppError osztály egységes hibaformátum |
| Skálázhatóság | Stateless design, horizontálisan skálázható |
BaseService - Közös Alapműveletek¶
Minden domain-specifikus service a BaseService osztályból származik:
export abstract class BaseService<T extends Document> {
constructor(protected model: Model<T>) {}
async findById(id: string): Promise<T | null>
async findOne(query: Record<string, unknown>): Promise<T | null>
async findAll(query: Record<string, unknown> = {}): Promise<T[]>
async create(data: Record<string, unknown>): Promise<T>
async update(id: string, data: Record<string, unknown>): Promise<T | null>
async delete(id: string): Promise<T | null>
async count(query: Record<string, unknown> = {}): Promise<number>
async exists(query: Record<string, unknown>): Promise<boolean>
}
Megjegyzés: A kódbázis refaktoráláson esett át az
anytípus használatának csökkentése érdekében. A legtöbb service metódus mostRecord<string, unknown>típust használ a jobb típusbiztonság érdekében.
Ez biztosítja: - DRY elv - Nem kell minden service-ben újraimplementálni a CRUD műveleteket - Konzisztencia - Minden service ugyanúgy működik az alapműveleteknél - Kiterjeszthetőség - Domain-specifikus metódusok hozzáadása egyszerű
Projekt Struktúra¶
src/
├── config/ # Környezeti és alkalmazás konfiguráció
│ ├── env.ts # Környezeti változók validálása
│ ├── auth.ts # JWT és autentikáció beállítások
│ └── i18n.ts # Nemzetköziesítés konfiguráció
│
├── middleware/ # Express middleware-ek
│ ├── auth.ts # JWT token ellenőrzés
│ ├── rbac.ts # Szerepkör alapú jogosultságkezelés
│ ├── multisite.ts # Többbérlős rendszer tenant kezelés
│ ├── rateLimiter.ts # Rate limiting
│ └── errorHandler.ts # Központi hibakezelés
│
├── models/ # Mongoose adatmodellek
│ ├── User.ts # Felhasználók
│ ├── Config.ts # Űrlap konfigurációk
│ ├── Data.ts # Beküldött adatok
│ ├── Workflow.ts # Workflow definíciók
│ ├── FormRole.ts # Űrlap szintű szerepkörök
│ ├── FormPermission.ts # Űrlap jogosultságok
│ └── Site.ts # Multisite tenant-ok
│
├── services/ # Üzleti logika réteg
│ ├── BaseService.ts # Közös CRUD műveletek
│ ├── UserService.ts # Felhasználó kezelés
│ ├── ConfigService.ts # Konfiguráció kezelés
│ ├── DataService.ts # Adatkezelés és validáció
│ ├── WorkflowService.ts # Workflow végrehajtás
│ ├── ValidationService.ts # Validáció integráció
│ ├── RoleService.ts # Szerepkör kezelés
│ ├── PermissionService.ts # Jogosultság kezelés
│ └── EmailService.ts # Email küldés
│
├── routes/ # API végpontok
│ ├── auth.ts # /api/auth/*
│ ├── users.ts # /api/users/*
│ ├── config-routes.ts # /api/config/*
│ ├── data.ts # /api/data/*
│ ├── ai-generation.ts # /api/ai/* (AI konfig generálás)
│ ├── workflow.ts # /api/workflow/*
│ ├── roles.ts # /api/roles/*
│ └── permissions.ts # /api/permissions/*
│
├── types/ # TypeScript típusdefiníciók
│ └── express.d.ts # Express request kiterjesztés
│
└── utils/ # Segédfüggvények
├── logger.ts # Winston logger
├── cache.ts # Redis cache kezelés
├── errors.ts # Egyedi hiba osztályok
└── configValidator.ts # Schema validáció
Hívási Láncok¶
1. Űrlap Mentés Folyamata¶
sequenceDiagram
participant C as Client
participant MW as Middleware Chain
participant DS as DataService
participant VS as ValidationService
participant DB as MongoDB
C->>MW: POST /api/data/:configId
MW->>MW: authenticate (JWT)
MW->>MW: extractTenant (Site ID)
MW->>MW: requireFormPermission
MW->>DS: createData()
DS->>DS: Config betöltés
DS->>VS: validateFormData()
VS-->>DS: validation result + computedResults
DS->>DS: Save limit ellenőrzés
DS->>DB: Data mentés
DB-->>DS: Saved document
DS-->>C: { success, dataId, computedResults }
2. Workflow Végrehajtás Folyamata¶
flowchart TB
REQ["POST /api/workflow/:id/execute"]
subgraph WS["WorkflowService.executeWorkflow()"]
CTX["Context Inicializálás<br/>userId, userRole, input, results"]
subgraph LOOP["FOR EACH Step"]
COND{"Condition<br/>teljesül?"}
EXEC["Step végrehajtás"]
VAL["validate → ValidationService"]
SAVE["save → DataService"]
NOTIFY["notify → EmailService"]
API["api → External HTTP"]
TRANS["transform → Data mapping"]
STORE["Eredmény tárolás"]
ERR{"Hiba?"}
STOP["stop"]
CONT["continue"]
ROLL["rollback"]
end
end
RESP["Válasz: { success, steps, data, results }"]
REQ --> CTX
CTX --> COND
COND -->|Igen| EXEC
COND -->|Nem| STORE
EXEC --> STORE
STORE --> ERR
ERR -->|Nem| COND
ERR -->|Igen| STOP
ERR -->|Igen| CONT
ERR -->|Igen| ROLL
LOOP --> RESP
style RESP fill:#ccffcc,stroke:#00cc00
3. Config Lekérés Cachelt Folyamata¶
flowchart TB
REQ["GET /api/config/:id"]
subgraph CS["ConfigService.getConfigForUser()"]
REDIS{"Redis<br/>Enabled?"}
CACHE["Cache lookup<br/>config:{id}:{userId}"]
HIT{"Cache<br/>Hit?"}
CACHED["Return cached config"]
QUERY["MongoDB Query<br/>+ Permission Check<br/>+ Store in cache"]
end
REQ --> REDIS
REDIS -->|Igen| CACHE
REDIS -->|Nem| QUERY
CACHE --> HIT
HIT -->|Hit| CACHED
HIT -->|Miss| QUERY
style CACHED fill:#ccffcc,stroke:#00cc00
style CACHE fill:#e6f3ff,stroke:#0066cc
Workflow Kezelés Áttekintés¶
A workflow rendszer lehetővé teszi összetett üzleti folyamatok deklaratív definiálását és automatikus végrehajtását.
Támogatott Step Típusok¶
| Típus | Leírás | Használat |
|---|---|---|
validate |
Űrlap adatok validálása | Schema és szabályok ellenőrzése |
save |
Adatok mentése adatbázisba | DataService.createData() hívás |
notify |
Email értesítés küldése | EmailService integráció |
api |
Külső API hívás | Webhook, integráció |
transform |
Adatok átalakítása | Mapping, formázás |
conditional |
Feltételes elágazás | Üzleti logika alapján |
Hibakezelési Stratégiák¶
- stop: Hiba esetén a workflow leáll
- continue: Hiba esetén folytatódik a következő lépéssel
- rollback: Hiba esetén visszavonás (korlátozott támogatás)
Részletes workflow dokumentáció: features/workflow.md
Cache és Teljesítmény¶
Redis Cache¶
Ha engedélyezve van (REDIS_ENABLED=true), a rendszer cache-eli:
// Cache prefixek és TTL-ek
const CachePrefix = {
CONFIG: 'config:', // Űrlap konfigurációk
USER: 'user:', // Felhasználói adatok
PERMISSION: 'permission:', // Jogosultságok
};
const CacheTTL = {
CONFIG: 300, // 5 perc
USER: 600, // 10 perc
PERMISSION: 120, // 2 perc
};
Optimalizált Lekérdezések¶
// Csak szükséges mezők betöltése
const config = await Config.findById(configId)
.select('preferences siteId') // Csak ami kell
.lean(); // Plain JS object (gyorsabb)
// Index használat
configSchema.index({ createdBy: 1, isActive: 1 });
configSchema.index({ siteId: 1, type: 1 });
Teljesítmény Tippek¶
- Lean queries:
.lean()használata ha nem kell Mongoose document - Projection: Csak szükséges mezők lekérése
.select()-tel - Indexek: Gyakran szűrt mezőkre index definíció
- Batch műveletek:
insertMany(),bulkWrite()használata - Connection pooling: Mongoose alapértelmezett pool kezelése
Middleware-ek¶
Autentikáció¶
import { authenticate } from './middleware/auth';
router.get('/protected', authenticate, (req, res) => {
// req.user elérhető (userId, role, email)
});
Jogosultságkezelés¶
import { checkPermission } from './middleware/rbac';
router.post('/admin',
authenticate,
checkPermission('configs', 'create'),
(req, res) => {
// Admin művelet
}
);
Űrlap Szintű Jogosultság¶
import { requireFormPermission } from './middleware/formPermission';
router.post('/data/:configId',
authenticate,
requireFormPermission('createResults'),
async (req, res) => {
// Űrlaphoz van jogosultsága
}
);
Multisite¶
import { extractTenant } from './middleware/multisite';
// Automatikusan beállítja req.tenantId-t a Host header alapján
router.use(extractTenant);
API Fejlesztés¶
Új Endpoint Hozzáadása¶
- Hozd létre a route-ot a
routes/könyvtárban - Implementáld a service metódust
- Dokumentáld Swagger-rel
// routes/example.ts
import { Router } from 'express';
import { exampleService } from '../services';
import { authenticate } from '../middleware/auth';
const router = Router();
/**
* @swagger
* /api/example:
* get:
* summary: Példa endpoint
* responses:
* 200:
* description: Sikeres válasz
*/
router.get('/', authenticate, async (req, res, next) => {
try {
const result = await exampleService.getAll();
res.json(result);
} catch (error) {
next(error);
}
});
export default router;
Hibakezelés¶
AppError Osztály¶
import { AppError } from '../middleware/errorHandler';
// Egyszerű hiba
throw new AppError('Konfiguráció nem található', 404);
// Hiba extra adatokkal
throw new AppError('Validáció sikertelen', 400, {
validationErrors: errors,
fieldResults: results
});
Központi Hibakezelő¶
Minden hiba a központi error handler-en megy keresztül:
// middleware/errorHandler.ts
export const errorHandler = (err, req, res, next) => {
logger.error('Error:', {
message: err.message,
stack: err.stack,
statusCode: err.statusCode
});
res.status(err.statusCode || 500).json({
success: false,
error: err.message,
...(process.env.NODE_ENV === 'development' && { stack: err.stack })
});
};
Tesztelés¶
# Tesztek futtatása
npm test
# Coverage jelentés
npm run test:coverage
# Specifikus teszt futtatása
npm test -- --grep "ConfigService"
Hasznos Parancsok¶
# Fejlesztői szerver (hot reload)
npm run dev
# Build
npm run build
# Éles futtatás
npm start
# Adatbázis seed
npm run seed
# Admin felhasználó létrehozása
npm run create-admin
# API dokumentáció generálás
npm run docs
# Linter
npm run lint
Kapcsolódó Dokumentációk¶
- Workflow Kezelés - Részletes workflow dokumentáció
- Adatkezelés - Data Service és exportálás
- Jogosultságkezelés - RBAC rendszer
- Felhasználó Kezelés - User Service
- Validáció - Validációs szabályok