@xtr-dev/payload-automation 0.0.23 → 0.0.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/plugin/cron-scheduler.ts"],"sourcesContent":["import type {Config, Payload, TaskConfig} from 'payload'\n\nimport cron from 'node-cron'\n\nimport {type PayloadWorkflow, WorkflowExecutor} from '../core/workflow-executor.js'\nimport {getConfigLogger} from './logger.js'\n\n/**\n * Generate dynamic cron tasks for all workflows with cron triggers\n * This is called at config time to register all scheduled tasks\n */\nexport function generateCronTasks(config: Config): void {\n const logger = getConfigLogger()\n\n // Note: We can't query the database at config time, so we'll need a different approach\n // We'll create a single task that handles all cron-triggered workflows\n const cronTask: TaskConfig = {\n slug: 'workflow-cron-executor',\n handler: async ({ input, req }) => {\n const { cronExpression, timezone, workflowId } = input as {\n cronExpression?: string\n timezone?: string\n workflowId: string\n }\n\n const logger = req.payload.logger.child({ plugin: '@xtr-dev/payload-automation' })\n\n try {\n // Get the workflow\n const workflow = await req.payload.findByID({\n id: workflowId,\n collection: 'workflows',\n depth: 2,\n req\n })\n\n if (!workflow) {\n throw new Error(`Workflow ${workflowId} not found`)\n }\n\n // Create execution context for cron trigger\n const context = {\n steps: {},\n trigger: {\n type: 'cron',\n req,\n triggeredAt: new Date().toISOString()\n }\n }\n\n // Create executor\n const executor = new WorkflowExecutor(req.payload, logger)\n\n // Find the matching cron trigger and check its condition if present\n const triggers = workflow.triggers as Array<{\n condition?: string\n cronExpression?: string\n timezone?: string\n type: string\n }>\n\n const matchingTrigger = triggers?.find(trigger =>\n trigger.type === 'cron-trigger' &&\n trigger.cronExpression === cronExpression\n )\n\n // Check trigger condition if present\n if (matchingTrigger?.condition) {\n const conditionMet = executor.evaluateCondition(matchingTrigger.condition, context)\n\n if (!conditionMet) {\n logger.info({\n condition: matchingTrigger.condition,\n cronExpression,\n workflowId,\n workflowName: workflow.name\n }, 'Cron trigger condition not met, skipping workflow execution')\n\n // Re-queue for next execution but don't run workflow\n if (cronExpression) {\n void requeueCronJob(workflowId, cronExpression, timezone, req.payload, logger)\n }\n\n return {\n output: {\n executedAt: new Date().toISOString(),\n reason: 'Condition not met',\n status: 'skipped',\n workflowId\n },\n state: 'succeeded'\n }\n }\n\n logger.info({\n condition: matchingTrigger.condition,\n cronExpression,\n workflowId,\n workflowName: workflow.name\n }, 'Cron trigger condition met')\n }\n\n // Execute the workflow\n await executor.execute(workflow as PayloadWorkflow, context, req)\n\n // Re-queue the job for the next scheduled execution if cronExpression is provided\n if (cronExpression) {\n void requeueCronJob(workflowId, cronExpression, timezone, req.payload, logger)\n }\n\n return {\n output: {\n executedAt: new Date().toISOString(),\n status: 'completed',\n workflowId\n },\n state: 'succeeded'\n }\n } catch (error) {\n logger.error({\n error: error instanceof Error ? error.message : 'Unknown error',\n workflowId\n }, 'Cron job execution failed')\n\n // Re-queue even on failure to ensure continuity (unless it's a validation error)\n if (cronExpression && !(error instanceof Error && error.message.includes('Invalid cron'))) {\n void requeueCronJob(workflowId, cronExpression, timezone, req.payload, logger)\n .catch((requeueError) => {\n logger.error({\n error: requeueError instanceof Error ? requeueError.message : 'Unknown error',\n workflowId\n }, 'Failed to re-queue cron job after execution failure')\n })\n }\n\n return {\n output: {\n error: error instanceof Error ? error.message : 'Unknown error',\n workflowId\n },\n state: 'failed'\n }\n }\n }\n }\n\n // Add the cron task to config if not already present\n if (!config.jobs) {\n config.jobs = { tasks: [] }\n }\n\n if (!config.jobs.tasks) {\n config.jobs.tasks = []\n }\n\n if (!config.jobs.tasks.find(task => task.slug === cronTask.slug)) {\n logger.debug(`Registering cron executor task: ${cronTask.slug}`)\n config.jobs.tasks.push(cronTask)\n } else {\n logger.debug(`Cron executor task ${cronTask.slug} already registered, skipping`)\n }\n}\n\n/**\n * Register cron jobs for workflows with cron triggers\n * This is called at runtime after PayloadCMS is initialized\n */\nexport async function registerCronJobs(payload: Payload, logger: Payload['logger']): Promise<void> {\n try {\n // Find all workflows with cron triggers\n const workflows = await payload.find({\n collection: 'workflows',\n depth: 0,\n limit: 1000,\n where: {\n 'triggers.type': {\n equals: 'cron-trigger'\n }\n }\n })\n\n logger.info(`Found ${workflows.docs.length} workflows with cron triggers`)\n\n for (const workflow of workflows.docs) {\n const triggers = workflow.triggers as Array<{\n cronExpression?: string\n timezone?: string\n type: string\n }>\n\n // Find all cron triggers for this workflow\n const cronTriggers = triggers?.filter(t => t.type === 'cron-trigger') || []\n\n for (const trigger of cronTriggers) {\n if (trigger.cronExpression) {\n try {\n // Validate cron expression before queueing\n if (!validateCronExpression(trigger.cronExpression)) {\n logger.error({\n cronExpression: trigger.cronExpression,\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Invalid cron expression format')\n continue\n }\n\n // Validate timezone if provided\n if (trigger.timezone) {\n try {\n // Test if timezone is valid by trying to create a date with it\n new Intl.DateTimeFormat('en', { timeZone: trigger.timezone })\n } catch {\n logger.error({\n timezone: trigger.timezone,\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Invalid timezone specified')\n continue\n }\n }\n\n // Calculate next execution time\n const nextExecution = getNextCronTime(trigger.cronExpression, trigger.timezone)\n\n // Queue the job\n await payload.jobs.queue({\n input: { cronExpression: trigger.cronExpression, timezone: trigger.timezone, workflowId: workflow.id },\n task: 'workflow-cron-executor',\n waitUntil: nextExecution\n })\n\n logger.info({\n cronExpression: trigger.cronExpression,\n nextExecution: nextExecution.toISOString(),\n timezone: trigger.timezone || 'UTC',\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Queued initial cron job for workflow')\n } catch (error) {\n logger.error({\n cronExpression: trigger.cronExpression,\n error: error instanceof Error ? error.message : 'Unknown error',\n timezone: trigger.timezone,\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Failed to queue cron job')\n }\n } else {\n logger.warn({\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Cron trigger found but no cron expression specified')\n }\n }\n }\n } catch (error) {\n logger.error({\n error: error instanceof Error ? error.message : 'Unknown error'\n }, 'Failed to register cron jobs')\n }\n}\n\n/**\n * Validate a cron expression\n */\nexport function validateCronExpression(cronExpression: string): boolean {\n return cron.validate(cronExpression)\n}\n\n/**\n * Calculate the next time a cron expression should run\n */\nfunction getNextCronTime(cronExpression: string, timezone?: string): Date {\n if (!validateCronExpression(cronExpression)) {\n throw new Error(`Invalid cron expression: ${cronExpression}`)\n }\n\n const now = new Date()\n const options: { timezone?: string } = timezone ? { timezone } : {}\n\n // Create a task to find the next execution time\n const task = cron.schedule(cronExpression, () => {}, {\n ...options\n })\n\n // Parse cron expression parts\n const cronParts = cronExpression.trim().split(/\\s+/)\n if (cronParts.length !== 5) {\n void task.destroy()\n throw new Error(`Invalid cron format: ${cronExpression}. Expected 5 parts.`)\n }\n\n const [minutePart, hourPart, dayPart, monthPart, weekdayPart] = cronParts\n\n // Calculate next execution with proper lookahead for any schedule frequency\n // Start from next minute and look ahead systematically\n let testTime = new Date(now.getTime() + 60 * 1000) // Start 1 minute from now\n testTime.setSeconds(0, 0) // Reset seconds and milliseconds\n\n // Maximum iterations to prevent infinite loops (covers ~2 years)\n const maxIterations = 2 * 365 * 24 * 60 // 2 years worth of minutes\n let iterations = 0\n\n while (iterations < maxIterations) {\n const minute = testTime.getMinutes()\n const hour = testTime.getHours()\n const dayOfMonth = testTime.getDate()\n const month = testTime.getMonth() + 1\n const dayOfWeek = testTime.getDay()\n\n if (matchesCronPart(minute, minutePart) &&\n matchesCronPart(hour, hourPart) &&\n matchesCronPart(dayOfMonth, dayPart) &&\n matchesCronPart(month, monthPart) &&\n matchesCronPart(dayOfWeek, weekdayPart)) {\n void task.destroy()\n return testTime\n }\n\n // Increment time intelligently based on cron pattern\n testTime = incrementTimeForCronPattern(testTime, cronParts)\n iterations++\n }\n\n void task.destroy()\n throw new Error(`Could not calculate next execution time for cron expression: ${cronExpression} within reasonable timeframe`)\n}\n\n/**\n * Intelligently increment time based on cron pattern to avoid unnecessary iterations\n */\nfunction incrementTimeForCronPattern(currentTime: Date, cronParts: string[]): Date {\n const [minutePart, hourPart, _dayPart, _monthPart, _weekdayPart] = cronParts\n const nextTime = new Date(currentTime)\n\n // If minute is specific (not wildcard), we can jump to next hour\n if (minutePart !== '*' && !minutePart.includes('/')) {\n const targetMinute = getNextValidCronValue(currentTime.getMinutes(), minutePart)\n if (targetMinute <= currentTime.getMinutes()) {\n // Move to next hour\n nextTime.setHours(nextTime.getHours() + 1, targetMinute, 0, 0)\n } else {\n nextTime.setMinutes(targetMinute, 0, 0)\n }\n return nextTime\n }\n\n // If hour is specific and we're past it, jump to next day\n if (hourPart !== '*' && !hourPart.includes('/')) {\n const targetHour = getNextValidCronValue(currentTime.getHours(), hourPart)\n if (targetHour <= currentTime.getHours()) {\n // Move to next day\n nextTime.setDate(nextTime.getDate() + 1)\n nextTime.setHours(targetHour, 0, 0, 0)\n } else {\n nextTime.setHours(targetHour, 0, 0, 0)\n }\n return nextTime\n }\n\n // Default: increment by 1 minute\n nextTime.setTime(nextTime.getTime() + 60 * 1000)\n return nextTime\n}\n\n/**\n * Get the next valid value for a cron part\n */\nfunction getNextValidCronValue(currentValue: number, cronPart: string): number {\n if (cronPart === '*') {return currentValue + 1}\n\n // Handle specific values and ranges\n const values = parseCronPart(cronPart)\n return values.find(v => v > currentValue) || values[0]\n}\n\n/**\n * Parse a cron part into an array of valid values\n */\nfunction parseCronPart(cronPart: string): number[] {\n if (cronPart === '*') {return []}\n\n const values: number[] = []\n\n // Handle comma-separated values\n if (cronPart.includes(',')) {\n cronPart.split(',').forEach(part => {\n values.push(...parseCronPart(part.trim()))\n })\n return values.sort((a, b) => a - b)\n }\n\n // Handle ranges\n if (cronPart.includes('-')) {\n const [start, end] = cronPart.split('-').map(n => parseInt(n, 10))\n for (let i = start; i <= end; i++) {\n values.push(i)\n }\n return values\n }\n\n // Handle step values\n if (cronPart.includes('/')) {\n const [range, step] = cronPart.split('/')\n const stepNum = parseInt(step, 10)\n\n if (range === '*') {\n // For wildcards with steps, return empty - handled elsewhere\n return []\n }\n\n const baseValues = parseCronPart(range)\n return baseValues.filter((_, index) => index % stepNum === 0)\n }\n\n // Single value\n values.push(parseInt(cronPart, 10))\n return values\n}\n\n/**\n * Check if a value matches a cron expression part\n */\nfunction matchesCronPart(value: number, cronPart: string): boolean {\n if (cronPart === '*') {return true}\n\n // Handle step values (e.g., */5)\n if (cronPart.includes('/')) {\n const [range, step] = cronPart.split('/')\n const stepNum = parseInt(step, 10)\n\n if (range === '*') {\n return value % stepNum === 0\n }\n }\n\n // Handle ranges (e.g., 1-5)\n if (cronPart.includes('-')) {\n const [start, end] = cronPart.split('-').map(n => parseInt(n, 10))\n return value >= start && value <= end\n }\n\n // Handle comma-separated values (e.g., 1,3,5)\n if (cronPart.includes(',')) {\n const values = cronPart.split(',').map(n => parseInt(n, 10))\n return values.includes(value)\n }\n\n // Handle single value\n const cronValue = parseInt(cronPart, 10)\n return value === cronValue\n}\n\n/**\n * Handle re-queueing of cron jobs after they execute\n * This ensures the job runs again at the next scheduled time\n */\nexport async function requeueCronJob(\n workflowId: string,\n cronExpression: string,\n timezone: string | undefined,\n payload: Payload,\n logger: Payload['logger']\n): Promise<void> {\n try {\n // Queue the job to run at the next scheduled time\n await payload.jobs.queue({\n input: { cronExpression, timezone, workflowId },\n task: 'workflow-cron-executor',\n waitUntil: getNextCronTime(cronExpression, timezone)\n })\n\n logger.debug({\n nextRun: getNextCronTime(cronExpression, timezone),\n timezone: timezone || 'UTC',\n workflowId\n }, 'Re-queued cron job')\n } catch (error) {\n logger.error({\n error: error instanceof Error ? error.message : 'Unknown error',\n workflowId\n }, 'Failed to re-queue cron job')\n }\n}\n\n/**\n * Register or update cron jobs for a specific workflow\n */\nexport async function updateWorkflowCronJobs(\n workflowId: string,\n payload: Payload,\n logger: Payload['logger']\n): Promise<void> {\n try {\n // First, cancel any existing cron jobs for this workflow\n cancelWorkflowCronJobs(workflowId, payload, logger)\n\n // Get the workflow\n const workflow = await payload.findByID({\n id: workflowId,\n collection: 'workflows',\n depth: 0\n })\n\n if (!workflow) {\n logger.warn({ workflowId }, 'Workflow not found for cron job update')\n return\n }\n\n const triggers = workflow.triggers as Array<{\n cronExpression?: string\n timezone?: string\n type: string\n }>\n\n // Find all cron triggers for this workflow\n const cronTriggers = triggers?.filter(t => t.type === 'cron-trigger') || []\n\n if (cronTriggers.length === 0) {\n logger.debug({ workflowId }, 'No cron triggers found for workflow')\n return\n }\n\n let scheduledJobs = 0\n\n for (const trigger of cronTriggers) {\n if (trigger.cronExpression) {\n try {\n // Validate cron expression before queueing\n if (!validateCronExpression(trigger.cronExpression)) {\n logger.error({\n cronExpression: trigger.cronExpression,\n workflowId,\n workflowName: workflow.name\n }, 'Invalid cron expression format')\n continue\n }\n\n // Validate timezone if provided\n if (trigger.timezone) {\n try {\n new Intl.DateTimeFormat('en', { timeZone: trigger.timezone })\n } catch {\n logger.error({\n timezone: trigger.timezone,\n workflowId,\n workflowName: workflow.name\n }, 'Invalid timezone specified')\n continue\n }\n }\n\n // Calculate next execution time\n const nextExecution = getNextCronTime(trigger.cronExpression, trigger.timezone)\n\n // Queue the job\n await payload.jobs.queue({\n input: { cronExpression: trigger.cronExpression, timezone: trigger.timezone, workflowId },\n task: 'workflow-cron-executor',\n waitUntil: nextExecution\n })\n\n scheduledJobs++\n\n logger.info({\n cronExpression: trigger.cronExpression,\n nextExecution: nextExecution.toISOString(),\n timezone: trigger.timezone || 'UTC',\n workflowId,\n workflowName: workflow.name\n }, 'Scheduled cron job for workflow')\n } catch (error) {\n logger.error({\n cronExpression: trigger.cronExpression,\n error: error instanceof Error ? error.message : 'Unknown error',\n timezone: trigger.timezone,\n workflowId,\n workflowName: workflow.name\n }, 'Failed to schedule cron job')\n }\n }\n }\n\n if (scheduledJobs > 0) {\n logger.info({ scheduledJobs, workflowId }, 'Updated cron jobs for workflow')\n }\n } catch (error) {\n logger.error({\n error: error instanceof Error ? error.message : 'Unknown error',\n workflowId\n }, 'Failed to update workflow cron jobs')\n }\n}\n\n/**\n * Cancel all cron jobs for a specific workflow\n */\nexport function cancelWorkflowCronJobs(\n workflowId: string,\n payload: Payload,\n logger: Payload['logger']\n): void {\n try {\n // Note: PayloadCMS job system doesn't have a built-in way to cancel specific jobs by input\n // This is a limitation we need to work around\n // For now, we log that we would cancel jobs for this workflow\n logger.debug({ workflowId }, 'Would cancel existing cron jobs for workflow (PayloadCMS limitation: cannot selectively cancel jobs)')\n } catch (error) {\n logger.error({\n error: error instanceof Error ? error.message : 'Unknown error',\n workflowId\n }, 'Failed to cancel workflow cron jobs')\n }\n}\n\n/**\n * Remove cron jobs for a deleted workflow\n */\nexport function removeWorkflowCronJobs(\n workflowId: string,\n payload: Payload,\n logger: Payload['logger']\n): void {\n try {\n cancelWorkflowCronJobs(workflowId, payload, logger)\n logger.info({ workflowId }, 'Removed cron jobs for deleted workflow')\n } catch (error) {\n logger.error({\n error: error instanceof Error ? error.message : 'Unknown error',\n workflowId\n }, 'Failed to remove workflow cron jobs')\n }\n}\n"],"names":["cron","WorkflowExecutor","getConfigLogger","generateCronTasks","config","logger","cronTask","slug","handler","input","req","cronExpression","timezone","workflowId","payload","child","plugin","workflow","findByID","id","collection","depth","Error","context","steps","trigger","type","triggeredAt","Date","toISOString","executor","triggers","matchingTrigger","find","condition","conditionMet","evaluateCondition","info","workflowName","name","requeueCronJob","output","executedAt","reason","status","state","execute","error","message","includes","catch","requeueError","jobs","tasks","task","debug","push","registerCronJobs","workflows","limit","where","equals","docs","length","cronTriggers","filter","t","validateCronExpression","Intl","DateTimeFormat","timeZone","nextExecution","getNextCronTime","queue","waitUntil","warn","validate","now","options","schedule","cronParts","trim","split","destroy","minutePart","hourPart","dayPart","monthPart","weekdayPart","testTime","getTime","setSeconds","maxIterations","iterations","minute","getMinutes","hour","getHours","dayOfMonth","getDate","month","getMonth","dayOfWeek","getDay","matchesCronPart","incrementTimeForCronPattern","currentTime","_dayPart","_monthPart","_weekdayPart","nextTime","targetMinute","getNextValidCronValue","setHours","setMinutes","targetHour","setDate","setTime","currentValue","cronPart","values","parseCronPart","v","forEach","part","sort","a","b","start","end","map","n","parseInt","i","range","step","stepNum","baseValues","_","index","value","cronValue","nextRun","updateWorkflowCronJobs","cancelWorkflowCronJobs","scheduledJobs","removeWorkflowCronJobs"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/plugin/cron-scheduler.ts"],"sourcesContent":["import type {Config, Payload, TaskConfig} from 'payload'\n\nimport cron from 'node-cron'\n\nimport {type PayloadWorkflow, WorkflowExecutor} from '../core/workflow-executor.js'\nimport {getConfigLogger} from './logger.js'\n\n/**\n * Generate dynamic cron tasks for all workflows with cron triggers\n * This is called at config time to register all scheduled tasks\n */\nexport function generateCronTasks(config: Config): void {\n const logger = getConfigLogger()\n\n // Note: We can't query the database at config time, so we'll need a different approach\n // We'll create a single task that handles all cron-triggered workflows\n const cronTask: TaskConfig = {\n slug: 'workflow-cron-executor',\n handler: async ({ input, req }) => {\n const { cronExpression, timezone, workflowId } = input as {\n cronExpression?: string\n timezone?: string\n workflowId: string\n }\n\n const logger = req.payload.logger.child({ plugin: '@xtr-dev/payload-automation' })\n\n try {\n // Get the workflow\n const workflow = await req.payload.findByID({\n id: workflowId,\n collection: 'workflows',\n depth: 2,\n req\n })\n\n if (!workflow) {\n throw new Error(`Workflow ${workflowId} not found`)\n }\n\n // Create execution context for cron trigger\n const context = {\n steps: {},\n trigger: {\n type: 'cron',\n req,\n triggeredAt: new Date().toISOString()\n }\n }\n\n // Create executor\n const executor = new WorkflowExecutor(req.payload, logger)\n\n // Find the matching cron trigger and check its condition if present\n const triggers = workflow.triggers as Array<{\n condition?: string\n parameters?: {\n cronExpression?: string\n timezone?: string\n [key: string]: any\n }\n type: string\n }>\n\n const matchingTrigger = triggers?.find(trigger =>\n trigger.type === 'cron-trigger' &&\n trigger.parameters?.cronExpression === cronExpression\n )\n\n // Check trigger condition if present\n if (matchingTrigger?.condition) {\n const conditionMet = executor.evaluateCondition(matchingTrigger.condition, context)\n\n if (!conditionMet) {\n logger.info({\n condition: matchingTrigger.condition,\n cronExpression,\n workflowId,\n workflowName: workflow.name\n }, 'Cron trigger condition not met, skipping workflow execution')\n\n // Re-queue for next execution but don't run workflow\n if (cronExpression) {\n void requeueCronJob(workflowId, cronExpression, timezone, req.payload, logger)\n }\n\n return {\n output: {\n executedAt: new Date().toISOString(),\n reason: 'Condition not met',\n status: 'skipped',\n workflowId\n },\n state: 'succeeded'\n }\n }\n\n logger.info({\n condition: matchingTrigger.condition,\n cronExpression,\n workflowId,\n workflowName: workflow.name\n }, 'Cron trigger condition met')\n }\n\n // Execute the workflow\n await executor.execute(workflow as PayloadWorkflow, context, req)\n\n // Re-queue the job for the next scheduled execution if cronExpression is provided\n if (cronExpression) {\n void requeueCronJob(workflowId, cronExpression, timezone, req.payload, logger)\n }\n\n return {\n output: {\n executedAt: new Date().toISOString(),\n status: 'completed',\n workflowId\n },\n state: 'succeeded'\n }\n } catch (error) {\n logger.error({\n error: error instanceof Error ? error.message : 'Unknown error',\n workflowId\n }, 'Cron job execution failed')\n\n // Re-queue even on failure to ensure continuity (unless it's a validation error)\n if (cronExpression && !(error instanceof Error && error.message.includes('Invalid cron'))) {\n void requeueCronJob(workflowId, cronExpression, timezone, req.payload, logger)\n .catch((requeueError) => {\n logger.error({\n error: requeueError instanceof Error ? requeueError.message : 'Unknown error',\n workflowId\n }, 'Failed to re-queue cron job after execution failure')\n })\n }\n\n return {\n output: {\n error: error instanceof Error ? error.message : 'Unknown error',\n workflowId\n },\n state: 'failed'\n }\n }\n }\n }\n\n // Add the cron task to config if not already present\n if (!config.jobs) {\n config.jobs = { tasks: [] }\n }\n\n if (!config.jobs.tasks) {\n config.jobs.tasks = []\n }\n\n if (!config.jobs.tasks.find(task => task.slug === cronTask.slug)) {\n logger.debug(`Registering cron executor task: ${cronTask.slug}`)\n config.jobs.tasks.push(cronTask)\n } else {\n logger.debug(`Cron executor task ${cronTask.slug} already registered, skipping`)\n }\n}\n\n/**\n * Register cron jobs for workflows with cron triggers\n * This is called at runtime after PayloadCMS is initialized\n */\nexport async function registerCronJobs(payload: Payload, logger: Payload['logger']): Promise<void> {\n try {\n // Find all workflows with cron triggers\n const workflows = await payload.find({\n collection: 'workflows',\n depth: 0,\n limit: 1000,\n where: {\n 'triggers.type': {\n equals: 'cron-trigger'\n }\n }\n })\n\n logger.info(`Found ${workflows.docs.length} workflows with cron triggers`)\n\n for (const workflow of workflows.docs) {\n const triggers = workflow.triggers as Array<{\n parameters?: {\n cronExpression?: string\n timezone?: string\n [key: string]: any\n }\n type: string\n }>\n\n // Find all cron triggers for this workflow\n const cronTriggers = triggers?.filter(t => t.type === 'cron-trigger') || []\n\n for (const trigger of cronTriggers) {\n if (trigger.parameters?.cronExpression) {\n try {\n // Validate cron expression before queueing\n if (!validateCronExpression(trigger.parameters.cronExpression)) {\n logger.error({\n cronExpression: trigger.parameters.cronExpression,\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Invalid cron expression format')\n continue\n }\n\n // Validate timezone if provided\n if (trigger.parameters?.timezone) {\n try {\n // Test if timezone is valid by trying to create a date with it\n new Intl.DateTimeFormat('en', { timeZone: trigger.parameters.timezone })\n } catch {\n logger.error({\n timezone: trigger.parameters.timezone,\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Invalid timezone specified')\n continue\n }\n }\n\n // Calculate next execution time\n const nextExecution = getNextCronTime(trigger.parameters.cronExpression, trigger.parameters?.timezone)\n\n // Queue the job\n await payload.jobs.queue({\n input: { cronExpression: trigger.parameters.cronExpression, timezone: trigger.parameters?.timezone, workflowId: workflow.id },\n task: 'workflow-cron-executor',\n waitUntil: nextExecution\n })\n\n logger.info({\n cronExpression: trigger.parameters.cronExpression,\n nextExecution: nextExecution.toISOString(),\n timezone: trigger.parameters?.timezone || 'UTC',\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Queued initial cron job for workflow')\n } catch (error) {\n logger.error({\n cronExpression: trigger.parameters.cronExpression,\n error: error instanceof Error ? error.message : 'Unknown error',\n timezone: trigger.parameters?.timezone,\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Failed to queue cron job')\n }\n } else {\n logger.warn({\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Cron trigger found but no cron expression specified')\n }\n }\n }\n } catch (error) {\n logger.error({\n error: error instanceof Error ? error.message : 'Unknown error'\n }, 'Failed to register cron jobs')\n }\n}\n\n/**\n * Validate a cron expression\n */\nexport function validateCronExpression(cronExpression: string): boolean {\n return cron.validate(cronExpression)\n}\n\n/**\n * Calculate the next time a cron expression should run\n */\nfunction getNextCronTime(cronExpression: string, timezone?: string): Date {\n if (!validateCronExpression(cronExpression)) {\n throw new Error(`Invalid cron expression: ${cronExpression}`)\n }\n\n const now = new Date()\n const options: { timezone?: string } = timezone ? { timezone } : {}\n\n // Create a task to find the next execution time\n const task = cron.schedule(cronExpression, () => {}, {\n ...options\n })\n\n // Parse cron expression parts\n const cronParts = cronExpression.trim().split(/\\s+/)\n if (cronParts.length !== 5) {\n void task.destroy()\n throw new Error(`Invalid cron format: ${cronExpression}. Expected 5 parts.`)\n }\n\n const [minutePart, hourPart, dayPart, monthPart, weekdayPart] = cronParts\n\n // Calculate next execution with proper lookahead for any schedule frequency\n // Start from next minute and look ahead systematically\n let testTime = new Date(now.getTime() + 60 * 1000) // Start 1 minute from now\n testTime.setSeconds(0, 0) // Reset seconds and milliseconds\n\n // Maximum iterations to prevent infinite loops (covers ~2 years)\n const maxIterations = 2 * 365 * 24 * 60 // 2 years worth of minutes\n let iterations = 0\n\n while (iterations < maxIterations) {\n const minute = testTime.getMinutes()\n const hour = testTime.getHours()\n const dayOfMonth = testTime.getDate()\n const month = testTime.getMonth() + 1\n const dayOfWeek = testTime.getDay()\n\n if (matchesCronPart(minute, minutePart) &&\n matchesCronPart(hour, hourPart) &&\n matchesCronPart(dayOfMonth, dayPart) &&\n matchesCronPart(month, monthPart) &&\n matchesCronPart(dayOfWeek, weekdayPart)) {\n void task.destroy()\n return testTime\n }\n\n // Increment time intelligently based on cron pattern\n testTime = incrementTimeForCronPattern(testTime, cronParts)\n iterations++\n }\n\n void task.destroy()\n throw new Error(`Could not calculate next execution time for cron expression: ${cronExpression} within reasonable timeframe`)\n}\n\n/**\n * Intelligently increment time based on cron pattern to avoid unnecessary iterations\n */\nfunction incrementTimeForCronPattern(currentTime: Date, cronParts: string[]): Date {\n const [minutePart, hourPart, _dayPart, _monthPart, _weekdayPart] = cronParts\n const nextTime = new Date(currentTime)\n\n // If minute is specific (not wildcard), we can jump to next hour\n if (minutePart !== '*' && !minutePart.includes('/')) {\n const targetMinute = getNextValidCronValue(currentTime.getMinutes(), minutePart)\n if (targetMinute <= currentTime.getMinutes()) {\n // Move to next hour\n nextTime.setHours(nextTime.getHours() + 1, targetMinute, 0, 0)\n } else {\n nextTime.setMinutes(targetMinute, 0, 0)\n }\n return nextTime\n }\n\n // If hour is specific and we're past it, jump to next day\n if (hourPart !== '*' && !hourPart.includes('/')) {\n const targetHour = getNextValidCronValue(currentTime.getHours(), hourPart)\n if (targetHour <= currentTime.getHours()) {\n // Move to next day\n nextTime.setDate(nextTime.getDate() + 1)\n nextTime.setHours(targetHour, 0, 0, 0)\n } else {\n nextTime.setHours(targetHour, 0, 0, 0)\n }\n return nextTime\n }\n\n // Default: increment by 1 minute\n nextTime.setTime(nextTime.getTime() + 60 * 1000)\n return nextTime\n}\n\n/**\n * Get the next valid value for a cron part\n */\nfunction getNextValidCronValue(currentValue: number, cronPart: string): number {\n if (cronPart === '*') {return currentValue + 1}\n\n // Handle specific values and ranges\n const values = parseCronPart(cronPart)\n return values.find(v => v > currentValue) || values[0]\n}\n\n/**\n * Parse a cron part into an array of valid values\n */\nfunction parseCronPart(cronPart: string): number[] {\n if (cronPart === '*') {return []}\n\n const values: number[] = []\n\n // Handle comma-separated values\n if (cronPart.includes(',')) {\n cronPart.split(',').forEach(part => {\n values.push(...parseCronPart(part.trim()))\n })\n return values.sort((a, b) => a - b)\n }\n\n // Handle ranges\n if (cronPart.includes('-')) {\n const [start, end] = cronPart.split('-').map(n => parseInt(n, 10))\n for (let i = start; i <= end; i++) {\n values.push(i)\n }\n return values\n }\n\n // Handle step values\n if (cronPart.includes('/')) {\n const [range, step] = cronPart.split('/')\n const stepNum = parseInt(step, 10)\n\n if (range === '*') {\n // For wildcards with steps, return empty - handled elsewhere\n return []\n }\n\n const baseValues = parseCronPart(range)\n return baseValues.filter((_, index) => index % stepNum === 0)\n }\n\n // Single value\n values.push(parseInt(cronPart, 10))\n return values\n}\n\n/**\n * Check if a value matches a cron expression part\n */\nfunction matchesCronPart(value: number, cronPart: string): boolean {\n if (cronPart === '*') {return true}\n\n // Handle step values (e.g., */5)\n if (cronPart.includes('/')) {\n const [range, step] = cronPart.split('/')\n const stepNum = parseInt(step, 10)\n\n if (range === '*') {\n return value % stepNum === 0\n }\n }\n\n // Handle ranges (e.g., 1-5)\n if (cronPart.includes('-')) {\n const [start, end] = cronPart.split('-').map(n => parseInt(n, 10))\n return value >= start && value <= end\n }\n\n // Handle comma-separated values (e.g., 1,3,5)\n if (cronPart.includes(',')) {\n const values = cronPart.split(',').map(n => parseInt(n, 10))\n return values.includes(value)\n }\n\n // Handle single value\n const cronValue = parseInt(cronPart, 10)\n return value === cronValue\n}\n\n/**\n * Handle re-queueing of cron jobs after they execute\n * This ensures the job runs again at the next scheduled time\n */\nexport async function requeueCronJob(\n workflowId: string,\n cronExpression: string,\n timezone: string | undefined,\n payload: Payload,\n logger: Payload['logger']\n): Promise<void> {\n try {\n // Queue the job to run at the next scheduled time\n await payload.jobs.queue({\n input: { cronExpression, timezone, workflowId },\n task: 'workflow-cron-executor',\n waitUntil: getNextCronTime(cronExpression, timezone)\n })\n\n logger.debug({\n nextRun: getNextCronTime(cronExpression, timezone),\n timezone: timezone || 'UTC',\n workflowId\n }, 'Re-queued cron job')\n } catch (error) {\n logger.error({\n error: error instanceof Error ? error.message : 'Unknown error',\n workflowId\n }, 'Failed to re-queue cron job')\n }\n}\n\n/**\n * Register or update cron jobs for a specific workflow\n */\nexport async function updateWorkflowCronJobs(\n workflowId: string,\n payload: Payload,\n logger: Payload['logger']\n): Promise<void> {\n try {\n // First, cancel any existing cron jobs for this workflow\n cancelWorkflowCronJobs(workflowId, payload, logger)\n\n // Get the workflow\n const workflow = await payload.findByID({\n id: workflowId,\n collection: 'workflows',\n depth: 0\n })\n\n if (!workflow) {\n logger.warn({ workflowId }, 'Workflow not found for cron job update')\n return\n }\n\n const triggers = workflow.triggers as Array<{\n parameters?: {\n cronExpression?: string\n timezone?: string\n [key: string]: any\n }\n type: string\n }>\n\n // Find all cron triggers for this workflow\n const cronTriggers = triggers?.filter(t => t.type === 'cron-trigger') || []\n\n if (cronTriggers.length === 0) {\n logger.debug({ workflowId }, 'No cron triggers found for workflow')\n return\n }\n\n let scheduledJobs = 0\n\n for (const trigger of cronTriggers) {\n if (trigger.parameters?.cronExpression) {\n try {\n // Validate cron expression before queueing\n if (!validateCronExpression(trigger.parameters.cronExpression)) {\n logger.error({\n cronExpression: trigger.parameters.cronExpression,\n workflowId,\n workflowName: workflow.name\n }, 'Invalid cron expression format')\n continue\n }\n\n // Validate timezone if provided\n if (trigger.parameters?.timezone) {\n try {\n new Intl.DateTimeFormat('en', { timeZone: trigger.parameters.timezone })\n } catch {\n logger.error({\n timezone: trigger.parameters.timezone,\n workflowId,\n workflowName: workflow.name\n }, 'Invalid timezone specified')\n continue\n }\n }\n\n // Calculate next execution time\n const nextExecution = getNextCronTime(trigger.parameters.cronExpression, trigger.parameters?.timezone)\n\n // Queue the job\n await payload.jobs.queue({\n input: { cronExpression: trigger.parameters.cronExpression, timezone: trigger.parameters?.timezone, workflowId },\n task: 'workflow-cron-executor',\n waitUntil: nextExecution\n })\n\n scheduledJobs++\n\n logger.info({\n cronExpression: trigger.parameters.cronExpression,\n nextExecution: nextExecution.toISOString(),\n timezone: trigger.parameters?.timezone || 'UTC',\n workflowId,\n workflowName: workflow.name\n }, 'Scheduled cron job for workflow')\n } catch (error) {\n logger.error({\n cronExpression: trigger.parameters?.cronExpression,\n error: error instanceof Error ? error.message : 'Unknown error',\n timezone: trigger.parameters?.timezone,\n workflowId,\n workflowName: workflow.name\n }, 'Failed to schedule cron job')\n }\n }\n }\n\n if (scheduledJobs > 0) {\n logger.info({ scheduledJobs, workflowId }, 'Updated cron jobs for workflow')\n }\n } catch (error) {\n logger.error({\n error: error instanceof Error ? error.message : 'Unknown error',\n workflowId\n }, 'Failed to update workflow cron jobs')\n }\n}\n\n/**\n * Cancel all cron jobs for a specific workflow\n */\nexport function cancelWorkflowCronJobs(\n workflowId: string,\n payload: Payload,\n logger: Payload['logger']\n): void {\n try {\n // Note: PayloadCMS job system doesn't have a built-in way to cancel specific jobs by input\n // This is a limitation we need to work around\n // For now, we log that we would cancel jobs for this workflow\n logger.debug({ workflowId }, 'Would cancel existing cron jobs for workflow (PayloadCMS limitation: cannot selectively cancel jobs)')\n } catch (error) {\n logger.error({\n error: error instanceof Error ? error.message : 'Unknown error',\n workflowId\n }, 'Failed to cancel workflow cron jobs')\n }\n}\n\n/**\n * Remove cron jobs for a deleted workflow\n */\nexport function removeWorkflowCronJobs(\n workflowId: string,\n payload: Payload,\n logger: Payload['logger']\n): void {\n try {\n cancelWorkflowCronJobs(workflowId, payload, logger)\n logger.info({ workflowId }, 'Removed cron jobs for deleted workflow')\n } catch (error) {\n logger.error({\n error: error instanceof Error ? error.message : 'Unknown error',\n workflowId\n }, 'Failed to remove workflow cron jobs')\n }\n}\n"],"names":["cron","WorkflowExecutor","getConfigLogger","generateCronTasks","config","logger","cronTask","slug","handler","input","req","cronExpression","timezone","workflowId","payload","child","plugin","workflow","findByID","id","collection","depth","Error","context","steps","trigger","type","triggeredAt","Date","toISOString","executor","triggers","matchingTrigger","find","parameters","condition","conditionMet","evaluateCondition","info","workflowName","name","requeueCronJob","output","executedAt","reason","status","state","execute","error","message","includes","catch","requeueError","jobs","tasks","task","debug","push","registerCronJobs","workflows","limit","where","equals","docs","length","cronTriggers","filter","t","validateCronExpression","Intl","DateTimeFormat","timeZone","nextExecution","getNextCronTime","queue","waitUntil","warn","validate","now","options","schedule","cronParts","trim","split","destroy","minutePart","hourPart","dayPart","monthPart","weekdayPart","testTime","getTime","setSeconds","maxIterations","iterations","minute","getMinutes","hour","getHours","dayOfMonth","getDate","month","getMonth","dayOfWeek","getDay","matchesCronPart","incrementTimeForCronPattern","currentTime","_dayPart","_monthPart","_weekdayPart","nextTime","targetMinute","getNextValidCronValue","setHours","setMinutes","targetHour","setDate","setTime","currentValue","cronPart","values","parseCronPart","v","forEach","part","sort","a","b","start","end","map","n","parseInt","i","range","step","stepNum","baseValues","_","index","value","cronValue","nextRun","updateWorkflowCronJobs","cancelWorkflowCronJobs","scheduledJobs","removeWorkflowCronJobs"],"mappings":"AAEA,OAAOA,UAAU,YAAW;AAE5B,SAA8BC,gBAAgB,QAAO,+BAA8B;AACnF,SAAQC,eAAe,QAAO,cAAa;AAE3C;;;CAGC,GACD,OAAO,SAASC,kBAAkBC,MAAc;IAC9C,MAAMC,SAASH;IAEf,uFAAuF;IACvF,uEAAuE;IACvE,MAAMI,WAAuB;QAC3BC,MAAM;QACNC,SAAS,OAAO,EAAEC,KAAK,EAAEC,GAAG,EAAE;YAC5B,MAAM,EAAEC,cAAc,EAAEC,QAAQ,EAAEC,UAAU,EAAE,GAAGJ;YAMjD,MAAMJ,SAASK,IAAII,OAAO,CAACT,MAAM,CAACU,KAAK,CAAC;gBAAEC,QAAQ;YAA8B;YAEhF,IAAI;gBACF,mBAAmB;gBACnB,MAAMC,WAAW,MAAMP,IAAII,OAAO,CAACI,QAAQ,CAAC;oBAC1CC,IAAIN;oBACJO,YAAY;oBACZC,OAAO;oBACPX;gBACF;gBAEA,IAAI,CAACO,UAAU;oBACb,MAAM,IAAIK,MAAM,CAAC,SAAS,EAAET,WAAW,UAAU,CAAC;gBACpD;gBAEA,4CAA4C;gBAC5C,MAAMU,UAAU;oBACdC,OAAO,CAAC;oBACRC,SAAS;wBACPC,MAAM;wBACNhB;wBACAiB,aAAa,IAAIC,OAAOC,WAAW;oBACrC;gBACF;gBAEA,kBAAkB;gBAClB,MAAMC,WAAW,IAAI7B,iBAAiBS,IAAII,OAAO,EAAET;gBAEnD,oEAAoE;gBACpE,MAAM0B,WAAWd,SAASc,QAAQ;gBAUlC,MAAMC,kBAAkBD,UAAUE,KAAKR,CAAAA,UACrCA,QAAQC,IAAI,KAAK,kBACjBD,QAAQS,UAAU,EAAEvB,mBAAmBA;gBAGzC,qCAAqC;gBACrC,IAAIqB,iBAAiBG,WAAW;oBAC9B,MAAMC,eAAeN,SAASO,iBAAiB,CAACL,gBAAgBG,SAAS,EAAEZ;oBAE3E,IAAI,CAACa,cAAc;wBACjB/B,OAAOiC,IAAI,CAAC;4BACVH,WAAWH,gBAAgBG,SAAS;4BACpCxB;4BACAE;4BACA0B,cAActB,SAASuB,IAAI;wBAC7B,GAAG;wBAEH,qDAAqD;wBACrD,IAAI7B,gBAAgB;4BAClB,KAAK8B,eAAe5B,YAAYF,gBAAgBC,UAAUF,IAAII,OAAO,EAAET;wBACzE;wBAEA,OAAO;4BACLqC,QAAQ;gCACNC,YAAY,IAAIf,OAAOC,WAAW;gCAClCe,QAAQ;gCACRC,QAAQ;gCACRhC;4BACF;4BACAiC,OAAO;wBACT;oBACF;oBAEAzC,OAAOiC,IAAI,CAAC;wBACVH,WAAWH,gBAAgBG,SAAS;wBACpCxB;wBACAE;wBACA0B,cAActB,SAASuB,IAAI;oBAC7B,GAAG;gBACL;gBAEA,uBAAuB;gBACvB,MAAMV,SAASiB,OAAO,CAAC9B,UAA6BM,SAASb;gBAE7D,kFAAkF;gBAClF,IAAIC,gBAAgB;oBAClB,KAAK8B,eAAe5B,YAAYF,gBAAgBC,UAAUF,IAAII,OAAO,EAAET;gBACzE;gBAEA,OAAO;oBACLqC,QAAQ;wBACNC,YAAY,IAAIf,OAAOC,WAAW;wBAClCgB,QAAQ;wBACRhC;oBACF;oBACAiC,OAAO;gBACT;YACF,EAAE,OAAOE,OAAO;gBACd3C,OAAO2C,KAAK,CAAC;oBACXA,OAAOA,iBAAiB1B,QAAQ0B,MAAMC,OAAO,GAAG;oBAChDpC;gBACF,GAAG;gBAEH,iFAAiF;gBACjF,IAAIF,kBAAkB,CAAEqC,CAAAA,iBAAiB1B,SAAS0B,MAAMC,OAAO,CAACC,QAAQ,CAAC,eAAc,GAAI;oBACzF,KAAKT,eAAe5B,YAAYF,gBAAgBC,UAAUF,IAAII,OAAO,EAAET,QACpE8C,KAAK,CAAC,CAACC;wBACN/C,OAAO2C,KAAK,CAAC;4BACXA,OAAOI,wBAAwB9B,QAAQ8B,aAAaH,OAAO,GAAG;4BAC9DpC;wBACF,GAAG;oBACL;gBACJ;gBAEA,OAAO;oBACL6B,QAAQ;wBACNM,OAAOA,iBAAiB1B,QAAQ0B,MAAMC,OAAO,GAAG;wBAChDpC;oBACF;oBACAiC,OAAO;gBACT;YACF;QACF;IACF;IAEA,qDAAqD;IACrD,IAAI,CAAC1C,OAAOiD,IAAI,EAAE;QAChBjD,OAAOiD,IAAI,GAAG;YAAEC,OAAO,EAAE;QAAC;IAC5B;IAEA,IAAI,CAAClD,OAAOiD,IAAI,CAACC,KAAK,EAAE;QACtBlD,OAAOiD,IAAI,CAACC,KAAK,GAAG,EAAE;IACxB;IAEA,IAAI,CAAClD,OAAOiD,IAAI,CAACC,KAAK,CAACrB,IAAI,CAACsB,CAAAA,OAAQA,KAAKhD,IAAI,KAAKD,SAASC,IAAI,GAAG;QAChEF,OAAOmD,KAAK,CAAC,CAAC,gCAAgC,EAAElD,SAASC,IAAI,EAAE;QAC/DH,OAAOiD,IAAI,CAACC,KAAK,CAACG,IAAI,CAACnD;IACzB,OAAO;QACLD,OAAOmD,KAAK,CAAC,CAAC,mBAAmB,EAAElD,SAASC,IAAI,CAAC,6BAA6B,CAAC;IACjF;AACF;AAEA;;;CAGC,GACD,OAAO,eAAemD,iBAAiB5C,OAAgB,EAAET,MAAyB;IAChF,IAAI;QACF,wCAAwC;QACxC,MAAMsD,YAAY,MAAM7C,QAAQmB,IAAI,CAAC;YACnCb,YAAY;YACZC,OAAO;YACPuC,OAAO;YACPC,OAAO;gBACL,iBAAiB;oBACfC,QAAQ;gBACV;YACF;QACF;QAEAzD,OAAOiC,IAAI,CAAC,CAAC,MAAM,EAAEqB,UAAUI,IAAI,CAACC,MAAM,CAAC,6BAA6B,CAAC;QAEzE,KAAK,MAAM/C,YAAY0C,UAAUI,IAAI,CAAE;YACrC,MAAMhC,WAAWd,SAASc,QAAQ;YASlC,2CAA2C;YAC3C,MAAMkC,eAAelC,UAAUmC,OAAOC,CAAAA,IAAKA,EAAEzC,IAAI,KAAK,mBAAmB,EAAE;YAE3E,KAAK,MAAMD,WAAWwC,aAAc;gBAClC,IAAIxC,QAAQS,UAAU,EAAEvB,gBAAgB;oBACtC,IAAI;wBACF,2CAA2C;wBAC3C,IAAI,CAACyD,uBAAuB3C,QAAQS,UAAU,CAACvB,cAAc,GAAG;4BAC9DN,OAAO2C,KAAK,CAAC;gCACXrC,gBAAgBc,QAAQS,UAAU,CAACvB,cAAc;gCACjDE,YAAYI,SAASE,EAAE;gCACvBoB,cAActB,SAASuB,IAAI;4BAC7B,GAAG;4BACH;wBACF;wBAEA,gCAAgC;wBAChC,IAAIf,QAAQS,UAAU,EAAEtB,UAAU;4BAChC,IAAI;gCACF,+DAA+D;gCAC/D,IAAIyD,KAAKC,cAAc,CAAC,MAAM;oCAAEC,UAAU9C,QAAQS,UAAU,CAACtB,QAAQ;gCAAC;4BACxE,EAAE,OAAM;gCACNP,OAAO2C,KAAK,CAAC;oCACXpC,UAAUa,QAAQS,UAAU,CAACtB,QAAQ;oCACrCC,YAAYI,SAASE,EAAE;oCACvBoB,cAActB,SAASuB,IAAI;gCAC7B,GAAG;gCACH;4BACF;wBACF;wBAEA,gCAAgC;wBAChC,MAAMgC,gBAAgBC,gBAAgBhD,QAAQS,UAAU,CAACvB,cAAc,EAAEc,QAAQS,UAAU,EAAEtB;wBAE7F,gBAAgB;wBAChB,MAAME,QAAQuC,IAAI,CAACqB,KAAK,CAAC;4BACvBjE,OAAO;gCAAEE,gBAAgBc,QAAQS,UAAU,CAACvB,cAAc;gCAAEC,UAAUa,QAAQS,UAAU,EAAEtB;gCAAUC,YAAYI,SAASE,EAAE;4BAAC;4BAC5HoC,MAAM;4BACNoB,WAAWH;wBACb;wBAEAnE,OAAOiC,IAAI,CAAC;4BACV3B,gBAAgBc,QAAQS,UAAU,CAACvB,cAAc;4BACjD6D,eAAeA,cAAc3C,WAAW;4BACxCjB,UAAUa,QAAQS,UAAU,EAAEtB,YAAY;4BAC1CC,YAAYI,SAASE,EAAE;4BACvBoB,cAActB,SAASuB,IAAI;wBAC7B,GAAG;oBACL,EAAE,OAAOQ,OAAO;wBACd3C,OAAO2C,KAAK,CAAC;4BACXrC,gBAAgBc,QAAQS,UAAU,CAACvB,cAAc;4BACjDqC,OAAOA,iBAAiB1B,QAAQ0B,MAAMC,OAAO,GAAG;4BAChDrC,UAAUa,QAAQS,UAAU,EAAEtB;4BAC9BC,YAAYI,SAASE,EAAE;4BACvBoB,cAActB,SAASuB,IAAI;wBAC7B,GAAG;oBACL;gBACF,OAAO;oBACLnC,OAAOuE,IAAI,CAAC;wBACV/D,YAAYI,SAASE,EAAE;wBACvBoB,cAActB,SAASuB,IAAI;oBAC7B,GAAG;gBACL;YACF;QACF;IACF,EAAE,OAAOQ,OAAO;QACd3C,OAAO2C,KAAK,CAAC;YACXA,OAAOA,iBAAiB1B,QAAQ0B,MAAMC,OAAO,GAAG;QAClD,GAAG;IACL;AACF;AAEA;;CAEC,GACD,OAAO,SAASmB,uBAAuBzD,cAAsB;IAC3D,OAAOX,KAAK6E,QAAQ,CAAClE;AACvB;AAEA;;CAEC,GACD,SAAS8D,gBAAgB9D,cAAsB,EAAEC,QAAiB;IAChE,IAAI,CAACwD,uBAAuBzD,iBAAiB;QAC3C,MAAM,IAAIW,MAAM,CAAC,yBAAyB,EAAEX,gBAAgB;IAC9D;IAEA,MAAMmE,MAAM,IAAIlD;IAChB,MAAMmD,UAAiCnE,WAAW;QAAEA;IAAS,IAAI,CAAC;IAElE,gDAAgD;IAChD,MAAM2C,OAAOvD,KAAKgF,QAAQ,CAACrE,gBAAgB,KAAO,GAAG;QACnD,GAAGoE,OAAO;IACZ;IAEA,8BAA8B;IAC9B,MAAME,YAAYtE,eAAeuE,IAAI,GAAGC,KAAK,CAAC;IAC9C,IAAIF,UAAUjB,MAAM,KAAK,GAAG;QAC1B,KAAKT,KAAK6B,OAAO;QACjB,MAAM,IAAI9D,MAAM,CAAC,qBAAqB,EAAEX,eAAe,mBAAmB,CAAC;IAC7E;IAEA,MAAM,CAAC0E,YAAYC,UAAUC,SAASC,WAAWC,YAAY,GAAGR;IAEhE,4EAA4E;IAC5E,uDAAuD;IACvD,IAAIS,WAAW,IAAI9D,KAAKkD,IAAIa,OAAO,KAAK,KAAK,MAAM,0BAA0B;;IAC7ED,SAASE,UAAU,CAAC,GAAG,IAAG,iCAAiC;IAE3D,iEAAiE;IACjE,MAAMC,gBAAgB,IAAI,MAAM,KAAK,GAAG,2BAA2B;;IACnE,IAAIC,aAAa;IAEjB,MAAOA,aAAaD,cAAe;QACjC,MAAME,SAASL,SAASM,UAAU;QAClC,MAAMC,OAAOP,SAASQ,QAAQ;QAC9B,MAAMC,aAAaT,SAASU,OAAO;QACnC,MAAMC,QAAQX,SAASY,QAAQ,KAAK;QACpC,MAAMC,YAAYb,SAASc,MAAM;QAEjC,IAAIC,gBAAgBV,QAAQV,eACxBoB,gBAAgBR,MAAMX,aACtBmB,gBAAgBN,YAAYZ,YAC5BkB,gBAAgBJ,OAAOb,cACvBiB,gBAAgBF,WAAWd,cAAc;YAC3C,KAAKlC,KAAK6B,OAAO;YACjB,OAAOM;QACT;QAEA,qDAAqD;QACrDA,WAAWgB,4BAA4BhB,UAAUT;QACjDa;IACF;IAEA,KAAKvC,KAAK6B,OAAO;IACjB,MAAM,IAAI9D,MAAM,CAAC,6DAA6D,EAAEX,eAAe,4BAA4B,CAAC;AAC9H;AAEA;;CAEC,GACD,SAAS+F,4BAA4BC,WAAiB,EAAE1B,SAAmB;IACzE,MAAM,CAACI,YAAYC,UAAUsB,UAAUC,YAAYC,aAAa,GAAG7B;IACnE,MAAM8B,WAAW,IAAInF,KAAK+E;IAE1B,iEAAiE;IACjE,IAAItB,eAAe,OAAO,CAACA,WAAWnC,QAAQ,CAAC,MAAM;QACnD,MAAM8D,eAAeC,sBAAsBN,YAAYX,UAAU,IAAIX;QACrE,IAAI2B,gBAAgBL,YAAYX,UAAU,IAAI;YAC5C,oBAAoB;YACpBe,SAASG,QAAQ,CAACH,SAASb,QAAQ,KAAK,GAAGc,cAAc,GAAG;QAC9D,OAAO;YACLD,SAASI,UAAU,CAACH,cAAc,GAAG;QACvC;QACA,OAAOD;IACT;IAEA,0DAA0D;IAC1D,IAAIzB,aAAa,OAAO,CAACA,SAASpC,QAAQ,CAAC,MAAM;QAC/C,MAAMkE,aAAaH,sBAAsBN,YAAYT,QAAQ,IAAIZ;QACjE,IAAI8B,cAAcT,YAAYT,QAAQ,IAAI;YACxC,mBAAmB;YACnBa,SAASM,OAAO,CAACN,SAASX,OAAO,KAAK;YACtCW,SAASG,QAAQ,CAACE,YAAY,GAAG,GAAG;QACtC,OAAO;YACLL,SAASG,QAAQ,CAACE,YAAY,GAAG,GAAG;QACtC;QACA,OAAOL;IACT;IAEA,iCAAiC;IACjCA,SAASO,OAAO,CAACP,SAASpB,OAAO,KAAK,KAAK;IAC3C,OAAOoB;AACT;AAEA;;CAEC,GACD,SAASE,sBAAsBM,YAAoB,EAAEC,QAAgB;IACnE,IAAIA,aAAa,KAAK;QAAC,OAAOD,eAAe;IAAC;IAE9C,oCAAoC;IACpC,MAAME,SAASC,cAAcF;IAC7B,OAAOC,OAAOxF,IAAI,CAAC0F,CAAAA,IAAKA,IAAIJ,iBAAiBE,MAAM,CAAC,EAAE;AACxD;AAEA;;CAEC,GACD,SAASC,cAAcF,QAAgB;IACrC,IAAIA,aAAa,KAAK;QAAC,OAAO,EAAE;IAAA;IAEhC,MAAMC,SAAmB,EAAE;IAE3B,gCAAgC;IAChC,IAAID,SAAStE,QAAQ,CAAC,MAAM;QAC1BsE,SAASrC,KAAK,CAAC,KAAKyC,OAAO,CAACC,CAAAA;YAC1BJ,OAAOhE,IAAI,IAAIiE,cAAcG,KAAK3C,IAAI;QACxC;QACA,OAAOuC,OAAOK,IAAI,CAAC,CAACC,GAAGC,IAAMD,IAAIC;IACnC;IAEA,gBAAgB;IAChB,IAAIR,SAAStE,QAAQ,CAAC,MAAM;QAC1B,MAAM,CAAC+E,OAAOC,IAAI,GAAGV,SAASrC,KAAK,CAAC,KAAKgD,GAAG,CAACC,CAAAA,IAAKC,SAASD,GAAG;QAC9D,IAAK,IAAIE,IAAIL,OAAOK,KAAKJ,KAAKI,IAAK;YACjCb,OAAOhE,IAAI,CAAC6E;QACd;QACA,OAAOb;IACT;IAEA,qBAAqB;IACrB,IAAID,SAAStE,QAAQ,CAAC,MAAM;QAC1B,MAAM,CAACqF,OAAOC,KAAK,GAAGhB,SAASrC,KAAK,CAAC;QACrC,MAAMsD,UAAUJ,SAASG,MAAM;QAE/B,IAAID,UAAU,KAAK;YACjB,6DAA6D;YAC7D,OAAO,EAAE;QACX;QAEA,MAAMG,aAAahB,cAAca;QACjC,OAAOG,WAAWxE,MAAM,CAAC,CAACyE,GAAGC,QAAUA,QAAQH,YAAY;IAC7D;IAEA,eAAe;IACfhB,OAAOhE,IAAI,CAAC4E,SAASb,UAAU;IAC/B,OAAOC;AACT;AAEA;;CAEC,GACD,SAAShB,gBAAgBoC,KAAa,EAAErB,QAAgB;IACtD,IAAIA,aAAa,KAAK;QAAC,OAAO;IAAI;IAElC,iCAAiC;IACjC,IAAIA,SAAStE,QAAQ,CAAC,MAAM;QAC1B,MAAM,CAACqF,OAAOC,KAAK,GAAGhB,SAASrC,KAAK,CAAC;QACrC,MAAMsD,UAAUJ,SAASG,MAAM;QAE/B,IAAID,UAAU,KAAK;YACjB,OAAOM,QAAQJ,YAAY;QAC7B;IACF;IAEA,4BAA4B;IAC5B,IAAIjB,SAAStE,QAAQ,CAAC,MAAM;QAC1B,MAAM,CAAC+E,OAAOC,IAAI,GAAGV,SAASrC,KAAK,CAAC,KAAKgD,GAAG,CAACC,CAAAA,IAAKC,SAASD,GAAG;QAC9D,OAAOS,SAASZ,SAASY,SAASX;IACpC;IAEA,8CAA8C;IAC9C,IAAIV,SAAStE,QAAQ,CAAC,MAAM;QAC1B,MAAMuE,SAASD,SAASrC,KAAK,CAAC,KAAKgD,GAAG,CAACC,CAAAA,IAAKC,SAASD,GAAG;QACxD,OAAOX,OAAOvE,QAAQ,CAAC2F;IACzB;IAEA,sBAAsB;IACtB,MAAMC,YAAYT,SAASb,UAAU;IACrC,OAAOqB,UAAUC;AACnB;AAEA;;;CAGC,GACD,OAAO,eAAerG,eACpB5B,UAAkB,EAClBF,cAAsB,EACtBC,QAA4B,EAC5BE,OAAgB,EAChBT,MAAyB;IAEzB,IAAI;QACF,kDAAkD;QAClD,MAAMS,QAAQuC,IAAI,CAACqB,KAAK,CAAC;YACvBjE,OAAO;gBAAEE;gBAAgBC;gBAAUC;YAAW;YAC9C0C,MAAM;YACNoB,WAAWF,gBAAgB9D,gBAAgBC;QAC7C;QAEAP,OAAOmD,KAAK,CAAC;YACXuF,SAAStE,gBAAgB9D,gBAAgBC;YACzCA,UAAUA,YAAY;YACtBC;QACF,GAAG;IACL,EAAE,OAAOmC,OAAO;QACd3C,OAAO2C,KAAK,CAAC;YACXA,OAAOA,iBAAiB1B,QAAQ0B,MAAMC,OAAO,GAAG;YAChDpC;QACF,GAAG;IACL;AACF;AAEA;;CAEC,GACD,OAAO,eAAemI,uBACpBnI,UAAkB,EAClBC,OAAgB,EAChBT,MAAyB;IAEzB,IAAI;QACF,yDAAyD;QACzD4I,uBAAuBpI,YAAYC,SAAST;QAE5C,mBAAmB;QACnB,MAAMY,WAAW,MAAMH,QAAQI,QAAQ,CAAC;YACtCC,IAAIN;YACJO,YAAY;YACZC,OAAO;QACT;QAEA,IAAI,CAACJ,UAAU;YACbZ,OAAOuE,IAAI,CAAC;gBAAE/D;YAAW,GAAG;YAC5B;QACF;QAEA,MAAMkB,WAAWd,SAASc,QAAQ;QASlC,2CAA2C;QAC3C,MAAMkC,eAAelC,UAAUmC,OAAOC,CAAAA,IAAKA,EAAEzC,IAAI,KAAK,mBAAmB,EAAE;QAE3E,IAAIuC,aAAaD,MAAM,KAAK,GAAG;YAC7B3D,OAAOmD,KAAK,CAAC;gBAAE3C;YAAW,GAAG;YAC7B;QACF;QAEA,IAAIqI,gBAAgB;QAEpB,KAAK,MAAMzH,WAAWwC,aAAc;YAClC,IAAIxC,QAAQS,UAAU,EAAEvB,gBAAgB;gBACtC,IAAI;oBACF,2CAA2C;oBAC3C,IAAI,CAACyD,uBAAuB3C,QAAQS,UAAU,CAACvB,cAAc,GAAG;wBAC9DN,OAAO2C,KAAK,CAAC;4BACXrC,gBAAgBc,QAAQS,UAAU,CAACvB,cAAc;4BACjDE;4BACA0B,cAActB,SAASuB,IAAI;wBAC7B,GAAG;wBACH;oBACF;oBAEA,gCAAgC;oBAChC,IAAIf,QAAQS,UAAU,EAAEtB,UAAU;wBAChC,IAAI;4BACF,IAAIyD,KAAKC,cAAc,CAAC,MAAM;gCAAEC,UAAU9C,QAAQS,UAAU,CAACtB,QAAQ;4BAAC;wBACxE,EAAE,OAAM;4BACNP,OAAO2C,KAAK,CAAC;gCACXpC,UAAUa,QAAQS,UAAU,CAACtB,QAAQ;gCACrCC;gCACA0B,cAActB,SAASuB,IAAI;4BAC7B,GAAG;4BACH;wBACF;oBACF;oBAEA,gCAAgC;oBAChC,MAAMgC,gBAAgBC,gBAAgBhD,QAAQS,UAAU,CAACvB,cAAc,EAAEc,QAAQS,UAAU,EAAEtB;oBAE7F,gBAAgB;oBAChB,MAAME,QAAQuC,IAAI,CAACqB,KAAK,CAAC;wBACvBjE,OAAO;4BAAEE,gBAAgBc,QAAQS,UAAU,CAACvB,cAAc;4BAAEC,UAAUa,QAAQS,UAAU,EAAEtB;4BAAUC;wBAAW;wBAC/G0C,MAAM;wBACNoB,WAAWH;oBACb;oBAEA0E;oBAEA7I,OAAOiC,IAAI,CAAC;wBACV3B,gBAAgBc,QAAQS,UAAU,CAACvB,cAAc;wBACjD6D,eAAeA,cAAc3C,WAAW;wBACxCjB,UAAUa,QAAQS,UAAU,EAAEtB,YAAY;wBAC1CC;wBACA0B,cAActB,SAASuB,IAAI;oBAC7B,GAAG;gBACL,EAAE,OAAOQ,OAAO;oBACd3C,OAAO2C,KAAK,CAAC;wBACXrC,gBAAgBc,QAAQS,UAAU,EAAEvB;wBACpCqC,OAAOA,iBAAiB1B,QAAQ0B,MAAMC,OAAO,GAAG;wBAChDrC,UAAUa,QAAQS,UAAU,EAAEtB;wBAC9BC;wBACA0B,cAActB,SAASuB,IAAI;oBAC7B,GAAG;gBACL;YACF;QACF;QAEA,IAAI0G,gBAAgB,GAAG;YACrB7I,OAAOiC,IAAI,CAAC;gBAAE4G;gBAAerI;YAAW,GAAG;QAC7C;IACF,EAAE,OAAOmC,OAAO;QACd3C,OAAO2C,KAAK,CAAC;YACXA,OAAOA,iBAAiB1B,QAAQ0B,MAAMC,OAAO,GAAG;YAChDpC;QACF,GAAG;IACL;AACF;AAEA;;CAEC,GACD,OAAO,SAASoI,uBACdpI,UAAkB,EAClBC,OAAgB,EAChBT,MAAyB;IAEzB,IAAI;QACF,2FAA2F;QAC3F,8CAA8C;QAC9C,8DAA8D;QAC9DA,OAAOmD,KAAK,CAAC;YAAE3C;QAAW,GAAG;IAC/B,EAAE,OAAOmC,OAAO;QACd3C,OAAO2C,KAAK,CAAC;YACXA,OAAOA,iBAAiB1B,QAAQ0B,MAAMC,OAAO,GAAG;YAChDpC;QACF,GAAG;IACL;AACF;AAEA;;CAEC,GACD,OAAO,SAASsI,uBACdtI,UAAkB,EAClBC,OAAgB,EAChBT,MAAyB;IAEzB,IAAI;QACF4I,uBAAuBpI,YAAYC,SAAST;QAC5CA,OAAOiC,IAAI,CAAC;YAAEzB;QAAW,GAAG;IAC9B,EAAE,OAAOmC,OAAO;QACd3C,OAAO2C,KAAK,CAAC;YACXA,OAAOA,iBAAiB1B,QAAQ0B,MAAMC,OAAO,GAAG;YAChDpC;QACF,GAAG;IACL;AACF"}
@@ -10,8 +10,8 @@ import { getConfigLogger, initializeLogger } from './logger.js';
10
10
  export { getLogger } from './logger.js';
11
11
  const executorRegistry = {
12
12
  executor: null,
13
- logger: null,
14
- isInitialized: false
13
+ isInitialized: false,
14
+ logger: null
15
15
  };
16
16
  const setWorkflowExecutor = (executor, logger)=>{
17
17
  executorRegistry.executor = executor;
@@ -32,61 +32,61 @@ const createFailedWorkflowRun = async (args, errorMessage, logger)=>{
32
32
  // Find workflows that should have been triggered
33
33
  const workflows = await args.req.payload.find({
34
34
  collection: 'workflows',
35
+ limit: 10,
36
+ req: args.req,
35
37
  where: {
36
- 'triggers.type': {
37
- equals: 'collection-trigger'
38
- },
39
38
  'triggers.collectionSlug': {
40
39
  equals: args.collection.slug
41
40
  },
42
41
  'triggers.operation': {
43
42
  equals: args.operation
43
+ },
44
+ 'triggers.type': {
45
+ equals: 'collection-trigger'
44
46
  }
45
- },
46
- limit: 10,
47
- req: args.req
47
+ }
48
48
  });
49
49
  // Create failed workflow runs for each matching workflow
50
50
  for (const workflow of workflows.docs){
51
51
  await args.req.payload.create({
52
52
  collection: 'workflow-runs',
53
53
  data: {
54
- workflow: workflow.id,
55
- workflowVersion: 1,
56
- status: 'failed',
57
- startedAt: new Date().toISOString(),
58
54
  completedAt: new Date().toISOString(),
59
- error: `Hook execution failed: ${errorMessage}`,
60
- triggeredBy: args?.req?.user?.email || 'system',
61
55
  context: {
56
+ steps: {},
62
57
  trigger: {
63
58
  type: 'collection',
64
59
  collection: args.collection.slug,
65
- operation: args.operation,
66
60
  doc: args.doc,
61
+ operation: args.operation,
67
62
  previousDoc: args.previousDoc,
68
63
  triggeredAt: new Date().toISOString()
69
- },
70
- steps: {}
64
+ }
71
65
  },
66
+ error: `Hook execution failed: ${errorMessage}`,
72
67
  inputs: {},
73
- outputs: {},
74
- steps: [],
75
68
  logs: [
76
69
  {
77
70
  level: 'error',
78
71
  message: `Hook execution failed: ${errorMessage}`,
79
72
  timestamp: new Date().toISOString()
80
73
  }
81
- ]
74
+ ],
75
+ outputs: {},
76
+ startedAt: new Date().toISOString(),
77
+ status: 'failed',
78
+ steps: [],
79
+ triggeredBy: args?.req?.user?.email || 'system',
80
+ workflow: workflow.id,
81
+ workflowVersion: 1
82
82
  },
83
83
  req: args.req
84
84
  });
85
85
  }
