import { Injectable } from '@nestjs/common'; import { validate, ValidationError } from 'class-validator'; import { plainToClass, ClassConstructor } from 'class-transformer'; {{#if enableDatabaseValidation}} import { PrismaService } from '../database/prisma.service'; {{/if}} {{#if enableI18n}} import { I18nService } from 'nestjs-i18n'; {{/if}} export interface ValidationResult { isValid: boolean; errors?: ValidationError[]; data?: any; } @Injectable() export class ValidationService { constructor( {{#if enableDatabaseValidation}} private readonly prisma: PrismaService, {{/if}} {{#if enableI18n}} private readonly i18n: I18nService, {{/if}} ) {} async validateDto( dto: ClassConstructor, data: any, options?: { groups?: string[]; skipMissingProperties?: boolean; whitelist?: boolean; forbidNonWhitelisted?: boolean; } ): Promise { try { const object = plainToClass(dto, data); const errors = await validate(object, { groups: options?.groups, skipMissingProperties: options?.skipMissingProperties || false, whitelist: options?.whitelist || {{whitelist}}, forbidNonWhitelisted: options?.forbidNonWhitelisted || {{forbidNonWhitelisted}}, transform: {{transform}}, }); if (errors.length > 0) { return { isValid: false, errors, }; } return { isValid: true, data: object, }; } catch (error) { return { isValid: false, errors: [error as ValidationError], }; } } async validateArray( dto: ClassConstructor, dataArray: any[], options?: { groups?: string[]; skipMissingProperties?: boolean; whitelist?: boolean; forbidNonWhitelisted?: boolean; } ): Promise { const results: ValidationResult[] = []; for (const data of dataArray) { const result = await this.validateDto(dto, data, options); results.push(result); } return results; } {{#if enableDatabaseValidation}} async validateUnique( model: string, field: string, value: any, excludeId?: string ): Promise { try { const whereClause: any = { [field]: value }; if (excludeId) { whereClause.id = { not: excludeId }; } const record = await this.prisma[model].findFirst({ where: whereClause, }); return !record; } catch (error) { console.error('Error validating uniqueness:', error); return false; } } async validateExists( model: string, field: string, value: any ): Promise { try { const record = await this.prisma[model].findFirst({ where: { [field]: value }, }); return !!record; } catch (error) { console.error('Error validating existence:', error); return false; } } {{/if}} formatValidationErrors(errors: ValidationError[]): any[] { return errors.map(error => ({ field: error.property, value: error.value, constraints: error.constraints, children: error.children?.length > 0 ? this.formatValidationErrors(error.children) : undefined, })); } {{#if enableI18n}} async getLocalizedErrorMessage( error: ValidationError, lang: string = 'en' ): Promise { const constraint = Object.keys(error.constraints || {})[0]; const key = `validation.${constraint}`; try { return await this.i18n.translate(key, { lang, args: { property: error.property, value: error.value, }, }); } catch { return Object.values(error.constraints || {})[0] || 'Validation error'; } } {{/if}} }