227 Commits

Author SHA1 Message Date
Bas
9811d63a92 Merge pull request #69 from xtr-dev/dev
Bump version to 0.4.21
v0.4.21
2025-10-11 15:18:16 +02:00
0fa10164bf Replace type assertions with CollectionSlug for better type safety
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-11 15:14:09 +02:00
ada13d27cb Bump version to 0.4.21
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-11 15:03:14 +02:00
Bas
53ab62ed10 Merge pull request #68 from xtr-dev/dev
Fix filterOptions ObjectId casting error and bump version to 0.4.20
v0.4.20
2025-10-07 22:04:22 +02:00
de57dd4102 Fix filterOptions ObjectId casting error and bump version to 0.4.20
Fixed incorrect usage of resolveID in filterOptions where { id } was passed instead of id directly. This caused ObjectId casting errors when the id parameter was a populated object.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 22:01:23 +02:00
Bas
4633ead274 Merge pull request #67 from xtr-dev/dev
Fix ObjectId casting error when jobs relationship is populated
v0.4.19
2025-10-07 21:38:42 +02:00
d69f7c1f98 Fix ObjectId casting error when jobs relationship is populated
When the email's jobs relationship is populated with full job objects instead of just IDs,
calling String(job) on an object results in "[object Object]", which causes a Mongoose
ObjectId casting error. This fix properly extracts the ID from job objects or uses the
value directly if it's already an ID.

Fixes job scheduler error: "Cast to ObjectId failed for value '[object Object]'"

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 21:35:55 +02:00
Bas
57984e8633 Merge pull request #65 from xtr-dev/dev
Fix template relationship population in sendEmail and bump version to…
v0.4.18
2025-10-06 23:58:25 +02:00
d15fa454a0 Refactor template lookup to eliminate duplication and improve type safety
Changes:
- Added MailingService.renderTemplateDocument() method to render from template document
- Created renderTemplateWithId() helper that combines lookup and rendering in one operation
- Updated sendEmail() to use renderTemplateWithId() instead of separate lookup and render
- Added runtime validation to ensure template collection exists before querying
- Eliminated duplicate template lookup (previously looked up twice per email send)

