apps/recallassess/recallassess-api/src/api/shared/email/dto/preview-email.dto.ts
Properties |
|
| templateKey |
Type : string
|
Decorators :
@Expose()
|
import { ApiProperty } from "@nestjs/swagger";
import { IsNotEmpty, IsOptional, IsString, IsObject } from "class-validator";
import { Exclude, Expose, Transform } from "class-transformer";
@Exclude()
export class PreviewEmailDto {
@Expose()
@ApiProperty({
description: "Email template key",
example: "account.welcome.email",
})
@IsNotEmpty()
@IsString()
templateKey!: string;
/**
* Mail-merge variable map keyed by dotted names (e.g. "system.knowledgeReviewUrl",
* "user.name"). The keys are dynamic, so we can't @Expose() each one individually.
*
* The global ValidationPipe is configured with `excludeExtraneousValues: true`,
* which — combined with `@Exclude()` on this class and `@Expose()` on each
* property — causes class-transformer to recurse into this Record and strip
* every key inside it (since none of the dynamic keys have @Expose()). The
* symptom was `dto.variables` arriving as an empty `{}` even though the raw
* HTTP body contained all the keys.
*
* `@Transform(({ obj }) => obj.variables)` short-circuits that recursion by
* returning the original plain object verbatim from the raw incoming body,
* so every dotted key survives intact.
*/
@Expose()
@Transform(({ obj }) => obj.variables, { toClassOnly: true })
@ApiProperty({
description: "Variables to replace in template",
example: { "user.name": "John Doe", "user.email": "john@example.com" },
required: false,
})
@IsOptional()
@IsObject()
variables?: Record<string, string>;
}
@Exclude()
export class TestEmailDto extends PreviewEmailDto {
@Expose()
@ApiProperty({
description: "Recipient email address (for testing only)",
example: "test@example.com",
required: false,
})
@IsOptional()
@IsString()
recipientEmail?: string;
}
@Exclude()
export class ScheduleConfigDto {
@Expose()
@ApiProperty({
description: "Email type",
example: "hundred_day_journey",
})
@IsNotEmpty()
@IsString()
emailType!: string;
@Expose()
@ApiProperty({
description: "Template key",
example: "course.hundred.day.journey.email1",
})
@IsNotEmpty()
@IsString()
templateKey!: string;
@Expose()
@ApiProperty({
description: "Days after trigger event",
example: 2,
})
@IsNotEmpty()
daysAfterTrigger!: number;
@Expose()
@ApiProperty({
description: "Send time (HH:mm format)",
example: "09:00",
})
@IsNotEmpty()
@IsString()
sendTime!: string;
@Expose()
@ApiProperty({
description: "Timezone type: participant, company, or system",
example: "participant",
})
@IsNotEmpty()
@IsString()
timezoneType!: "participant" | "company" | "system";
@Expose()
@ApiProperty({
description: "Whether this schedule is enabled",
example: true,
required: false,
})
@IsOptional()
enabled?: boolean;
@Expose()
@ApiProperty({
description: "Additional metadata for the schedule configuration",
example: { customField: "value" },
required: false,
})
@IsOptional()
@IsObject()
metadata?: Record<string, any>;
}
@Exclude()
export class SendNowDto {
@Expose()
@ApiProperty({
description: "Email log ID to send immediately",
example: 1,
})
@IsNotEmpty()
emailLogId!: number;
}