mirror of
https://github.com/xtr-dev/payload-mailing.git
synced 2025-12-10 00:03:23 +00:00
✨ IMPROVE: Clean up async initialization pattern
- Remove unnecessary initializeTemplateEngine() from constructor - Rename initializeLiquidJS() to ensureLiquidJSInitialized() for clarity - Make template engine loading truly lazy (only on first template render) - Eliminate potential timing issues with constructor async calls - Improve code clarity and maintainability Now template engines are only loaded when actually needed for rendering. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@xtr-dev/payload-mailing",
|
"name": "@xtr-dev/payload-mailing",
|
||||||
"version": "0.0.11",
|
"version": "0.0.12",
|
||||||
"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",
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { Payload } from 'payload'
|
import { Payload } from 'payload'
|
||||||
import { Liquid } from 'liquidjs'
|
import { Liquid } from 'liquidjs'
|
||||||
import nodemailer, { Transporter } from 'nodemailer'
|
import nodemailer, { Transporter } from 'nodemailer'
|
||||||
import {
|
import {
|
||||||
MailingPluginConfig,
|
MailingPluginConfig,
|
||||||
SendEmailOptions,
|
SendEmailOptions,
|
||||||
MailingService as IMailingService,
|
MailingService as IMailingService,
|
||||||
EmailTemplate,
|
EmailTemplate,
|
||||||
QueuedEmail,
|
QueuedEmail,
|
||||||
@@ -23,15 +23,14 @@ export class MailingService implements IMailingService {
|
|||||||
constructor(payload: Payload, config: MailingPluginConfig) {
|
constructor(payload: Payload, config: MailingPluginConfig) {
|
||||||
this.payload = payload
|
this.payload = payload
|
||||||
this.config = config
|
this.config = config
|
||||||
|
|
||||||
const templatesConfig = config.collections?.templates
|
const templatesConfig = config.collections?.templates
|
||||||
this.templatesCollection = typeof templatesConfig === 'string' ? templatesConfig : 'email-templates'
|
this.templatesCollection = typeof templatesConfig === 'string' ? templatesConfig : 'email-templates'
|
||||||
|
|
||||||
const emailsConfig = config.collections?.emails
|
const emailsConfig = config.collections?.emails
|
||||||
this.emailsCollection = typeof emailsConfig === 'string' ? emailsConfig : 'emails'
|
this.emailsCollection = typeof emailsConfig === 'string' ? emailsConfig : 'emails'
|
||||||
|
|
||||||
this.initializeTransporter()
|
this.initializeTransporter()
|
||||||
this.initializeTemplateEngine()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeTransporter(): void {
|
private initializeTransporter(): void {
|
||||||
@@ -63,31 +62,11 @@ export class MailingService implements IMailingService {
|
|||||||
return fromEmail || ''
|
return fromEmail || ''
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeTemplateEngine(): void {
|
private async ensureLiquidJSInitialized(): Promise<void> {
|
||||||
// Skip initialization if custom template renderer is provided
|
|
||||||
if (this.config.templateRenderer) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use specified template engine or default to 'liquidjs'
|
|
||||||
const engine = this.config.templateEngine || 'liquidjs'
|
|
||||||
|
|
||||||
if (engine === 'liquidjs') {
|
|
||||||
// LiquidJS will be initialized lazily on first use
|
|
||||||
this.liquid = null
|
|
||||||
} else if (engine === 'mustache') {
|
|
||||||
// Mustache will be loaded dynamically on first use
|
|
||||||
this.liquid = null
|
|
||||||
} else if (engine === 'simple') {
|
|
||||||
this.liquid = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async initializeLiquidJS(): Promise<void> {
|
|
||||||
if (this.liquid !== null) return // Already initialized or failed
|
if (this.liquid !== null) return // Already initialized or failed
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const liquidModule = await import('liquidjs') as any
|
const liquidModule = await import('liquidjs')
|
||||||
const { Liquid: LiquidEngine } = liquidModule
|
const { Liquid: LiquidEngine } = liquidModule
|
||||||
this.liquid = new LiquidEngine()
|
this.liquid = new LiquidEngine()
|
||||||
|
|
||||||
@@ -135,7 +114,7 @@ export class MailingService implements IMailingService {
|
|||||||
})
|
})
|
||||||
|
|
||||||
await this.processEmailItem(emailId)
|
await this.processEmailItem(emailId)
|
||||||
|
|
||||||
return emailId
|
return emailId
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,7 +126,7 @@ export class MailingService implements IMailingService {
|
|||||||
|
|
||||||
if (options.templateSlug) {
|
if (options.templateSlug) {
|
||||||
const template = await this.getTemplateBySlug(options.templateSlug)
|
const template = await this.getTemplateBySlug(options.templateSlug)
|
||||||
|
|
||||||
if (template) {
|
if (template) {
|
||||||
templateId = template.id
|
templateId = template.id
|
||||||
const variables = options.variables || {}
|
const variables = options.variables || {}
|
||||||
@@ -195,7 +174,7 @@ export class MailingService implements IMailingService {
|
|||||||
|
|
||||||
async processEmails(): Promise<void> {
|
async processEmails(): Promise<void> {
|
||||||
const currentTime = new Date().toISOString()
|
const currentTime = new Date().toISOString()
|
||||||
|
|
||||||
const { docs: pendingEmails } = await this.payload.find({
|
const { docs: pendingEmails } = await this.payload.find({
|
||||||
collection: this.emailsCollection as any,
|
collection: this.emailsCollection as any,
|
||||||
where: {
|
where: {
|
||||||
@@ -379,7 +358,7 @@ export class MailingService implements IMailingService {
|
|||||||
},
|
},
|
||||||
limit: 1,
|
limit: 1,
|
||||||
})
|
})
|
||||||
|
|
||||||
return docs.length > 0 ? docs[0] as EmailTemplate : null
|
return docs.length > 0 ? docs[0] as EmailTemplate : null
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Template with slug '${templateSlug}' not found:`, error)
|
console.error(`Template with slug '${templateSlug}' not found:`, error)
|
||||||
@@ -403,7 +382,7 @@ export class MailingService implements IMailingService {
|
|||||||
// Use LiquidJS if configured
|
// Use LiquidJS if configured
|
||||||
if (engine === 'liquidjs') {
|
if (engine === 'liquidjs') {
|
||||||
try {
|
try {
|
||||||
await this.initializeLiquidJS()
|
await this.ensureLiquidJSInitialized()
|
||||||
if (this.liquid && typeof this.liquid !== 'boolean') {
|
if (this.liquid && typeof this.liquid !== 'boolean') {
|
||||||
return await this.liquid.parseAndRender(template, variables)
|
return await this.liquid.parseAndRender(template, variables)
|
||||||
}
|
}
|
||||||
@@ -430,7 +409,7 @@ export class MailingService implements IMailingService {
|
|||||||
|
|
||||||
private async renderWithMustache(template: string, variables: Record<string, any>): Promise<string | null> {
|
private async renderWithMustache(template: string, variables: Record<string, any>): Promise<string | null> {
|
||||||
try {
|
try {
|
||||||
const mustacheModule = await import('mustache') as any
|
const mustacheModule = await import('mustache')
|
||||||
const Mustache = mustacheModule.default || mustacheModule
|
const Mustache = mustacheModule.default || mustacheModule
|
||||||
return Mustache.render(template, variables)
|
return Mustache.render(template, variables)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -461,4 +440,4 @@ export class MailingService implements IMailingService {
|
|||||||
return { html, text }
|
return { html, text }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user