/
npronnikov
/
ProcessVisualizer
Обзор
Документация
Войти
/
npronnikov
/
ProcessVisualizer
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
backend/src/middleware/validation.ts
139 строк
4 KB
Madnick
refactor metrics fields and update remaining calculation
18 май 2026, 19:06
18 май 2026, 19:06
0f0c9d2
Код
Авторство
О чём код?
import { Request, Response, NextFunction } from 'express'; import { z } from 'zod'; import { AppError } from './errorHandler'; // Validation schemas export const createGroupSchema = z.object({ name: z.string().min(1, 'Name is required').max(255), description: z.string().optional(), weightUnit: z.enum(['percentage']), }); export const updateGroupSchema = z.object({ name: z.string().min(1).max(255).optional(), description: z.string().optional(), }); export const createProcessSchema = z.object({ groupId: z.string().uuid('Invalid group ID'), name: z.string().min(1, 'Name is required').max(255), description: z.string().optional(), responsible: z.string().max(255).optional(), totalValue: z.number().positive('Total value must be positive'), targetValue: z.number().nonnegative('Target value must be non-negative'), }).superRefine((data, ctx) => { if (data.targetValue > data.totalValue) { ctx.addIssue({ code: z.ZodIssueCode.custom, path: ['targetValue'], message: 'Цель автономизации не может быть больше общего значения', }); } }); export const updateProcessSchema = z.object({ name: z.string().min(1).max(255).optional(), description: z.string().optional(), responsible: z.string().max(255).optional(), totalValue: z.number().positive().optional(), targetValue: z.number().nonnegative().optional(), }).superRefine((data, ctx) => { if ( data.totalValue !== undefined && data.targetValue !== undefined && data.targetValue > data.totalValue ) { ctx.addIssue({ code: z.ZodIssueCode.custom, path: ['targetValue'], message: 'Целевое значение не может быть больше общего значения', }); } }); export const updateOperationSchema = z.object({ operationId: z.string().optional(), planEffort: z.number().nonnegative().nullable().optional(), factEffort: z.number().nonnegative().nullable().optional(), isManual: z.boolean().optional(), targetEffort: z.number().nonnegative().optional(), comment: z.string().optional(), date: z.string().optional(), userLogin: z.string().optional(), }).superRefine((data, ctx) => { const isHistoryRequest = data.date !== undefined; const hasPlan = data.planEffort !== undefined && data.planEffort !== null; const hasFact = data.factEffort !== undefined && data.factEffort !== null; if (isHistoryRequest && !hasPlan && !hasFact) { ctx.addIssue({ code: z.ZodIssueCode.custom, path: ['planEffort'], message: 'Нужно указать план или факт', }); ctx.addIssue({ code: z.ZodIssueCode.custom, path: ['factEffort'], message: 'Нужно указать план или факт', }); } }); export const upsertProcessBaseHistorySchema = z.object({ baseValue: z.number().nonnegative(), baseUnit: z.enum(['pieces', 'hours']), date: z.string().optional(), userLogin: z.string().optional(), }); /** * Validate request body against a schema */ export function validateBody<T extends z.ZodType>(schema: T) { return (req: Request, _res: Response, next: NextFunction) => { try { req.body = schema.parse(req.body); next(); } catch (error) { if (error instanceof z.ZodError) { throw new AppError(400, error.errors.map((e) => `${e.path.join('.')}: ${e.message}`).join(', ')); } throw error; } }; } /** * Validate request params */ export function validateParams<T extends z.ZodType>(schema: T) { return (req: Request, _res: Response, next: NextFunction) => { try { req.params = schema.parse(req.params); next(); } catch (error) { if (error instanceof z.ZodError) { throw new AppError(400, 'Invalid parameters: ' + error.errors.map((e) => e.message).join(', ')); } throw error; } }; } // Common param schemas export const idParamSchema = z.object({ id: z.string().uuid(), }); export const processIdParamSchema = z.object({ id: z.string().uuid(), }); export const groupIdParamSchema = z.object({ groupId: z.string().uuid(), }); export const processHistoryIdParamSchema = z.object({ id: z.string().uuid(), historyId: z.string().uuid(), });