Merge pull request #30 from xtr-dev/dev

Add null value support to BaseEmailDocument interface
This commit is contained in:
Bas
2025-09-13 23:35:25 +02:00
committed by GitHub
4 changed files with 67 additions and 55 deletions

View File

@@ -38,13 +38,15 @@ const customEmail = await sendEmail<MyEmail>(payload, {
}) })
``` ```
## ID Type Compatibility ## Compatibility
The plugin works with both: The plugin works with:
- **String IDs**: `id: string` - **String IDs**: `id: string`
- **Number IDs**: `id: number` - **Number IDs**: `id: number`
- **Nullable fields**: Fields can be `null`, `undefined`, or have values
- **Generated types**: Works with `payload generate:types` output
Your Payload configuration determines which type is used. The plugin automatically adapts to your setup. Your Payload configuration determines which types are used. The plugin automatically adapts to your setup.
## Type Definitions ## Type Definitions
@@ -55,33 +57,33 @@ interface BaseEmailDocument {
id: string | number id: string | number
template?: any template?: any
to: string[] to: string[]
cc?: string[] cc?: string[] | null
bcc?: string[] bcc?: string[] | null
from?: string from?: string | null
replyTo?: string replyTo?: string | null
subject: string subject: string
html: string html: string
text?: string text?: string | null
variables?: Record<string, any> variables?: Record<string, any> | null
scheduledAt?: string scheduledAt?: string | null
sentAt?: string sentAt?: string | null
status?: 'pending' | 'processing' | 'sent' | 'failed' status?: 'pending' | 'processing' | 'sent' | 'failed' | null
attempts?: number attempts?: number | null
lastAttemptAt?: string lastAttemptAt?: string | null
error?: string error?: string | null
priority?: number priority?: number | null
createdAt?: string createdAt?: string | null
updatedAt?: string updatedAt?: string | null
} }
interface BaseEmailTemplateDocument { interface BaseEmailTemplateDocument {
id: string | number id: string | number
name: string name: string
slug: string slug: string
subject?: string subject?: string | null
content?: any content?: any
createdAt?: string createdAt?: string | null
updatedAt?: string updatedAt?: string | null
} }
``` ```

View File

@@ -1,6 +1,6 @@
{ {
"name": "@xtr-dev/payload-mailing", "name": "@xtr-dev/payload-mailing",
"version": "0.1.13", "version": "0.1.14",
"description": "Template-based email system with scheduling and job processing for PayloadCMS", "description": "Template-based email system with scheduling and job processing for PayloadCMS",
"type": "module", "type": "module",
"main": "dist/index.js", "main": "dist/index.js",

View File

@@ -83,12 +83,22 @@ export const sendEmail = async <TEmail extends BaseEmailDocument = BaseEmailDocu
if (emailData.to) { if (emailData.to) {
emailData.to = parseAndValidateEmails(emailData.to as string | string[]) emailData.to = parseAndValidateEmails(emailData.to as string | string[])
} }
if (emailData.cc) { if (emailData.cc && emailData.cc !== null) {
emailData.cc = parseAndValidateEmails(emailData.cc as string | string[]) emailData.cc = parseAndValidateEmails(emailData.cc as string | string[])
} }
if (emailData.bcc) { if (emailData.bcc && emailData.bcc !== null) {
emailData.bcc = parseAndValidateEmails(emailData.bcc as string | string[]) emailData.bcc = parseAndValidateEmails(emailData.bcc as string | string[])
} }
if (emailData.replyTo && emailData.replyTo !== null) {
const validated = parseAndValidateEmails(emailData.replyTo as string | string[])
// replyTo should be a single email, so take the first one if array
emailData.replyTo = validated && validated.length > 0 ? validated[0] : undefined
}
if (emailData.from && emailData.from !== null) {
const validated = parseAndValidateEmails(emailData.from as string | string[])
// from should be a single email, so take the first one if array
emailData.from = validated && validated.length > 0 ? validated[0] : undefined
}
// Create the email in the collection with proper typing // Create the email in the collection with proper typing
const email = await payload.create({ const email = await payload.create({

View File

@@ -2,38 +2,38 @@ import { Payload } from 'payload'
import type { CollectionConfig, RichTextField } from 'payload' import type { CollectionConfig, RichTextField } from 'payload'
import { Transporter } from 'nodemailer' import { Transporter } from 'nodemailer'
// Generic base interfaces that work with any ID type // Generic base interfaces that work with any ID type and null values
export interface BaseEmailDocument { export interface BaseEmailDocument {
id: string | number id: string | number
template?: any template?: any
to: string[] to: string[]
cc?: string[] cc?: string[] | null
bcc?: string[] bcc?: string[] | null
from?: string from?: string | null
replyTo?: string replyTo?: string | null
subject: string subject: string
html: string html: string
text?: string text?: string | null
variables?: Record<string, any> variables?: Record<string, any> | null
scheduledAt?: string scheduledAt?: string | null
sentAt?: string sentAt?: string | null
status?: 'pending' | 'processing' | 'sent' | 'failed' status?: 'pending' | 'processing' | 'sent' | 'failed' | null
attempts?: number attempts?: number | null
lastAttemptAt?: string lastAttemptAt?: string | null
error?: string error?: string | null
priority?: number priority?: number | null
createdAt?: string createdAt?: string | null
updatedAt?: string updatedAt?: string | null
} }
export interface BaseEmailTemplateDocument { export interface BaseEmailTemplateDocument {
id: string | number id: string | number
name: string name: string
slug: string slug: string
subject?: string subject?: string | null
content?: any content?: any
createdAt?: string createdAt?: string | null
updatedAt?: string updatedAt?: string | null
} }
export type BaseEmail<TEmail extends BaseEmailDocument = BaseEmailDocument, TEmailTemplate extends BaseEmailTemplateDocument = BaseEmailTemplateDocument> = Omit<TEmail, 'id' | 'template'> & {template: Omit<TEmailTemplate, 'id'> | TEmailTemplate['id'] | undefined | null} export type BaseEmail<TEmail extends BaseEmailDocument = BaseEmailDocument, TEmailTemplate extends BaseEmailTemplateDocument = BaseEmailTemplateDocument> = Omit<TEmail, 'id' | 'template'> & {template: Omit<TEmailTemplate, 'id'> | TEmailTemplate['id'] | undefined | null}
@@ -75,23 +75,23 @@ export interface MailingTransportConfig {
export interface QueuedEmail { export interface QueuedEmail {
id: string id: string
template?: string template?: string | null
to: string[] to: string[]
cc?: string[] cc?: string[] | null
bcc?: string[] bcc?: string[] | null
from?: string from?: string | null
replyTo?: string replyTo?: string | null
subject: string subject: string
html: string html: string
text?: string text?: string | null
variables?: Record<string, any> variables?: Record<string, any> | null
scheduledAt?: string scheduledAt?: string | null
sentAt?: string sentAt?: string | null
status: 'pending' | 'processing' | 'sent' | 'failed' status: 'pending' | 'processing' | 'sent' | 'failed'
attempts: number attempts: number
lastAttemptAt?: string lastAttemptAt?: string | null
error?: string error?: string | null
priority?: number priority?: number | null
createdAt: string createdAt: string
updatedAt: string updatedAt: string
} }