Benefits:
- Improved performance by reducing database queries from 2 to 1 per template-based email
- Better error messages when template collection is misconfigured
- Runtime validation complements TypeScript type assertions for safer code
- Cleaner separation of concerns in sendEmail() function

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-06 23:55:31 +02:00
f431786907 Fix template relationship population in sendEmail and bump version to 0.4.18
The sendEmail function now properly populates the template relationship field when using template-based emails. This ensures:
- Template relationship is set on the email document
- templateSlug field is auto-populated via beforeChange hook
- beforeSend hook has access to the full template relationship
- Proper record of which template was used for each email

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-06 23:48:23 +02:00
Bas
63a5c5f982 Merge pull request #64 from xtr-dev/dev
Add templateSlug field auto-populated from template relationship and …
v0.4.17
2025-10-06 23:38:11 +02:00
107f67e22b Add templateSlug field auto-populated from template relationship and bump version to 0.4.17
Added templateSlug text field to Emails collection that is automatically populated via beforeChange hook when template relationship is set, making template slug accessible in beforeSend hook.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-06 23:37:17 +02:00
Bas
e95296feff Merge pull request #63 from xtr-dev/dev
Fix template population in beforeSend hook and bump version to 0.4.16
v0.4.16
2025-10-06 23:23:14 +02:00
7b853cbd4a Fix template population in beforeSend hook and bump version to 0.4.16
Added depth parameter to findByID call in processEmailItem to ensure template relationship is populated when passed to beforeSend hook.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-06 23:20:56 +02:00
Bas
8406bca718 Merge pull request #62 from xtr-dev/dev
Dev
v0.4.15
2025-10-06 23:16:24 +02:00
59ce8c031a Refactor immediate processing to use configurable job polling
Extract complex polling mechanism from sendEmail.ts into dedicated utility function (jobPolling.ts) and make polling parameters configurable via plugin options. This improves code maintainability and allows users to customize polling behavior through the jobPolling config option.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-06 23:13:54 +02:00
08ba814da0 Add PayloadID type and relation helpers, fix filterOptions casting issue
- Add PayloadID type for string | number IDs
- Add PayloadRelation<T> type for populated/unpopulated relations
- Add isPopulated() type guard to check if relation is populated
- Add resolveID() helper to extract ID from relation (object or ID)
- Add resolveIDs() helper for arrays of relations
- Fix filterOptions in Emails.ts to safely resolve ID before filtering
- This prevents MongoDB ObjectId casting errors when id is an object
- Bump version to 0.4.15

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-06 23:05:16 +02:00
f303eda652 Clean up sendEmail.ts and bump version to 0.4.14
- Remove duplicate nested if statement at line 188
- Remove redundant comments throughout the file
- Simplify code structure for better readability
- Bump patch version from 0.4.13 to 0.4.14

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-06 22:59:55 +02:00
Bas
8e1128f1e8 Merge pull request #61 from xtr-dev/dev
Remove deprecated `processEmailsTask` and associated helpers
v0.4.13
2025-09-27 11:49:44 +02:00
c62a364d9c Remove deprecated processEmailsTask and associated helpers
- Deleted batch email processing logic in favor of individual email jobs
- Updated `mailingJobs` to only register `processEmailJob`
- Simplified LiquidJS initialization check in `MailingService`
- Bumped version to 0.4.13
2025-09-27 11:48:38 +02:00
Bas
50ce181893 Merge pull request #59 from xtr-dev/dev
Dev
v0.4.12
2025-09-20 20:29:07 +02:00
8b2af8164a Remove verbose debug logs from immediate processing
- Reduced log noise while keeping essential error logging
- Only show job polling logs after 2 attempts (to catch real issues)
- Keep the main job scheduling confirmation log
- Immediate processing success is now at debug level

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-20 20:24:34 +02:00
3d7ddb8c97 Bump version to 0.4.12 2025-09-20 20:23:07 +02:00
Bas
2c0f202518 Merge pull request #58 from xtr-dev/dev
Dev
v0.4.11
2025-09-20 20:18:56 +02:00
3f177cfeb5 Bump version to 0.4.11 2025-09-20 20:11:00 +02:00
e364dd2c58 Fix job ID extraction in immediate processing
- Job relationship returns job objects, not just IDs
- Extract ID property from job object before passing to processJobById()
- This fixes the '[object Object]' issue in logs and ensures job execution works

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-20 20:10:35 +02:00
Bas
aa5a03b5b0 Merge pull request #57 from xtr-dev/dev
Fix TypeScript build error in jobScheduler.ts
v0.4.10
2025-09-20 19:04:46 +02:00
8ee3ff5a7d Fix TypeScript build error in jobScheduler.ts
- Use static values for task and queue in logging instead of accessing job properties
- Properties 'task' and 'queue' don't exist on BaseJob type

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-20 19:02:38 +02:00
Bas
2220d83288 Merge pull request #56 from xtr-dev/dev
Dev
2025-09-20 19:01:01 +02:00
2f46dde532 Add configurable logger with PAYLOAD_MAILING_LOG_LEVEL support
- Created centralized logger utility using Payload's built-in logger system
- Added PAYLOAD_MAILING_LOG_LEVEL environment variable for log level configuration
- Replaced all console.log/error/warn calls with structured logger
- Added debug logging for immediate processing flow to help troubleshoot issues
- Improved logging context with specific prefixes (IMMEDIATE, PROCESSOR, JOB_SCHEDULER, etc.)
- Bumped version to 0.4.10

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-20 18:57:18 +02:00
02a9334bf4 Add npm version badge to README for improved visibility 2025-09-19 09:59:28 +02:00
Bas
de1ae636de Merge pull request #55 from xtr-dev/dev
Dev
v0.4.9
2025-09-14 23:36:58 +02:00
ae38653466 Expand and clarify README documentation:
- Provide detailed examples of email template structure and rendering.
- Add guidance on job scheduling and direct email sending use cases.
- Enhance troubleshooting section with common issues and solutions.
- Introduce bulk operations, email monitoring, and query examples.
- Update plugin configuration requirements and clarify environment variables.

Improves overall usability and onboarding for developers.
2025-09-14 23:33:14 +02:00
fe8c4d194e Bump version to 0.4.9 and add comprehensive plugin configuration details to README. 2025-09-14 23:30:14 +02:00
0198821ff3 Update README for improved clarity and reduced redundancy. 2025-09-14 23:22:46 +02:00
Bas
5e0ed0a03a Merge pull request #52 from xtr-dev/dev
Dev
v0.4.8
2025-09-14 22:05:08 +02:00
d661d2e13e Fix critical race conditions and error handling inconsistencies
Race Condition Fixes (jobScheduler.ts):
- Implement optimistic job creation with graceful fallback
- Minimize race condition window by trying create first, then check
- Add enhanced error detection for constraint violations
- Provide detailed error context for debugging data consistency issues