86
86
  if (workflows.docs.length > 0) {
87
87
  logger.info({
88
- workflowCount: workflows.docs.length,
89
- errorMessage
88
+ errorMessage,
89
+ workflowCount: workflows.docs.length
90
90
  }, 'Created failed workflow runs for hook execution error');
91
91
  }
92
92
  } catch (error) {
@@ -116,7 +116,9 @@ export const workflowsPlugin = (pluginOptions)=>(config)=>{
116
116
  logger.info('Attempting to modify collection configs before PayloadCMS initialization...');
117
117
  if (config.collections && pluginOptions.collectionTriggers) {
118
118
  for (const [triggerSlug, triggerConfig] of Object.entries(pluginOptions.collectionTriggers)){
119
- if (!triggerConfig) continue;
119
+ if (!triggerConfig) {
120
+ continue;
121
+ }
120
122
  // Find the collection config that matches
121
123
  const collectionIndex = config.collections.findIndex((c)=>c.slug === triggerSlug);
122
124
  if (collectionIndex === -1) {
@@ -140,9 +142,9 @@ export const workflowsPlugin = (pluginOptions)=>(config)=>{
140
142
  try {
141
143
  logger.info({
142
144
  collection: args?.collection?.slug,
143
- operation: args?.operation,
144
145
  docId: args?.doc?.id,
145
- hookType: 'automation'
146
+ hookType: 'automation',
147
+ operation: args?.operation
146
148
  }, 'Collection automation hook triggered');
147
149
  if (!registry.isInitialized) {
148
150
  logger.warn('Workflow executor not yet initialized, skipping execution');
@@ -158,17 +160,17 @@ export const workflowsPlugin = (pluginOptions)=>(config)=>{
158
160
  await registry.executor.executeTriggeredWorkflows(args.collection.slug, args.operation, args.doc, args.previousDoc, args.req);
159
161
  logger.info({
160
162
  collection: args?.collection?.slug,
161
- operation: args?.operation,
162
- docId: args?.doc?.id
163
+ docId: args?.doc?.id,
164
+ operation: args?.operation
163
165
  }, 'Workflow execution completed successfully');
164
166
  } catch (error) {
165
167
  const errorMessage = error instanceof Error ? error.message : 'Unknown error';
166
168
  logger.error({
169
+ collection: args?.collection?.slug,
170
+ docId: args?.doc?.id,
167
171
  error: errorMessage,
168
172
  errorStack: error instanceof Error ? error.stack : undefined,
169
- collection: args?.collection?.slug,
170
- operation: args?.operation,
171
- docId: args?.doc?.id
173
+ operation: args?.operation
172
174
  }, 'Hook execution failed');
173
175
  // Create a failed workflow run to track this error
174
176
  try {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/plugin/index.ts"],"sourcesContent":["import type {Config} from 'payload'\n\nimport type {WorkflowsPluginConfig, CollectionTriggerConfigCrud} from \"./config-types.js\"\n\nimport {createWorkflowCollection} from '../collections/Workflow.js'\nimport {WorkflowRunsCollection} from '../collections/WorkflowRuns.js'\nimport {WorkflowExecutor} from '../core/workflow-executor.js'\nimport {generateCronTasks, registerCronJobs} from './cron-scheduler.js'\nimport {initCollectionHooks} from \"./init-collection-hooks.js\"\nimport {initGlobalHooks} from \"./init-global-hooks.js\"\nimport {initStepTasks} from \"./init-step-tasks.js\"\nimport {initWebhookEndpoint} from \"./init-webhook.js\"\nimport {initWorkflowHooks} from './init-workflow-hooks.js'\nimport {getConfigLogger, initializeLogger} from './logger.js'\n\nexport {getLogger} from './logger.js'\n\n// Improved executor registry with proper error handling and logging\ninterface ExecutorRegistry {\n executor: WorkflowExecutor | null\n logger: any | null\n isInitialized: boolean\n}\n\nconst executorRegistry: ExecutorRegistry = {\n executor: null,\n logger: null,\n isInitialized: false\n}\n\nconst setWorkflowExecutor = (executor: WorkflowExecutor, logger: any) => {\n executorRegistry.executor = executor\n executorRegistry.logger = logger\n executorRegistry.isInitialized = true\n \n logger.info('Workflow executor initialized and registered successfully')\n}\n\nconst getExecutorRegistry = (): ExecutorRegistry => {\n return executorRegistry\n}\n\n// Helper function to create failed workflow runs for tracking errors\nconst createFailedWorkflowRun = async (args: any, errorMessage: string, logger: any) => {\n try {\n // Only create failed workflow runs if we have enough context\n if (!args?.req?.payload || !args?.collection?.slug) {\n return\n }\n \n // Find workflows that should have been triggered\n const workflows = await args.req.payload.find({\n collection: 'workflows',\n where: {\n 'triggers.type': {\n equals: 'collection-trigger'\n },\n 'triggers.collectionSlug': {\n equals: args.collection.slug\n },\n 'triggers.operation': {\n equals: args.operation\n }\n },\n limit: 10,\n req: args.req\n })\n \n // Create failed workflow runs for each matching workflow\n for (const workflow of workflows.docs) {\n await args.req.payload.create({\n collection: 'workflow-runs',\n data: {\n workflow: workflow.id,\n workflowVersion: 1,\n status: 'failed',\n startedAt: new Date().toISOString(),\n completedAt: new Date().toISOString(),\n error: `Hook execution failed: ${errorMessage}`,\n triggeredBy: args?.req?.user?.email || 'system',\n context: {\n trigger: {\n type: 'collection',\n collection: args.collection.slug,\n operation: args.operation,\n doc: args.doc,\n previousDoc: args.previousDoc,\n triggeredAt: new Date().toISOString()\n },\n steps: {}\n },\n inputs: {},\n outputs: {},\n steps: [],\n logs: [{\n level: 'error',\n message: `Hook execution failed: ${errorMessage}`,\n timestamp: new Date().toISOString()\n }]\n },\n req: args.req\n })\n }\n \n if (workflows.docs.length > 0) {\n logger.info({\n workflowCount: workflows.docs.length,\n errorMessage\n }, 'Created failed workflow runs for hook execution error')\n }\n \n } catch (error) {\n // Don't let workflow run creation failures break the original operation\n logger.warn({\n error: error instanceof Error ? error.message : 'Unknown error'\n }, 'Failed to create failed workflow run record')\n }\n}\n\nconst applyCollectionsConfig = <T extends string>(pluginOptions: WorkflowsPluginConfig<T>, config: Config) => {\n // Add workflow collections\n if (!config.collections) {\n config.collections = []\n }\n\n config.collections.push(\n createWorkflowCollection(pluginOptions),\n WorkflowRunsCollection\n )\n}\n\n// Removed config-phase hook registration - user collections don't exist during config phase\n\n\nexport const workflowsPlugin =\n <TSlug extends string>(pluginOptions: WorkflowsPluginConfig<TSlug>) =>\n (config: Config): Config => {\n // If the plugin is disabled, return config unchanged\n if (pluginOptions.enabled === false) {\n return config\n }\n\n applyCollectionsConfig<TSlug>(pluginOptions, config)\n \n // CRITICAL: Modify existing collection configs BEFORE PayloadCMS processes them\n // This is the ONLY time we can add hooks that will actually work\n const logger = getConfigLogger()\n logger.info('Attempting to modify collection configs before PayloadCMS initialization...')\n \n if (config.collections && pluginOptions.collectionTriggers) {\n for (const [triggerSlug, triggerConfig] of Object.entries(pluginOptions.collectionTriggers)) {\n if (!triggerConfig) continue\n \n // Find the collection config that matches\n const collectionIndex = config.collections.findIndex(c => c.slug === triggerSlug)\n if (collectionIndex === -1) {\n logger.warn(`Collection '${triggerSlug}' not found in config.collections`)\n continue\n }\n \n const collection = config.collections[collectionIndex]\n logger.info(`Found collection '${triggerSlug}' - modifying its hooks...`)\n \n // Initialize hooks if needed\n if (!collection.hooks) {\n collection.hooks = {}\n }\n if (!collection.hooks.afterChange) {\n collection.hooks.afterChange = []\n }\n \n // Create a reliable hook function with proper dependency injection\n const automationHook = Object.assign(\n async function payloadAutomationHook(args: any) {\n const registry = getExecutorRegistry()\n \n // Use proper logger if available, fallback to args.req.payload.logger\n const logger = registry.logger || args?.req?.payload?.logger || console\n \n try {\n logger.info({\n collection: args?.collection?.slug,\n operation: args?.operation,\n docId: args?.doc?.id,\n hookType: 'automation'\n }, 'Collection automation hook triggered')\n \n if (!registry.isInitialized) {\n logger.warn('Workflow executor not yet initialized, skipping execution')\n return undefined\n }\n \n if (!registry.executor) {\n logger.error('Workflow executor is null despite being marked as initialized')\n // Create a failed workflow run to track this issue\n await createFailedWorkflowRun(args, 'Executor not available', logger)\n return undefined\n }\n \n logger.debug('Executing triggered workflows...')\n await registry.executor.executeTriggeredWorkflows(\n args.collection.slug,\n args.operation,\n args.doc,\n args.previousDoc,\n args.req\n )\n \n logger.info({\n collection: args?.collection?.slug,\n operation: args?.operation,\n docId: args?.doc?.id\n }, 'Workflow execution completed successfully')\n \n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error'\n \n logger.error({\n error: errorMessage,\n errorStack: error instanceof Error ? error.stack : undefined,\n collection: args?.collection?.slug,\n operation: args?.operation,\n docId: args?.doc?.id\n }, 'Hook execution failed')\n \n // Create a failed workflow run to track this error\n try {\n await createFailedWorkflowRun(args, errorMessage, logger)\n } catch (createError) {\n logger.error({\n error: createError instanceof Error ? createError.message : 'Unknown error'\n }, 'Failed to create workflow run for hook error')\n }\n \n // Don't throw to prevent breaking the original operation\n }\n \n return undefined\n },\n {\n __isAutomationHook: true,\n __version: '0.0.22'\n }\n )\n \n // Add the hook to the collection config\n collection.hooks.afterChange.push(automationHook)\n logger.info(`Added automation hook to '${triggerSlug}' - hook count: ${collection.hooks.afterChange.length}`)\n }\n }\n\n if (!config.jobs) {\n config.jobs = {tasks: []}\n }\n\n const configLogger = getConfigLogger()\n configLogger.info(`Configuring workflow plugin with ${Object.keys(pluginOptions.collectionTriggers || {}).length} collection triggers`)\n\n // Generate cron tasks for workflows with cron triggers\n generateCronTasks(config)\n\n for (const step of pluginOptions.steps) {\n if (!config.jobs?.tasks?.find(task => task.slug === step.slug)) {\n configLogger.debug(`Registering task: ${step.slug}`)\n config.jobs?.tasks?.push(step)\n } else {\n configLogger.debug(`Task ${step.slug} already registered, skipping`)\n }\n }\n\n // Initialize webhook endpoint\n initWebhookEndpoint(config, pluginOptions.webhookPrefix || 'webhook')\n\n // Set up onInit to register collection hooks and initialize features\n const incomingOnInit = config.onInit\n config.onInit = async (payload) => {\n configLogger.info(`onInit called - collections: ${Object.keys(payload.collections).length}`)\n \n // Execute any existing onInit functions first\n if (incomingOnInit) {\n configLogger.debug('Executing existing onInit function')\n await incomingOnInit(payload)\n }\n\n // Initialize the logger with the payload instance\n const logger = initializeLogger(payload)\n logger.info('Logger initialized with payload instance')\n\n // Log collection trigger configuration\n logger.info(`Plugin configuration: ${Object.keys(pluginOptions.collectionTriggers || {}).length} collection triggers, ${pluginOptions.steps?.length || 0} steps`)\n\n // Create workflow executor instance\n console.log('🚨 CREATING WORKFLOW EXECUTOR INSTANCE')\n const executor = new WorkflowExecutor(payload, logger)\n console.log('🚨 EXECUTOR CREATED:', typeof executor)\n console.log('🚨 EXECUTOR METHODS:', Object.getOwnPropertyNames(Object.getPrototypeOf(executor)))\n \n // Register executor with proper dependency injection\n setWorkflowExecutor(executor, logger)\n\n // Hooks are now registered during config phase - just log status\n logger.info('Hooks were registered during config phase - executor now available')\n \n logger.info('Initializing global hooks...')\n initGlobalHooks(payload, logger, executor)\n \n logger.info('Initializing workflow hooks...')\n initWorkflowHooks(payload, logger)\n \n logger.info('Initializing step tasks...')\n initStepTasks(pluginOptions, payload, logger)\n\n // Register cron jobs for workflows with cron triggers\n logger.info('Registering cron jobs...')\n await registerCronJobs(payload, logger)\n\n logger.info('Plugin initialized successfully - all hooks registered')\n }\n\n return config\n }\n"],"names":["createWorkflowCollection","WorkflowRunsCollection","WorkflowExecutor","generateCronTasks","registerCronJobs","initGlobalHooks","initStepTasks","initWebhookEndpoint","initWorkflowHooks","getConfigLogger","initializeLogger","getLogger","executorRegistry","executor","logger","isInitialized","setWorkflowExecutor","info","getExecutorRegistry","createFailedWorkflowRun","args","errorMessage","req","payload","collection","slug","workflows","find","where","equals","operation","limit","workflow","docs","create","data","id","workflowVersion","status","startedAt","Date","toISOString","completedAt","error","triggeredBy","user","email","context","trigger","type","doc","previousDoc","triggeredAt","steps","inputs","outputs","logs","level","message","timestamp","length","workflowCount","warn","Error","applyCollectionsConfig","pluginOptions","config","collections","push","workflowsPlugin","enabled","collectionTriggers","triggerSlug","triggerConfig","Object","entries","collectionIndex","findIndex","c","hooks","afterChange","automationHook","assign","payloadAutomationHook","registry","console","docId","hookType","undefined","debug","executeTriggeredWorkflows","errorStack","stack","createError","__isAutomationHook","__version","jobs","tasks","configLogger","keys","step","task","webhookPrefix","incomingOnInit","onInit","log","getOwnPropertyNames","getPrototypeOf"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/plugin/index.ts"],"sourcesContent":["import type {Config} from 'payload'\n\nimport type {CollectionTriggerConfigCrud, WorkflowsPluginConfig} from \"./config-types.js\"\n\nimport {createWorkflowCollection} from '../collections/Workflow.js'\nimport {WorkflowRunsCollection} from '../collections/WorkflowRuns.js'\nimport {WorkflowExecutor} from '../core/workflow-executor.js'\nimport {generateCronTasks, registerCronJobs} from './cron-scheduler.js'\nimport {initCollectionHooks} from \"./init-collection-hooks.js\"\nimport {initGlobalHooks} from \"./init-global-hooks.js\"\nimport {initStepTasks} from \"./init-step-tasks.js\"\nimport {initWebhookEndpoint} from \"./init-webhook.js\"\nimport {initWorkflowHooks} from './init-workflow-hooks.js'\nimport {getConfigLogger, initializeLogger} from './logger.js'\n\nexport {getLogger} from './logger.js'\n\n// Improved executor registry with proper error handling and logging\ninterface ExecutorRegistry {\n executor: null | WorkflowExecutor\n isInitialized: boolean\n logger: any | null\n}\n\nconst executorRegistry: ExecutorRegistry = {\n executor: null,\n isInitialized: false,\n logger: null\n}\n\nconst setWorkflowExecutor = (executor: WorkflowExecutor, logger: any) => {\n executorRegistry.executor = executor\n executorRegistry.logger = logger\n executorRegistry.isInitialized = true\n\n logger.info('Workflow executor initialized and registered successfully')\n}\n\nconst getExecutorRegistry = (): ExecutorRegistry => {\n return executorRegistry\n}\n\n// Helper function to create failed workflow runs for tracking errors\nconst createFailedWorkflowRun = async (args: any, errorMessage: string, logger: any) => {\n try {\n // Only create failed workflow runs if we have enough context\n if (!args?.req?.payload || !args?.collection?.slug) {\n return\n }\n\n // Find workflows that should have been triggered\n const workflows = await args.req.payload.find({\n collection: 'workflows',\n limit: 10,\n req: args.req,\n where: {\n 'triggers.collectionSlug': {\n equals: args.collection.slug\n },\n 'triggers.operation': {\n equals: args.operation\n },\n 'triggers.type': {\n equals: 'collection-trigger'\n }\n }\n })\n\n // Create failed workflow runs for each matching workflow\n for (const workflow of workflows.docs) {\n await args.req.payload.create({\n collection: 'workflow-runs',\n data: {\n completedAt: new Date().toISOString(),\n context: {\n steps: {},\n trigger: {\n type: 'collection',\n collection: args.collection.slug,\n doc: args.doc,\n operation: args.operation,\n previousDoc: args.previousDoc,\n triggeredAt: new Date().toISOString()\n }\n },\n error: `Hook execution failed: ${errorMessage}`,\n inputs: {},\n logs: [{\n level: 'error',\n message: `Hook execution failed: ${errorMessage}`,\n timestamp: new Date().toISOString()\n }],\n outputs: {},\n startedAt: new Date().toISOString(),\n status: 'failed',\n steps: [],\n triggeredBy: args?.req?.user?.email || 'system',\n workflow: workflow.id,\n workflowVersion: 1\n },\n req: args.req\n })\n }\n\n if (workflows.docs.length > 0) {\n logger.info({\n errorMessage,\n workflowCount: workflows.docs.length\n }, 'Created failed workflow runs for hook execution error')\n }\n\n } catch (error) {\n // Don't let workflow run creation failures break the original operation\n logger.warn({\n error: error instanceof Error ? error.message : 'Unknown error'\n }, 'Failed to create failed workflow run record')\n }\n}\n\nconst applyCollectionsConfig = <T extends string>(pluginOptions: WorkflowsPluginConfig<T>, config: Config) => {\n // Add workflow collections\n if (!config.collections) {\n config.collections = []\n }\n\n config.collections.push(\n createWorkflowCollection(pluginOptions),\n WorkflowRunsCollection\n )\n}\n\n// Removed config-phase hook registration - user collections don't exist during config phase\n\n\nexport const workflowsPlugin =\n <TSlug extends string>(pluginOptions: WorkflowsPluginConfig<TSlug>) =>\n (config: Config): Config => {\n // If the plugin is disabled, return config unchanged\n if (pluginOptions.enabled === false) {\n return config\n }\n\n applyCollectionsConfig<TSlug>(pluginOptions, config)\n\n // CRITICAL: Modify existing collection configs BEFORE PayloadCMS processes them\n // This is the ONLY time we can add hooks that will actually work\n const logger = getConfigLogger()\n logger.info('Attempting to modify collection configs before PayloadCMS initialization...')\n\n if (config.collections && pluginOptions.collectionTriggers) {\n for (const [triggerSlug, triggerConfig] of Object.entries(pluginOptions.collectionTriggers)) {\n if (!triggerConfig) {continue}\n\n // Find the collection config that matches\n const collectionIndex = config.collections.findIndex(c => c.slug === triggerSlug)\n if (collectionIndex === -1) {\n logger.warn(`Collection '${triggerSlug}' not found in config.collections`)\n continue\n }\n\n const collection = config.collections[collectionIndex]\n logger.info(`Found collection '${triggerSlug}' - modifying its hooks...`)\n\n // Initialize hooks if needed\n if (!collection.hooks) {\n collection.hooks = {}\n }\n if (!collection.hooks.afterChange) {\n collection.hooks.afterChange = []\n }\n\n // Create a reliable hook function with proper dependency injection\n const automationHook = Object.assign(\n async function payloadAutomationHook(args: any) {\n const registry = getExecutorRegistry()\n\n // Use proper logger if available, fallback to args.req.payload.logger\n const logger = registry.logger || args?.req?.payload?.logger || console\n\n try {\n logger.info({\n collection: args?.collection?.slug,\n docId: args?.doc?.id,\n hookType: 'automation',\n operation: args?.operation\n }, 'Collection automation hook triggered')\n\n if (!registry.isInitialized) {\n logger.warn('Workflow executor not yet initialized, skipping execution')\n return undefined\n }\n\n if (!registry.executor) {\n logger.error('Workflow executor is null despite being marked as initialized')\n // Create a failed workflow run to track this issue\n await createFailedWorkflowRun(args, 'Executor not available', logger)\n return undefined\n }\n\n logger.debug('Executing triggered workflows...')\n await registry.executor.executeTriggeredWorkflows(\n args.collection.slug,\n args.operation,\n args.doc,\n args.previousDoc,\n args.req\n )\n\n logger.info({\n collection: args?.collection?.slug,\n docId: args?.doc?.id,\n operation: args?.operation\n }, 'Workflow execution completed successfully')\n\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error'\n\n logger.error({\n collection: args?.collection?.slug,\n docId: args?.doc?.id,\n error: errorMessage,\n errorStack: error instanceof Error ? error.stack : undefined,\n operation: args?.operation\n }, 'Hook execution failed')\n\n // Create a failed workflow run to track this error\n try {\n await createFailedWorkflowRun(args, errorMessage, logger)\n } catch (createError) {\n logger.error({\n error: createError instanceof Error ? createError.message : 'Unknown error'\n }, 'Failed to create workflow run for hook error')\n }\n\n // Don't throw to prevent breaking the original operation\n }\n\n return undefined\n },\n {\n __isAutomationHook: true,\n __version: '0.0.22'\n }\n )\n\n // Add the hook to the collection config\n collection.hooks.afterChange.push(automationHook)\n logger.info(`Added automation hook to '${triggerSlug}' - hook count: ${collection.hooks.afterChange.length}`)\n }\n }\n\n if (!config.jobs) {\n config.jobs = {tasks: []}\n }\n\n const configLogger = getConfigLogger()\n configLogger.info(`Configuring workflow plugin with ${Object.keys(pluginOptions.collectionTriggers || {}).length} collection triggers`)\n\n // Generate cron tasks for workflows with cron triggers\n generateCronTasks(config)\n\n for (const step of pluginOptions.steps) {\n if (!config.jobs?.tasks?.find(task => task.slug === step.slug)) {\n configLogger.debug(`Registering task: ${step.slug}`)\n config.jobs?.tasks?.push(step)\n } else {\n configLogger.debug(`Task ${step.slug} already registered, skipping`)\n }\n }\n\n // Initialize webhook endpoint\n initWebhookEndpoint(config, pluginOptions.webhookPrefix || 'webhook')\n\n // Set up onInit to register collection hooks and initialize features\n const incomingOnInit = config.onInit\n config.onInit = async (payload) => {\n configLogger.info(`onInit called - collections: ${Object.keys(payload.collections).length}`)\n\n // Execute any existing onInit functions first\n if (incomingOnInit) {\n configLogger.debug('Executing existing onInit function')\n await incomingOnInit(payload)\n }\n\n // Initialize the logger with the payload instance\n const logger = initializeLogger(payload)\n logger.info('Logger initialized with payload instance')\n\n // Log collection trigger configuration\n logger.info(`Plugin configuration: ${Object.keys(pluginOptions.collectionTriggers || {}).length} collection triggers, ${pluginOptions.steps?.length || 0} steps`)\n\n // Create workflow executor instance\n console.log('🚨 CREATING WORKFLOW EXECUTOR INSTANCE')\n const executor = new WorkflowExecutor(payload, logger)\n console.log('🚨 EXECUTOR CREATED:', typeof executor)\n console.log('🚨 EXECUTOR METHODS:', Object.getOwnPropertyNames(Object.getPrototypeOf(executor)))\n\n // Register executor with proper dependency injection\n setWorkflowExecutor(executor, logger)\n\n // Hooks are now registered during config phase - just log status\n logger.info('Hooks were registered during config phase - executor now available')\n\n logger.info('Initializing global hooks...')\n initGlobalHooks(payload, logger, executor)\n\n logger.info('Initializing workflow hooks...')\n initWorkflowHooks(payload, logger)\n\n logger.info('Initializing step tasks...')\n initStepTasks(pluginOptions, payload, logger)\n\n // Register cron jobs for workflows with cron triggers\n logger.info('Registering cron jobs...')\n await registerCronJobs(payload, logger)\n\n logger.info('Plugin initialized successfully - all hooks registered')\n }\n\n return config\n }\n"],"names":["createWorkflowCollection","WorkflowRunsCollection","WorkflowExecutor","generateCronTasks","registerCronJobs","initGlobalHooks","initStepTasks","initWebhookEndpoint","initWorkflowHooks","getConfigLogger","initializeLogger","getLogger","executorRegistry","executor","isInitialized","logger","setWorkflowExecutor","info","getExecutorRegistry","createFailedWorkflowRun","args","errorMessage","req","payload","collection","slug","workflows","find","limit","where","equals","operation","workflow","docs","create","data","completedAt","Date","toISOString","context","steps","trigger","type","doc","previousDoc","triggeredAt","error","inputs","logs","level","message","timestamp","outputs","startedAt","status","triggeredBy","user","email","id","workflowVersion","length","workflowCount","warn","Error","applyCollectionsConfig","pluginOptions","config","collections","push","workflowsPlugin","enabled","collectionTriggers","triggerSlug","triggerConfig","Object","entries","collectionIndex","findIndex","c","hooks","afterChange","automationHook","assign","payloadAutomationHook","registry","console","docId","hookType","undefined","debug","executeTriggeredWorkflows","errorStack","stack","createError","__isAutomationHook","__version","jobs","tasks","configLogger","keys","step","task","webhookPrefix","incomingOnInit","onInit","log","getOwnPropertyNames","getPrototypeOf"],"mappings":"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"}
@@ -56,7 +56,7 @@ export function initWebhookEndpoint(config, webhookPrefix = 'webhook') {
56
56
  };
57
57
  // Find the matching trigger and check its condition if present
58
58
  const triggers = workflow.triggers;
59
- const matchingTrigger = triggers?.find((trigger)=>trigger.type === 'webhook-trigger' && trigger.webhookPath === path);
59
+ const matchingTrigger = triggers?.find((trigger)=>trigger.type === 'webhook-trigger' && trigger.parameters?.webhookPath === path);
60
60
  // Check trigger condition if present
61
61
  if (matchingTrigger?.condition) {
62
62
  logger.debug({
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/plugin/init-webhook.ts"],"sourcesContent":["import type {Config, PayloadRequest} from 'payload'\n\nimport {type PayloadWorkflow, WorkflowExecutor} from '../core/workflow-executor.js'\nimport {getConfigLogger, initializeLogger} from './logger.js'\n\nexport function initWebhookEndpoint(config: Config, webhookPrefix = 'webhook'): void {\n const logger = getConfigLogger()\n // Ensure the prefix starts with a slash\n const normalizedPrefix = webhookPrefix.startsWith('/') ? webhookPrefix : `/${webhookPrefix}`\n logger.debug(`Adding webhook endpoint to config with prefix: ${normalizedPrefix}`)\n logger.debug('Current config.endpoints length:', config.endpoints?.length || 0)\n\n // Define webhook endpoint\n const webhookEndpoint = {\n handler: async (req: PayloadRequest) => {\n const {path} = req.routeParams as { path: string }\n const webhookData = req.body || {}\n\n logger.debug('Webhook endpoint handler called, path: ' + path)\n\n try {\n // Find workflows with matching webhook triggers\n const workflows = await req.payload.find({\n collection: 'workflows',\n depth: 2,\n limit: 100,\n req,\n where: {\n 'triggers.type': {\n equals: 'webhook-trigger'\n },\n 'triggers.webhookPath': {\n equals: path\n }\n }\n })\n\n if (workflows.docs.length === 0) {\n return new Response(\n JSON.stringify({error: 'No workflows found for this webhook path'}),\n {\n headers: {'Content-Type': 'application/json'},\n status: 404\n }\n )\n }\n\n // Create a workflow executor for this request\n const logger = initializeLogger(req.payload)\n const executor = new WorkflowExecutor(req.payload, logger)\n\n const executionPromises = workflows.docs.map(async (workflow) => {\n try {\n // Create execution context for the webhook trigger\n const context = {\n steps: {},\n trigger: {\n type: 'webhook',\n data: webhookData,\n headers: Object.fromEntries(req.headers?.entries() || []),\n path,\n req\n }\n }\n\n // Find the matching trigger and check its condition if present\n const triggers = workflow.triggers as Array<{\n condition?: string\n type: string\n webhookPath?: string\n }>\n\n const matchingTrigger = triggers?.find(trigger =>\n trigger.type === 'webhook-trigger' &&\n trigger.webhookPath === path\n )\n\n // Check trigger condition if present\n if (matchingTrigger?.condition) {\n logger.debug({\n condition: matchingTrigger.condition,\n path,\n webhookData: JSON.stringify(webhookData).substring(0, 200),\n headers: Object.keys(context.trigger.headers || {}),\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Evaluating webhook trigger condition')\n\n const conditionMet = executor.evaluateCondition(matchingTrigger.condition, context)\n\n if (!conditionMet) {\n logger.info({\n condition: matchingTrigger.condition,\n path,\n webhookDataSnapshot: JSON.stringify(webhookData).substring(0, 200),\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Webhook trigger condition not met, skipping workflow')\n\n return { reason: 'Condition not met', status: 'skipped', workflowId: workflow.id }\n }\n\n logger.info({\n condition: matchingTrigger.condition,\n path,\n webhookDataSnapshot: JSON.stringify(webhookData).substring(0, 200),\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Webhook trigger condition met')\n }\n\n // Execute the workflow\n await executor.execute(workflow as PayloadWorkflow, context, req)\n\n return { status: 'triggered', workflowId: workflow.id }\n } catch (error) {\n return {\n error: error instanceof Error ? error.message : 'Unknown error',\n status: 'failed',\n workflowId: workflow.id\n }\n }\n })\n\n const results = await Promise.allSettled(executionPromises)\n const resultsData = results.map((result, index) => {\n const baseResult = { workflowId: workflows.docs[index].id }\n if (result.status === 'fulfilled') {\n return { ...baseResult, ...result.value }\n } else {\n return { ...baseResult, error: result.reason, status: 'failed' }\n }\n })\n\n return new Response(\n JSON.stringify({\n message: `Triggered ${workflows.docs.length} workflow(s)`,\n results: resultsData\n }),\n {\n headers: { 'Content-Type': 'application/json' },\n status: 200\n }\n )\n\n } catch (error) {\n return new Response(\n JSON.stringify({\n details: error instanceof Error ? error.message : 'Unknown error',\n error: 'Failed to process webhook'\n }),\n {\n headers: { 'Content-Type': 'application/json' },\n status: 500\n }\n )\n }\n },\n method: 'post' as const,\n path: `${normalizedPrefix}/:path`\n }\n\n // Check if the webhook endpoint already exists to avoid duplicates\n const existingEndpoint = config.endpoints?.find(endpoint =>\n endpoint.path === webhookEndpoint.path && endpoint.method === webhookEndpoint.method\n )\n\n if (!existingEndpoint) {\n // Combine existing endpoints with the webhook endpoint\n config.endpoints = [...(config.endpoints || []), webhookEndpoint]\n logger.debug(`Webhook endpoint added at path: ${webhookEndpoint.path}`)\n logger.debug('New config.endpoints length:', config.endpoints.length)\n } else {\n logger.debug(`Webhook endpoint already exists at path: ${webhookEndpoint.path}`)\n }\n}\n"],"names":["WorkflowExecutor","getConfigLogger","initializeLogger","initWebhookEndpoint","config","webhookPrefix","logger","normalizedPrefix","startsWith","debug","endpoints","length","webhookEndpoint","handler","req","path","routeParams","webhookData","body","workflows","payload","find","collection","depth","limit","where","equals","docs","Response","JSON","stringify","error","headers","status","executor","executionPromises","map","workflow","context","steps","trigger","type","data","Object","fromEntries","entries","triggers","matchingTrigger","webhookPath","condition","substring","keys","workflowId","id","workflowName","name","conditionMet","evaluateCondition","info","webhookDataSnapshot","reason","execute","Error","message","results","Promise","allSettled","resultsData","result","index","baseResult","value","details","method","existingEndpoint","endpoint"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/plugin/init-webhook.ts"],"sourcesContent":["import type {Config, PayloadRequest} from 'payload'\n\nimport {type PayloadWorkflow, WorkflowExecutor} from '../core/workflow-executor.js'\nimport {getConfigLogger, initializeLogger} from './logger.js'\n\nexport function initWebhookEndpoint(config: Config, webhookPrefix = 'webhook'): void {\n const logger = getConfigLogger()\n // Ensure the prefix starts with a slash\n const normalizedPrefix = webhookPrefix.startsWith('/') ? webhookPrefix : `/${webhookPrefix}`\n logger.debug(`Adding webhook endpoint to config with prefix: ${normalizedPrefix}`)\n logger.debug('Current config.endpoints length:', config.endpoints?.length || 0)\n\n // Define webhook endpoint\n const webhookEndpoint = {\n handler: async (req: PayloadRequest) => {\n const {path} = req.routeParams as { path: string }\n const webhookData = req.body || {}\n\n logger.debug('Webhook endpoint handler called, path: ' + path)\n\n try {\n // Find workflows with matching webhook triggers\n const workflows = await req.payload.find({\n collection: 'workflows',\n depth: 2,\n limit: 100,\n req,\n where: {\n 'triggers.type': {\n equals: 'webhook-trigger'\n },\n 'triggers.webhookPath': {\n equals: path\n }\n }\n })\n\n if (workflows.docs.length === 0) {\n return new Response(\n JSON.stringify({error: 'No workflows found for this webhook path'}),\n {\n headers: {'Content-Type': 'application/json'},\n status: 404\n }\n )\n }\n\n // Create a workflow executor for this request\n const logger = initializeLogger(req.payload)\n const executor = new WorkflowExecutor(req.payload, logger)\n\n const executionPromises = workflows.docs.map(async (workflow) => {\n try {\n // Create execution context for the webhook trigger\n const context = {\n steps: {},\n trigger: {\n type: 'webhook',\n data: webhookData,\n headers: Object.fromEntries(req.headers?.entries() || []),\n path,\n req\n }\n }\n\n // Find the matching trigger and check its condition if present\n const triggers = workflow.triggers as Array<{\n condition?: string\n type: string\n parameters?: {\n webhookPath?: string\n [key: string]: any\n }\n }>\n\n const matchingTrigger = triggers?.find(trigger =>\n trigger.type === 'webhook-trigger' &&\n trigger.parameters?.webhookPath === path\n )\n\n // Check trigger condition if present\n if (matchingTrigger?.condition) {\n logger.debug({\n condition: matchingTrigger.condition,\n path,\n webhookData: JSON.stringify(webhookData).substring(0, 200),\n headers: Object.keys(context.trigger.headers || {}),\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Evaluating webhook trigger condition')\n\n const conditionMet = executor.evaluateCondition(matchingTrigger.condition, context)\n\n if (!conditionMet) {\n logger.info({\n condition: matchingTrigger.condition,\n path,\n webhookDataSnapshot: JSON.stringify(webhookData).substring(0, 200),\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Webhook trigger condition not met, skipping workflow')\n\n return { reason: 'Condition not met', status: 'skipped', workflowId: workflow.id }\n }\n\n logger.info({\n condition: matchingTrigger.condition,\n path,\n webhookDataSnapshot: JSON.stringify(webhookData).substring(0, 200),\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Webhook trigger condition met')\n }\n\n // Execute the workflow\n await executor.execute(workflow as PayloadWorkflow, context, req)\n\n return { status: 'triggered', workflowId: workflow.id }\n } catch (error) {\n return {\n error: error instanceof Error ? error.message : 'Unknown error',\n status: 'failed',\n workflowId: workflow.id\n }\n }\n })\n\n const results = await Promise.allSettled(executionPromises)\n const resultsData = results.map((result, index) => {\n const baseResult = { workflowId: workflows.docs[index].id }\n if (result.status === 'fulfilled') {\n return { ...baseResult, ...result.value }\n } else {\n return { ...baseResult, error: result.reason, status: 'failed' }\n }\n })\n\n return new Response(\n JSON.stringify({\n message: `Triggered ${workflows.docs.length} workflow(s)`,\n results: resultsData\n }),\n {\n headers: { 'Content-Type': 'application/json' },\n status: 200\n }\n )\n\n } catch (error) {\n return new Response(\n JSON.stringify({\n details: error instanceof Error ? error.message : 'Unknown error',\n error: 'Failed to process webhook'\n }),\n {\n headers: { 'Content-Type': 'application/json' },\n status: 500\n }\n )\n }\n },\n method: 'post' as const,\n path: `${normalizedPrefix}/:path`\n }\n\n // Check if the webhook endpoint already exists to avoid duplicates\n const existingEndpoint = config.endpoints?.find(endpoint =>\n endpoint.path === webhookEndpoint.path && endpoint.method === webhookEndpoint.method\n )\n\n if (!existingEndpoint) {\n // Combine existing endpoints with the webhook endpoint\n config.endpoints = [...(config.endpoints || []), webhookEndpoint]\n logger.debug(`Webhook endpoint added at path: ${webhookEndpoint.path}`)\n logger.debug('New config.endpoints length:', config.endpoints.length)\n } else {\n logger.debug(`Webhook endpoint already exists at path: ${webhookEndpoint.path}`)\n }\n}\n"],"names":["WorkflowExecutor","getConfigLogger","initializeLogger","initWebhookEndpoint","config","webhookPrefix","logger","normalizedPrefix","startsWith","debug","endpoints","length","webhookEndpoint","handler","req","path","routeParams","webhookData","body","workflows","payload","find","collection","depth","limit","where","equals","docs","Response","JSON","stringify","error","headers","status","executor","executionPromises","map","workflow","context","steps","trigger","type","data","Object","fromEntries","entries","triggers","matchingTrigger","parameters","webhookPath","condition","substring","keys","workflowId","id","workflowName","name","conditionMet","evaluateCondition","info","webhookDataSnapshot","reason","execute","Error","message","results","Promise","allSettled","resultsData","result","index","baseResult","value","details","method","existingEndpoint","endpoint"],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import type { Field } from 'payload';
2
+ import type { CustomTriggerConfig } from '../plugin/config-types.js';
3
+ /**
4
+ * Helper function to create a virtual trigger parameter field
5
+ * Handles the boilerplate for storing/reading from the parameters JSON field
6
+ */
7
+ export declare function createTriggerParameter(name: string, fieldConfig: any, // Use any to allow flexible field configurations
8
+ triggerSlug: string): Field;
9
+ /**
10
+ * Helper to create multiple trigger parameter fields at once
11
+ */
12
+ export declare function createTriggerParameters(triggerSlug: string, parameters: Record<string, any>): Field[];
13
+ /**
14
+ * Main trigger builder function that creates a fluent API for defining triggers
15
+ */
16
+ export declare function createTrigger<TSlug extends string>(slug: TSlug): {
17
+ /**
18
+ * Define parameters for this trigger using a clean object syntax
19
+ * @param paramConfig - Object where keys are parameter names and values are Field configs
20
+ * @returns Complete CustomTriggerConfig ready for use
21
+ */
22
+ parameters(paramConfig: Record<string, any>): CustomTriggerConfig;
23
+ };
24
+ /**
25
+ * Advanced trigger builder with chainable methods for more complex scenarios
26
+ */
27
+ export declare function createAdvancedTrigger<TSlug extends string>(slug: TSlug): {
28
+ slug: TSlug;
29
+ _parameters: Record<string, any>;
30
+ /**
31
+ * Set all parameters at once
32
+ */
33
+ parameters(paramConfig: Record<string, any>): /*elided*/ any;
34
+ /**
35
+ * Add a single parameter
36
+ */
37
+ parameter(name: string, fieldConfig: any): /*elided*/ any;
38
+ /**
39
+ * Extend with existing parameter sets (useful for common patterns)
40
+ */
41
+ extend(baseParameters: Record<string, any>): /*elided*/ any;
42
+ /**
43
+ * Build the final trigger configuration
44
+ */
45
+ build(): CustomTriggerConfig;
46
+ };