import { Type } from "class-transformer"; import { ArrayMaxSize, ArrayMinSize, IsArray, IsIn, IsNumber, IsOptional, IsString, Matches, MaxLength, ValidateNested } from "class-validator"; import { ALLOWED_IVR_DIGITS } from "@b2bcall/telephony"; import { IsSafeDialplanData } from "../../dialplan/dto/safe-dialplan-data.validator"; export class IvrMenuOptionDto { @IsIn(ALLOWED_IVR_DIGITS) digit!: string; @IsString() @Matches(/^[a-zA-Z0-9_-]{1,40}$/, { message: "destinationNumber deve ser alfanumérico (1 a 40 caracteres)" }) destinationNumber!: string; @IsOptional() @IsString() @MaxLength(80) destinationContext?: string; @IsOptional() @IsString() @MaxLength(80) label?: string; // Posição do nó no editor visual (PHASE 61) — puramente de // apresentação, nunca afeta o dialplan compilado. @IsOptional() @IsNumber() positionX?: number; @IsOptional() @IsNumber() positionY?: number; } export class CreateIvrMenuDto { @IsString() @MaxLength(80) name!: string; // Vira o `context` do dialplan compilado — derivado do nome no // frontend (slug), mas validado aqui como qualquer outro context. @IsString() @Matches(/^[a-z0-9-]{1,60}$/, { message: "context deve ser minúsculo, com letras/números/hífen (1 a 60 caracteres)" }) context!: string; @IsOptional() @IsString() @MaxLength(500) @IsSafeDialplanData({ message: "greeting usa uma função não permitida (ver docs/EXTENSIONS.md — nunca system/bg_system/curl/db/lua/shell)" }) greeting?: string; @IsArray() @ArrayMinSize(1) @ArrayMaxSize(12) @ValidateNested({ each: true }) @Type(() => IvrMenuOptionDto) options!: IvrMenuOptionDto[]; } export class UpdateIvrMenuDto { @IsOptional() @IsString() @MaxLength(80) name?: string; @IsOptional() @IsString() @MaxLength(500) @IsSafeDialplanData({ message: "greeting usa uma função não permitida (ver docs/EXTENSIONS.md — nunca system/bg_system/curl/db/lua/shell)" }) greeting?: string; @IsOptional() @IsArray() @ArrayMinSize(1) @ArrayMaxSize(12) @ValidateNested({ each: true }) @Type(() => IvrMenuOptionDto) options?: IvrMenuOptionDto[]; @IsOptional() @IsNumber() entryPositionX?: number; @IsOptional() @IsNumber() entryPositionY?: number; }