Files
payload-mailing/src/plugin.ts
Bas van den Aakster 08b4d49019 Simplify job system architecture
- Replace createMailingJobs() function with static mailingJobs array
- Remove complex initialization dependencies and function wrappers
- Jobs now get MailingService from payload context instead of factory injection
- Fix PayloadCMS task handler return types to use proper {output: {}} format
- Eliminate potential initialization race conditions
- Cleaner, more straightforward job registration process

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-13 20:12:14 +02:00

133 lines
4.1 KiB
TypeScript

import type {CollectionConfig, Config, Field} from 'payload'
import { MailingPluginConfig, MailingContext } from './types/index.js'
import { MailingService } from './services/MailingService.js'
import { createEmailTemplatesCollection } from './collections/EmailTemplates.js'
import Emails from './collections/Emails.js'
import { mailingJobs, scheduleEmailsJob } from './jobs/index.js'
export const mailingPlugin = (pluginConfig: MailingPluginConfig) => (config: Config): Config => {
const queueName = pluginConfig.queue || 'default'
// Validate queueName
if (!queueName || typeof queueName !== 'string') {
throw new Error('Invalid queue configuration: queue must be a non-empty string')
}
// Handle templates collection configuration
const templatesConfig = pluginConfig.collections?.templates
const templatesSlug = typeof templatesConfig === 'string' ? templatesConfig : 'email-templates'
const templatesOverrides = typeof templatesConfig === 'object' ? templatesConfig : {}
// Create base templates collection with custom editor if provided
const baseTemplatesCollection = createEmailTemplatesCollection(pluginConfig.richTextEditor)
const templatesCollection = {
...baseTemplatesCollection,
slug: templatesSlug,
...templatesOverrides,
// Ensure admin config is properly merged
admin: {
...baseTemplatesCollection.admin,
...templatesOverrides.admin,
},
// Ensure access config is properly merged
access: {
...baseTemplatesCollection.access,
...templatesOverrides.access,
},
} satisfies CollectionConfig
// Handle emails collection configuration
const emailsConfig = pluginConfig.collections?.emails
const emailsSlug = typeof emailsConfig === 'string' ? emailsConfig : 'emails'
const emailsOverrides = typeof emailsConfig === 'object' ? emailsConfig : {}
const emailsCollection = {
...Emails,
slug: emailsSlug,
...emailsOverrides,
// Ensure admin config is properly merged
admin: {
...Emails.admin,
...emailsOverrides.admin,
},
// Ensure access config is properly merged
access: {
...Emails.access,
...emailsOverrides.access,
},
// Update relationship fields to point to correct templates collection
fields: (emailsOverrides.fields || Emails.fields).map((field: Field) => {
if (field &&
typeof field === 'object' &&
'name' in field &&
field.name === 'template' &&
field.type === 'relationship') {
return {
...field,
relationTo: templatesSlug,
} as typeof field
}
return field
}),
} satisfies CollectionConfig
return {
...config,
collections: [
...(config.collections || []),
templatesCollection,
emailsCollection,
],
jobs: {
...(config.jobs || {}),
tasks: [
...(config.jobs?.tasks || []),
...mailingJobs,
],
},
onInit: async (payload: any) => {
if (pluginConfig.initOrder === 'after' && config.onInit) {
await config.onInit(payload)
}
// Initialize mailing service with proper payload instance
const mailingService = new MailingService(payload, pluginConfig)
// Add mailing context to payload for developer access
;(payload as any).mailing = {
payload,
service: mailingService,
config: pluginConfig,
collections: {
templates: templatesSlug,
emails: emailsSlug,
},
} as MailingContext
console.log('PayloadCMS Mailing Plugin initialized successfully')
// Schedule the initial email processing job
try {
await scheduleEmailsJob(payload, queueName, 60000) // Schedule in 1 minute
console.log(`🔄 Scheduled initial email processing job in queue: ${queueName}`)
} catch (error) {
console.error('Failed to schedule email processing job:', error)
}
// Call onReady callback if provided
if (pluginConfig.onReady) {
await pluginConfig.onReady(payload)
}
if (pluginConfig.initOrder !== 'after' && config.onInit) {
await config.onInit(payload)
}
},
}
}
export default mailingPlugin