Error Handling Improvements (sendEmail.ts):
- Distinguish between POLLING_TIMEOUT vs JOB_NOT_FOUND errors
- Add specific error types for programmatic handling
- Provide actionable troubleshooting steps in error messages
- Include recovery instructions (processEmailById fallback)

Benefits:
- Eliminates the check-then-create race condition vulnerability
- Provides clear error classification for different failure modes
- Enables better monitoring and debugging of job scheduling issues
- Maintains robustness under high concurrency scenarios

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-14 21:57:52 +02:00
e4a16094d6 Eliminate code duplication in email sanitization
- Create centralized sanitization utilities in utils/helpers.ts
- Add sanitizeDisplayName() with configurable quote escaping
- Add sanitizeFromName() wrapper for consistent fromName handling
- Replace duplicated sanitization logic in sendEmail.ts (9 lines → 1 line)
- Replace duplicated sanitization logic in MailingService.ts (9 lines → 1 line)
- Export new utilities from main index for external use
- Maintain identical functionality while reducing maintenance overhead

Benefits:
- Single source of truth for email header sanitization
- Consistent security handling across all email components
- Easier to maintain and update sanitization logic
- Configurable quote escaping for different use cases

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-14 21:52:55 +02:00
8135ff61c2 Optimize polling performance and reduce memory usage
- Reduce polling attempts from 10 to 5 with 3-second timeout protection
- Optimize exponential backoff delays (25ms-400ms vs 50ms-2000ms)
- Remove memory-intensive unique keys from job creation
- Reduce ensureEmailJob retry attempts from 5 to 3
- Use gentler exponential backoff (1.5x vs 2x) capped at 200ms
- Rely on database constraints for duplicate prevention instead of memory keys

Performance improvements:
- Faster response times for immediate email sending
- Reduced memory bloat in job queue systems
- Better resource efficiency for high-volume scenarios

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-14 21:41:29 +02:00
e28ee6b358 Fix critical race conditions and performance issues
- Implement atomic check-and-create pattern in ensureEmailJob with exponential backoff
- Fix import mismatch by exporting processJobById from index.ts
- Enable database indexes for status+scheduledAt and priority+createdAt fields
- Standardize string conversion for consistent ID handling throughout codebase
- Fix TypeScript compilation errors in collection indexes and variable scope

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-14 21:35:27 +02:00
4680f3303e Fix race condition with robust exponential backoff polling
🛡️ Race Condition Fix:
- Replaced unreliable fixed timeout with exponential backoff polling
- Polls up to 10 times for job creation
- Delays: 50ms, 100ms, 200ms, 400ms, 800ms, 1600ms, 2000ms (capped)
- Total max wait time: ~7 seconds under extreme load

🎯 Benefits:
- Fast response under normal conditions (usually first attempt)
- Graceful degradation under heavy load
- Proper error messages after timeout
- Debug logging for troubleshooting (after 3rd attempt)
- No race conditions even under extreme concurrency

📊 Performance:
- Normal case: 0-50ms wait (immediate success)
- Under load: Progressive backoff prevents overwhelming
- Worst case: Clear timeout with actionable error message
- Total attempts: 10 (configurable if needed)

🔍 How it works:
1. Create email and trigger hooks
2. Poll for job with exponential backoff
3. Exit early on success (usually first check)
4. Log attempts for debugging if delayed
5. Clear error if job never appears
2025-09-14 21:23:03 +02:00
efc734689b Bump version to 0.4.8 2025-09-14 21:20:16 +02:00
95ab07d72b Simplify hook logic and improve concurrent update handling
🎯 Simplifications:
- Removed complex beforeChange hook - all logic now in afterChange
- Single clear decision point with 'shouldSkip' variable
- Document ID always available in afterChange
- Clearer comments explaining the logic flow

🛡️ Concurrent Update Protection:
- ensureEmailJob now handles race conditions properly
- Double-checks for jobs after creation failure
- Idempotent function safe for concurrent calls
- Better error handling and recovery

📊 Benefits:
- Much simpler hook logic (from ~70 lines to ~40 lines)
- Single source of truth (afterChange only)
- No complex hook interactions
- Clear skip conditions
- Concurrent update safety
- Better code readability

🔍 How it works:
1. Check skip conditions (not pending, has jobs, etc.)
2. Call ensureEmailJob (handles all complexity)
3. Update relationship if needed
4. Log errors but don't fail operations
2025-09-14 21:18:51 +02:00
640ea0818d Extract job scheduling logic into dedicated utility functions
♻️ Refactoring:
- Created new jobScheduler.ts utility module
- Extracted findExistingJobs() for duplicate detection
- Extracted ensureEmailJob() for job creation with duplicate prevention
- Extracted updateEmailJobRelationship() for relationship management

📦 Functions:
- findExistingJobs(): Queries for existing processing jobs by email ID
- ensureEmailJob(): Creates job only if none exists, returns job IDs
- updateEmailJobRelationship(): Updates email with job relationship

🎯 Benefits:
- Reusable functions for job management
- Single source of truth for job scheduling logic
- Cleaner, more testable code
- Exported utilities for external use
- Better separation of concerns

🔧 Updated:
- Emails collection hooks now use extracted functions
- Exports added to main index for public API
- Cleaner hook implementation with less duplication
2025-09-14 21:14:02 +02:00
6f3d0f56c5 Bump version to 0.4.7 2025-09-14 21:07:38 +02:00
4e96fbcd20 Simplify sendEmail to rely on hooks for job creation
🔄 Cleaner Architecture:
- sendEmail now just creates the email and lets hooks handle job creation
- Hooks automatically create and populate job relationship
- For processImmediately, retrieves job from relationship and runs it
- Removes duplicate job creation logic from sendEmail

📈 Benefits:
- Single source of truth for job creation (hooks)
- Consistent behavior across all email creation methods
- Simpler, more maintainable code
- Better separation of concerns

🔍 Flow:
1. sendEmail creates email document
2. Hooks auto-create job and populate relationship
3. If processImmediately, fetch job from relationship and run it
4. Return email with complete job relationship
2025-09-14 21:06:47 +02:00
2d270ca527 Improve job scheduling hooks to populate relationship immediately
 Enhanced Job Relationship Management:
- Use beforeChange to populate existing jobs in relationship field
- Use afterChange to create new jobs and add them to relationship
- Jobs now appear immediately in the relationship field
- Better handling of updates vs new document creation

🔄 Hook Flow:
1. beforeChange: Find existing jobs for updates and populate relationship
2. afterChange: Create missing jobs and update relationship field
3. Result: Jobs relationship is always populated correctly

📈 Benefits:
- Immediate job visibility in admin interface
- No reliance on dynamic filtering alone
- Proper relationship data in database
- Handles both new emails and status changes
- Prevents duplicate job creation
2025-09-14 21:03:01 +02:00
9a996a33e5 Add afterChange hook to auto-schedule jobs for pending emails
 Smart Job Scheduling:
- Automatically creates processing jobs for pending emails
- Prevents orphaned emails that bypass sendEmail() function
- Checks for existing jobs to avoid duplicates
- Respects scheduledAt for delayed sending
- Handles both create and update operations intelligently

🔍 Logic:
- Only triggers for emails with status 'pending'
- Skips if email was already pending (prevents duplicate jobs)
- Queries existing jobs to avoid creating duplicates
- Uses mailing config queue or defaults to 'default'
- Graceful error handling (logs but doesn't fail email operations)

📈 Benefits:
- Complete email processing coverage
- Works for emails created via admin interface
- Handles manual status changes back to pending
- Maintains scheduling for delayed emails
- Zero-configuration auto-recovery
2025-09-14 21:01:35 +02:00
Bas
060b1914b6 Merge pull request #46 from xtr-dev/dev
Dev
v0.4.6
2025-09-14 20:45:26 +02:00
70fb79cca4 Add has-many relationship from emails to processing jobs
 New Feature:
- Add 'jobs' relationship field to emails collection
- Shows all PayloadCMS jobs associated with each email
- Read-only field with smart filtering by emailId
- Visible in admin interface for better email tracking

🔍 Benefits:
- Track job status and history for each email
- Debug processing issues more easily
- Monitor job queue performance per email
- Complete email processing visibility
2025-09-14 20:41:19 +02:00