@xtr-dev/payload-automation 0.0.13 → 0.0.15

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/core/trigger-custom-workflow.ts"],"sourcesContent":["import type { Payload, PayloadRequest } from 'payload'\n\nimport { initializeLogger } from '../plugin/logger.js'\nimport { type Workflow, WorkflowExecutor } from './workflow-executor.js'\n\nexport interface CustomTriggerOptions {\n /**\n * Data to pass to the workflow execution context\n */\n data?: Record<string, unknown>\n\n /**\n * Optional PayloadRequest to use for the workflow execution\n * If not provided, a minimal request will be created\n */\n req?: PayloadRequest\n\n /**\n * The slug of the custom trigger to execute\n */\n slug: string\n\n /**\n * Optional user information for tracking who triggered the workflow\n */\n user?: {\n email?: string\n id?: string\n }\n}\n\nexport interface TriggerResult {\n error?: string\n runId: number | string\n status: 'failed' | 'triggered'\n workflowId: string\n workflowName: string\n}\n\n/**\n * Programmatically trigger workflows that have a matching custom trigger\n *\n * @example\n * ```typescript\n * // In your onInit or elsewhere in your code\n * await triggerCustomWorkflow(payload, {\n * slug: 'data-import',\n * data: {\n * source: 'external-api',\n * recordCount: 100,\n * importedAt: new Date().toISOString()\n * }\n * })\n * ```\n */\nexport async function triggerCustomWorkflow(\n payload: Payload,\n options: CustomTriggerOptions\n): Promise<TriggerResult[]> {\n const { slug, data = {}, req, user } = options\n\n const logger = initializeLogger(payload)\n\n logger.info({\n hasData: Object.keys(data).length > 0,\n hasUser: !!user,\n triggerSlug: slug\n }, 'Triggering custom workflow')\n\n try {\n // Find workflows with matching custom trigger\n const workflows = await payload.find({\n collection: 'workflows',\n depth: 2,\n limit: 100,\n where: {\n 'triggers.type': {\n equals: slug\n }\n }\n })\n\n if (workflows.docs.length === 0) {\n logger.warn({\n triggerSlug: slug\n }, 'No workflows found for custom trigger')\n return []\n }\n\n logger.info({\n triggerSlug: slug,\n workflowCount: workflows.docs.length\n }, 'Found workflows for custom trigger')\n\n // Create a minimal request if not provided\n const workflowReq = req || {\n context: {},\n headers: new Headers(),\n payload,\n user: user ? {\n id: user.id,\n collection: 'users',\n email: user.email\n } : undefined\n } as PayloadRequest\n\n // Create workflow executor\n const executor = new WorkflowExecutor(payload, logger)\n\n // Execute all matching workflows\n const results: TriggerResult[] = []\n\n for (const workflow of workflows.docs) {\n try {\n // Check if this workflow actually has the custom trigger\n const triggers = workflow.triggers as Array<{type: string}>\n const hasMatchingTrigger = triggers?.some(trigger => trigger.type === slug)\n\n if (!hasMatchingTrigger) {\n continue\n }\n\n logger.info({\n triggerSlug: slug,\n workflowId: workflow.id.toString(),\n workflowName: workflow.name\n }, 'Executing workflow with custom trigger')\n\n // Create execution context\n const context = {\n steps: {},\n trigger: {\n type: slug,\n data,\n req: workflowReq,\n triggeredAt: new Date().toISOString(),\n user: (user || workflowReq.user) ? {\n id: (user || workflowReq.user)?.id?.toString(),\n email: (user || workflowReq.user)?.email\n } : undefined\n }\n }\n\n // Execute the workflow\n await executor.execute(workflow as Workflow, context, workflowReq)\n\n // Get the latest run for this workflow to get the run ID\n const runs = await payload.find({\n collection: 'workflow-runs',\n limit: 1,\n sort: '-createdAt',\n where: {\n workflow: {\n equals: workflow.id\n }\n }\n })\n\n results.push({\n runId: runs.docs[0]?.id?.toString() || 'unknown',\n status: 'triggered',\n workflowId: workflow.id.toString(),\n workflowName: workflow.name as string\n })\n\n logger.info({\n triggerSlug: slug,\n workflowId: workflow.id.toString(),\n workflowName: workflow.name\n }, 'Workflow executed successfully')\n\n } catch (error) {\n logger.error({\n error: error instanceof Error ? error.message : 'Unknown error',\n triggerSlug: slug,\n workflowId: workflow.id.toString(),\n workflowName: workflow.name\n }, 'Failed to execute workflow')\n\n results.push({\n error: error instanceof Error ? error.message : 'Unknown error',\n runId: 'failed',\n status: 'failed',\n workflowId: workflow.id.toString(),\n workflowName: workflow.name as string\n })\n }\n }\n\n return results\n\n } catch (error) {\n logger.error({\n error: error instanceof Error ? error.message : 'Unknown error',\n triggerSlug: slug\n }, 'Failed to trigger custom workflows')\n\n throw new Error(\n `Failed to trigger custom workflows: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`\n )\n }\n}\n\n/**\n * Helper function to trigger a single workflow by ID with custom trigger data\n * This is useful when you know exactly which workflow you want to trigger\n */\nexport async function triggerWorkflowById(\n payload: Payload,\n workflowId: string,\n triggerSlug: string,\n data?: Record<string, unknown>,\n req?: PayloadRequest\n): Promise<TriggerResult> {\n const logger = initializeLogger(payload)\n\n try {\n const workflow = await payload.findByID({\n id: workflowId,\n collection: 'workflows',\n depth: 2\n })\n\n if (!workflow) {\n throw new Error(`Workflow ${workflowId} not found`)\n }\n\n // Verify the workflow has the specified custom trigger\n const triggers = workflow.triggers as Array<{type: string}>\n const hasMatchingTrigger = triggers?.some(trigger => trigger.type === triggerSlug)\n\n if (!hasMatchingTrigger) {\n throw new Error(`Workflow ${workflowId} does not have trigger ${triggerSlug}`)\n }\n\n // Create a minimal request if not provided\n const workflowReq = req || {\n context: {},\n headers: new Headers(),\n payload\n } as PayloadRequest\n\n // Create execution context\n const context = {\n steps: {},\n trigger: {\n type: triggerSlug,\n data: data || {},\n req: workflowReq,\n triggeredAt: new Date().toISOString()\n }\n }\n\n // Create executor and execute\n const executor = new WorkflowExecutor(payload, logger)\n await executor.execute(workflow as Workflow, context, workflowReq)\n\n // Get the latest run to get the run ID\n const runs = await payload.find({\n collection: 'workflow-runs',\n limit: 1,\n sort: '-createdAt',\n where: {\n workflow: {\n equals: workflow.id\n }\n }\n })\n\n return {\n runId: runs.docs[0]?.id?.toString() || 'unknown',\n status: 'triggered',\n workflowId: workflow.id.toString(),\n workflowName: workflow.name as string\n }\n\n } catch (error) {\n logger.error({\n error: error instanceof Error ? error.message : 'Unknown error',\n triggerSlug,\n workflowId\n }, 'Failed to trigger workflow by ID')\n\n throw error\n }\n}\n"],"names":["initializeLogger","WorkflowExecutor","triggerCustomWorkflow","payload","options","slug","data","req","user","logger","info","hasData","Object","keys","length","hasUser","triggerSlug","workflows","find","collection","depth","limit","where","equals","docs","warn","workflowCount","workflowReq","context","headers","Headers","id","email","undefined","executor","results","workflow","triggers","hasMatchingTrigger","some","trigger","type","workflowId","toString","workflowName","name","steps","triggeredAt","Date","toISOString","execute","runs","sort","push","runId","status","error","Error","message","triggerWorkflowById","findByID"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/core/trigger-custom-workflow.ts"],"sourcesContent":["import type { Payload, PayloadRequest } from 'payload'\n\nimport { initializeLogger } from '../plugin/logger.js'\nimport { type PayloadWorkflow, WorkflowExecutor } from './workflow-executor.js'\n\nexport interface CustomTriggerOptions {\n /**\n * Data to pass to the workflow execution context\n */\n data?: Record<string, unknown>\n\n /**\n * Optional PayloadRequest to use for the workflow execution\n * If not provided, a minimal request will be created\n */\n req?: PayloadRequest\n\n /**\n * The slug of the custom trigger to execute\n */\n slug: string\n\n /**\n * Optional user information for tracking who triggered the workflow\n */\n user?: {\n email?: string\n id?: string\n }\n}\n\nexport interface TriggerResult {\n error?: string\n runId: number | string\n status: 'failed' | 'triggered'\n workflowId: string\n workflowName: string\n}\n\n/**\n * Programmatically trigger workflows that have a matching custom trigger\n *\n * @example\n * ```typescript\n * // In your onInit or elsewhere in your code\n * await triggerCustomWorkflow(payload, {\n * slug: 'data-import',\n * data: {\n * source: 'external-api',\n * recordCount: 100,\n * importedAt: new Date().toISOString()\n * }\n * })\n * ```\n */\nexport async function triggerCustomWorkflow(\n payload: Payload,\n options: CustomTriggerOptions\n): Promise<TriggerResult[]> {\n const { slug, data = {}, req, user } = options\n\n const logger = initializeLogger(payload)\n\n logger.info({\n hasData: Object.keys(data).length > 0,\n hasUser: !!user,\n triggerSlug: slug\n }, 'Triggering custom workflow')\n\n try {\n // Find workflows with matching custom trigger\n const workflows = await payload.find({\n collection: 'workflows',\n depth: 2,\n limit: 100,\n where: {\n 'triggers.type': {\n equals: slug\n }\n }\n })\n\n if (workflows.docs.length === 0) {\n logger.warn({\n triggerSlug: slug\n }, 'No workflows found for custom trigger')\n return []\n }\n\n logger.info({\n triggerSlug: slug,\n workflowCount: workflows.docs.length\n }, 'Found workflows for custom trigger')\n\n // Create a minimal request if not provided\n const workflowReq = req || {\n context: {},\n headers: new Headers(),\n payload,\n user: user ? {\n id: user.id,\n collection: 'users',\n email: user.email\n } : undefined\n } as PayloadRequest\n\n // Create workflow executor\n const executor = new WorkflowExecutor(payload, logger)\n\n // Execute all matching workflows\n const results: TriggerResult[] = []\n\n for (const workflow of workflows.docs) {\n try {\n // Check if this workflow actually has the custom trigger\n const triggers = workflow.triggers as Array<{type: string}>\n const hasMatchingTrigger = triggers?.some(trigger => trigger.type === slug)\n\n if (!hasMatchingTrigger) {\n continue\n }\n\n logger.info({\n triggerSlug: slug,\n workflowId: workflow.id.toString(),\n workflowName: workflow.name\n }, 'Executing workflow with custom trigger')\n\n // Create execution context\n const context = {\n steps: {},\n trigger: {\n type: slug,\n data,\n req: workflowReq,\n triggeredAt: new Date().toISOString(),\n user: (user || workflowReq.user) ? {\n id: (user || workflowReq.user)?.id?.toString(),\n email: (user || workflowReq.user)?.email\n } : undefined\n }\n }\n\n // Execute the workflow\n await executor.execute(workflow as PayloadWorkflow, context, workflowReq)\n\n // Get the latest run for this workflow to get the run ID\n const runs = await payload.find({\n collection: 'workflow-runs',\n limit: 1,\n sort: '-createdAt',\n where: {\n workflow: {\n equals: workflow.id\n }\n }\n })\n\n results.push({\n runId: runs.docs[0]?.id?.toString() || 'unknown',\n status: 'triggered',\n workflowId: workflow.id.toString(),\n workflowName: workflow.name as string\n })\n\n logger.info({\n triggerSlug: slug,\n workflowId: workflow.id.toString(),\n workflowName: workflow.name\n }, 'Workflow executed successfully')\n\n } catch (error) {\n logger.error({\n error: error instanceof Error ? error.message : 'Unknown error',\n triggerSlug: slug,\n workflowId: workflow.id.toString(),\n workflowName: workflow.name\n }, 'Failed to execute workflow')\n\n results.push({\n error: error instanceof Error ? error.message : 'Unknown error',\n runId: 'failed',\n status: 'failed',\n workflowId: workflow.id.toString(),\n workflowName: workflow.name as string\n })\n }\n }\n\n return results\n\n } catch (error) {\n logger.error({\n error: error instanceof Error ? error.message : 'Unknown error',\n triggerSlug: slug\n }, 'Failed to trigger custom workflows')\n\n throw new Error(\n `Failed to trigger custom workflows: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`\n )\n }\n}\n\n/**\n * Helper function to trigger a single workflow by ID with custom trigger data\n * This is useful when you know exactly which workflow you want to trigger\n */\nexport async function triggerWorkflowById(\n payload: Payload,\n workflowId: string,\n triggerSlug: string,\n data?: Record<string, unknown>,\n req?: PayloadRequest\n): Promise<TriggerResult> {\n const logger = initializeLogger(payload)\n\n try {\n const workflow = await payload.findByID({\n id: workflowId,\n collection: 'workflows',\n depth: 2\n })\n\n if (!workflow) {\n throw new Error(`Workflow ${workflowId} not found`)\n }\n\n // Verify the workflow has the specified custom trigger\n const triggers = workflow.triggers as Array<{type: string}>\n const hasMatchingTrigger = triggers?.some(trigger => trigger.type === triggerSlug)\n\n if (!hasMatchingTrigger) {\n throw new Error(`Workflow ${workflowId} does not have trigger ${triggerSlug}`)\n }\n\n // Create a minimal request if not provided\n const workflowReq = req || {\n context: {},\n headers: new Headers(),\n payload\n } as PayloadRequest\n\n // Create execution context\n const context = {\n steps: {},\n trigger: {\n type: triggerSlug,\n data: data || {},\n req: workflowReq,\n triggeredAt: new Date().toISOString()\n }\n }\n\n // Create executor and execute\n const executor = new WorkflowExecutor(payload, logger)\n await executor.execute(workflow as PayloadWorkflow, context, workflowReq)\n\n // Get the latest run to get the run ID\n const runs = await payload.find({\n collection: 'workflow-runs',\n limit: 1,\n sort: '-createdAt',\n where: {\n workflow: {\n equals: workflow.id\n }\n }\n })\n\n return {\n runId: runs.docs[0]?.id?.toString() || 'unknown',\n status: 'triggered',\n workflowId: workflow.id.toString(),\n workflowName: workflow.name as string\n }\n\n } catch (error) {\n logger.error({\n error: error instanceof Error ? error.message : 'Unknown error',\n triggerSlug,\n workflowId\n }, 'Failed to trigger workflow by ID')\n\n throw error\n }\n}\n"],"names":["initializeLogger","WorkflowExecutor","triggerCustomWorkflow","payload","options","slug","data","req","user","logger","info","hasData","Object","keys","length","hasUser","triggerSlug","workflows","find","collection","depth","limit","where","equals","docs","warn","workflowCount","workflowReq","context","headers","Headers","id","email","undefined","executor","results","workflow","triggers","hasMatchingTrigger","some","trigger","type","workflowId","toString","workflowName","name","steps","triggeredAt","Date","toISOString","execute","runs","sort","push","runId","status","error","Error","message","triggerWorkflowById","findByID"],"mappings":"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"}
@@ -1,27 +1,31 @@
1
1
  import type { Payload, PayloadRequest } from 'payload';
2
- export type Workflow = {
3
- _version?: number;
4
- id: string;
2
+ export type PayloadWorkflow = {
3
+ id: number;
5
4
  name: string;
6
- steps: WorkflowStep[];
7
- triggers: WorkflowTrigger[];
5
+ description?: string | null;
6
+ triggers?: Array<{
7
+ type?: string | null;
8
+ collectionSlug?: string | null;
9
+ operation?: string | null;
10
+ condition?: string | null;
11
+ [key: string]: unknown;
12
+ }> | null;
13
+ steps?: Array<{
14
+ step?: string | null;
15
+ name?: string | null;
16
+ input?: unknown;
17
+ dependencies?: string[] | null;
18
+ condition?: string | null;
19
+ [key: string]: unknown;
20
+ }> | null;
21
+ [key: string]: unknown;
8
22
  };
9
- export type WorkflowStep = {
10
- condition?: string;
11
- dependencies?: string[];
12
- input?: null | Record<string, unknown>;
23
+ export type WorkflowStep = NonNullable<PayloadWorkflow['steps']>[0] & {
13
24
  name: string;
14
- step: string;
15
25
  };
16
- export interface WorkflowTrigger {
17
- collection?: string;
18
- condition?: string;
19
- global?: string;
20
- globalOperation?: string;
21
- operation?: string;
26
+ export type WorkflowTrigger = NonNullable<PayloadWorkflow['triggers']>[0] & {
22
27
  type: string;
23
- webhookPath?: string;
24
- }
28
+ };
25
29
  export interface ExecutionContext {
26
30
  steps: Record<string, {
27
31
  error?: string;
@@ -67,18 +71,30 @@ export declare class WorkflowExecutor {
67
71
  * Resolve step input using JSONPath expressions
68
72
  */
69
73
  private resolveStepInput;
74
+ /**
75
+ * Safely serialize an object, handling circular references and non-serializable values
76
+ */
77
+ private safeSerialize;
70
78
  /**
71
79
  * Update workflow run with current context
72
80
  */
73
81
  private updateWorkflowRunContext;
74
82
  /**
75
- * Evaluate a condition using JSONPath
83
+ * Evaluate a condition using JSONPath and comparison operators
76
84
  */
77
85
  evaluateCondition(condition: string, context: ExecutionContext): boolean;
86
+ /**
87
+ * Resolve a JSONPath value from the context
88
+ */
89
+ private resolveJSONPathValue;
90
+ /**
91
+ * Parse a condition value (string literal, number, boolean, or JSONPath)
92
+ */
93
+ private parseConditionValue;
78
94
  /**
79
95
  * Execute a workflow with the given context
80
96
  */
81
- execute(workflow: Workflow, context: ExecutionContext, req: PayloadRequest): Promise<void>;
97
+ execute(workflow: PayloadWorkflow, context: ExecutionContext, req: PayloadRequest): Promise<void>;
82
98
  /**
83
99
  * Find and execute workflows triggered by a collection operation
84
100
  */
@@ -293,17 +293,49 @@ export class WorkflowExecutor {
293
293
  return resolved;
294
294
  }
295
295
  /**
296
+ * Safely serialize an object, handling circular references and non-serializable values
297
+ */ safeSerialize(obj) {
298
+ const seen = new WeakSet();
299
+ const serialize = (value)=>{
300
+ if (value === null || typeof value !== 'object') {
301
+ return value;
302
+ }
303
+ if (seen.has(value)) {
304
+ return '[Circular Reference]';
305
+ }
306
+ seen.add(value);
307
+ if (Array.isArray(value)) {
308
+ return value.map(serialize);
309
+ }
310
+ const result = {};
311
+ for (const [key, val] of Object.entries(value)){
312
+ try {
313
+ // Skip non-serializable properties that are likely internal database objects
314
+ if (key === 'table' || key === 'schema' || key === '_' || key === '__') {
315
+ continue;
316
+ }
317
+ result[key] = serialize(val);
318
+ } catch {
319
+ // Skip properties that can't be accessed or serialized
320
+ result[key] = '[Non-serializable]';
321
+ }
322
+ }
323
+ return result;
324
+ };
325
+ return serialize(obj);
326
+ }
327
+ /**
296
328
  * Update workflow run with current context
297
329
  */ async updateWorkflowRunContext(workflowRunId, context, req) {
298
330
  const serializeContext = ()=>({
299
- steps: context.steps,
331
+ steps: this.safeSerialize(context.steps),
300
332
  trigger: {
301
333
  type: context.trigger.type,
302
334
  collection: context.trigger.collection,
303
- data: context.trigger.data,
304
- doc: context.trigger.doc,
335
+ data: this.safeSerialize(context.trigger.data),
336
+ doc: this.safeSerialize(context.trigger.doc),
305
337
  operation: context.trigger.operation,
306
- previousDoc: context.trigger.previousDoc,
338
+ previousDoc: this.safeSerialize(context.trigger.previousDoc),
307
339
  triggeredAt: context.trigger.triggeredAt,
308
340
  user: context.trigger.req?.user
309
341
  }
@@ -318,7 +350,7 @@ export class WorkflowExecutor {
318
350
  });
319
351
  }
320
352
  /**
321
- * Evaluate a condition using JSONPath
353
+ * Evaluate a condition using JSONPath and comparison operators
322
354
  */ evaluateCondition(condition, context) {
323
355
  this.logger.debug({
324
356
  condition,
@@ -328,30 +360,83 @@ export class WorkflowExecutor {
328
360
  triggerDoc: context.trigger?.doc ? 'present' : 'absent'
329
361
  }, 'Starting condition evaluation');
330
362
  try {
331
- const result = JSONPath({
332
- json: context,
333
- path: condition,
334
- wrap: false
335
- });
336
- this.logger.debug({
337
- condition,
338
- result,
339
- resultType: Array.isArray(result) ? 'array' : typeof result,
340
- resultLength: Array.isArray(result) ? result.length : undefined
341
- }, 'JSONPath evaluation result');
342
- // Handle different result types
343
- let finalResult;
344
- if (Array.isArray(result)) {
345
- finalResult = result.length > 0 && Boolean(result[0]);
363
+ // Check if this is a comparison expression
364
+ const comparisonMatch = condition.match(/^(.+?)\s*(==|!=|>|<|>=|<=)\s*(.+)$/);
365
+ if (comparisonMatch) {
366
+ const [, leftExpr, operator, rightExpr] = comparisonMatch;
367
+ // Evaluate left side (should be JSONPath)
368
+ const leftValue = this.resolveJSONPathValue(leftExpr.trim(), context);
369
+ // Parse right side (could be string, number, boolean, or JSONPath)
370
+ const rightValue = this.parseConditionValue(rightExpr.trim(), context);
371
+ this.logger.debug({
372
+ condition,
373
+ leftExpr: leftExpr.trim(),
374
+ leftValue,
375
+ operator,
376
+ rightExpr: rightExpr.trim(),
377
+ rightValue,
378
+ leftType: typeof leftValue,
379
+ rightType: typeof rightValue
380
+ }, 'Evaluating comparison condition');
381
+ // Perform comparison
382
+ let result;
383
+ switch(operator){
384
+ case '==':
385
+ result = leftValue === rightValue;
386
+ break;
387
+ case '!=':
388
+ result = leftValue !== rightValue;
389
+ break;
390
+ case '>':
391
+ result = Number(leftValue) > Number(rightValue);
392
+ break;
393
+ case '<':
394
+ result = Number(leftValue) < Number(rightValue);
395
+ break;
396
+ case '>=':
397
+ result = Number(leftValue) >= Number(rightValue);
398
+ break;
399
+ case '<=':
400
+ result = Number(leftValue) <= Number(rightValue);
401
+ break;
402
+ default:
403
+ throw new Error(`Unknown comparison operator: ${operator}`);
404
+ }
405
+ this.logger.debug({
406
+ condition,
407
+ result,
408
+ leftValue,
409
+ rightValue,
410
+ operator
411
+ }, 'Comparison condition evaluation completed');
412
+ return result;
346
413
  } else {
347
- finalResult = Boolean(result);
414
+ // Treat as simple JSONPath boolean evaluation
415
+ const result = JSONPath({
416
+ json: context,
417
+ path: condition,
418
+ wrap: false
419
+ });
420
+ this.logger.debug({
421
+ condition,
422
+ result,
423
+ resultType: Array.isArray(result) ? 'array' : typeof result,
424
+ resultLength: Array.isArray(result) ? result.length : undefined
425
+ }, 'JSONPath boolean evaluation result');
426
+ // Handle different result types
427
+ let finalResult;
428
+ if (Array.isArray(result)) {
429
+ finalResult = result.length > 0 && Boolean(result[0]);
430
+ } else {
431
+ finalResult = Boolean(result);
432
+ }
433
+ this.logger.debug({
434
+ condition,
435
+ finalResult,
436
+ originalResult: result
437
+ }, 'Boolean condition evaluation completed');
438
+ return finalResult;
348
439
  }
349
- this.logger.debug({
350
- condition,
351
- finalResult,
352
- originalResult: result
353
- }, 'Condition evaluation completed');
354
- return finalResult;
355
440
  } catch (error) {
356
441
  this.logger.warn({
357
442
  condition,
@@ -363,6 +448,42 @@ export class WorkflowExecutor {
363
448
  }
364
449
  }
365
450
  /**
451
+ * Resolve a JSONPath value from the context
452
+ */ resolveJSONPathValue(expr, context) {
453
+ if (expr.startsWith('$')) {
454
+ const result = JSONPath({
455
+ json: context,
456
+ path: expr,
457
+ wrap: false
458
+ });
459
+ // Return first result if array, otherwise the result itself
460
+ return Array.isArray(result) && result.length > 0 ? result[0] : result;
461
+ }
462
+ return expr;
463
+ }
464
+ /**
465
+ * Parse a condition value (string literal, number, boolean, or JSONPath)
466
+ */ parseConditionValue(expr, context) {
467
+ // Handle string literals
468
+ if (expr.startsWith('"') && expr.endsWith('"') || expr.startsWith("'") && expr.endsWith("'")) {
469
+ return expr.slice(1, -1) // Remove quotes
470
+ ;
471
+ }
472
+ // Handle boolean literals
473
+ if (expr === 'true') return true;
474
+ if (expr === 'false') return false;
475
+ // Handle number literals
476
+ if (/^-?\d+(\.\d+)?$/.test(expr)) {
477
+ return Number(expr);
478
+ }
479
+ // Handle JSONPath expressions
480
+ if (expr.startsWith('$')) {
481
+ return this.resolveJSONPathValue(expr, context);
482
+ }
483
+ // Return as string if nothing else matches
484
+ return expr;
485
+ }
486
+ /**
366
487
  * Execute a workflow with the given context
367
488
  */ async execute(workflow, context, req) {
368
489
  this.logger.info({
@@ -370,34 +491,61 @@ export class WorkflowExecutor {
370
491
  workflowName: workflow.name
371
492
  }, 'Starting workflow execution');
372
493
  const serializeContext = ()=>({
373
- steps: context.steps,
494
+ steps: this.safeSerialize(context.steps),
374
495
  trigger: {
375
496
  type: context.trigger.type,
376
497
  collection: context.trigger.collection,
377
- data: context.trigger.data,
378
- doc: context.trigger.doc,
498
+ data: this.safeSerialize(context.trigger.data),
499
+ doc: this.safeSerialize(context.trigger.doc),
379
500
  operation: context.trigger.operation,
380
- previousDoc: context.trigger.previousDoc,
501
+ previousDoc: this.safeSerialize(context.trigger.previousDoc),
381
502
  triggeredAt: context.trigger.triggeredAt,
382
503
  user: context.trigger.req?.user
383
504
  }
384
505
  });
506
+ this.logger.info({
507
+ workflowId: workflow.id,
508
+ workflowName: workflow.name,
509
+ contextSummary: {
510
+ triggerType: context.trigger.type,
511
+ triggerCollection: context.trigger.collection,
512
+ triggerOperation: context.trigger.operation,
513
+ hasDoc: !!context.trigger.doc,
514
+ userEmail: context.trigger.req?.user?.email
515
+ }
516
+ }, 'About to create workflow run record');
385
517
  // Create a workflow run record
386
- const workflowRun = await this.payload.create({
387
- collection: 'workflow-runs',
388
- data: {
389
- context: serializeContext(),
390
- startedAt: new Date().toISOString(),
391
- status: 'running',
392
- triggeredBy: context.trigger.req?.user?.email || 'system',
393
- workflow: workflow.id,
394
- workflowVersion: workflow._version || 1
395
- },
396
- req
397
- });
518
+ let workflowRun;
519
+ try {
520
+ workflowRun = await this.payload.create({
521
+ collection: 'workflow-runs',
522
+ data: {
523
+ context: serializeContext(),
524
+ startedAt: new Date().toISOString(),
525
+ status: 'running',
526
+ triggeredBy: context.trigger.req?.user?.email || 'system',
527
+ workflow: workflow.id,
528
+ workflowVersion: 1 // Default version since generated type doesn't have _version field
529
+ },
530
+ req
531
+ });
532
+ this.logger.info({
533
+ workflowRunId: workflowRun.id,
534
+ workflowId: workflow.id,
535
+ workflowName: workflow.name
536
+ }, 'Workflow run record created successfully');
537
+ } catch (error) {
538
+ this.logger.error({
539
+ error: error instanceof Error ? error.message : 'Unknown error',
540
+ errorStack: error instanceof Error ? error.stack : undefined,
541
+ workflowId: workflow.id,
542
+ workflowName: workflow.name
543
+ }, 'Failed to create workflow run record');
544
+ throw error;
545
+ }
398
546
  try {
399
547
  // Resolve execution order based on dependencies
400
- const executionBatches = this.resolveExecutionOrder(workflow.steps);
548
+ const executionBatches = this.resolveExecutionOrder(workflow.steps || []);
401
549
  this.logger.info({
402
550
  batchSizes: executionBatches.map((batch)=>batch.length),
403
551
  totalBatches: executionBatches.length
@@ -499,6 +647,17 @@ export class WorkflowExecutor {
499
647
  targetOperation: operation
500
648
  }, 'Matching triggers found');
501
649
  for (const trigger of matchingTriggers){
650
+ this.logger.info({
651
+ workflowId: workflow.id,
652
+ workflowName: workflow.name,
653
+ triggerDetails: {
654
+ type: trigger.type,
655
+ collection: trigger.collection,
656
+ collectionSlug: trigger.collectionSlug,
657
+ operation: trigger.operation,
658
+ hasCondition: !!trigger.condition
659
+ }
660
+ }, 'Processing matching trigger - about to execute workflow');
502
661
  // Create execution context for condition evaluation
503
662
  const context = {
504
663
  steps: {},
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/workflow-executor.ts"],"sourcesContent":["import type { Payload, PayloadRequest } from 'payload'\n\nimport { JSONPath } from 'jsonpath-plus'\n\nexport type Workflow = {\n _version?: number\n id: string\n name: string\n steps: WorkflowStep[]\n triggers: WorkflowTrigger[]\n}\n\nexport type WorkflowStep = {\n condition?: string\n dependencies?: string[]\n input?: null | Record<string, unknown>\n name: string\n step: string\n}\n\nexport interface WorkflowTrigger {\n collection?: string\n condition?: string\n global?: string\n globalOperation?: string\n operation?: string\n type: string\n webhookPath?: string\n}\n\nexport interface ExecutionContext {\n steps: Record<string, {\n error?: string\n input: unknown\n output: unknown\n state: 'failed' | 'pending' | 'running' | 'succeeded'\n }>\n trigger: {\n collection?: string\n data?: unknown\n doc?: unknown\n headers?: Record<string, string>\n operation?: string\n path?: string\n previousDoc?: unknown\n req?: PayloadRequest\n triggeredAt?: string\n type: string\n user?: {\n collection?: string\n email?: string\n id?: string\n }\n }\n}\n\nexport class WorkflowExecutor {\n constructor(\n private payload: Payload,\n private logger: Payload['logger']\n ) {}\n\n /**\n * Evaluate a step condition using JSONPath\n */\n private evaluateStepCondition(condition: string, context: ExecutionContext): boolean {\n return this.evaluateCondition(condition, context)\n }\n\n /**\n * Execute a single workflow step\n */\n private async executeStep(\n step: WorkflowStep,\n stepIndex: number,\n context: ExecutionContext,\n req: PayloadRequest,\n workflowRunId?: number | string\n ): Promise<void> {\n const stepName = step.name || 'step-' + stepIndex\n\n this.logger.info({\n hasStep: 'step' in step,\n step: JSON.stringify(step),\n stepName\n }, 'Executing step')\n\n // Check step condition if present\n if (step.condition) {\n this.logger.debug({\n condition: step.condition,\n stepName,\n availableSteps: Object.keys(context.steps),\n completedSteps: Object.entries(context.steps)\n .filter(([_, s]) => s.state === 'succeeded')\n .map(([name]) => name),\n triggerType: context.trigger?.type\n }, 'Evaluating step condition')\n\n const conditionMet = this.evaluateStepCondition(step.condition, context)\n\n if (!conditionMet) {\n this.logger.info({\n condition: step.condition,\n stepName,\n contextSnapshot: JSON.stringify({\n stepOutputs: Object.entries(context.steps).reduce((acc, [name, step]) => {\n acc[name] = { state: step.state, hasOutput: !!step.output }\n return acc\n }, {} as Record<string, any>),\n triggerData: context.trigger?.data ? 'present' : 'absent'\n })\n }, 'Step condition not met, skipping')\n\n // Mark step as completed but skipped\n context.steps[stepName] = {\n error: undefined,\n input: undefined,\n output: { reason: 'Condition not met', skipped: true },\n state: 'succeeded'\n }\n\n // Update workflow run context if needed\n if (workflowRunId) {\n await this.updateWorkflowRunContext(workflowRunId, context, req)\n }\n\n return\n }\n\n this.logger.info({\n condition: step.condition,\n stepName,\n contextSnapshot: JSON.stringify({\n stepOutputs: Object.entries(context.steps).reduce((acc, [name, step]) => {\n acc[name] = { state: step.state, hasOutput: !!step.output }\n return acc\n }, {} as Record<string, any>),\n triggerData: context.trigger?.data ? 'present' : 'absent'\n })\n }, 'Step condition met, proceeding with execution')\n }\n\n // Initialize step context\n context.steps[stepName] = {\n error: undefined,\n input: undefined,\n output: undefined,\n state: 'running'\n }\n\n // Move taskSlug declaration outside try block so it's accessible in catch\n const taskSlug = step.step // Use the 'step' field for task type\n\n try {\n // Resolve input data using JSONPath\n const resolvedInput = this.resolveStepInput(step.input || {}, context)\n context.steps[stepName].input = resolvedInput\n\n if (!taskSlug) {\n throw new Error(`Step ${stepName} is missing a task type`)\n }\n\n this.logger.info({\n hasInput: !!resolvedInput,\n hasReq: !!req,\n stepName,\n taskSlug\n }, 'Queueing task')\n\n const job = await this.payload.jobs.queue({\n input: resolvedInput,\n req,\n task: taskSlug\n })\n\n // Run the job immediately\n await this.payload.jobs.run({\n limit: 1,\n req\n })\n\n // Get the job result\n const completedJob = await this.payload.findByID({\n id: job.id,\n collection: 'payload-jobs',\n req\n })\n\n const taskStatus = completedJob.taskStatus?.[completedJob.taskSlug]?.[completedJob.totalTried]\n const isComplete = taskStatus?.complete === true\n const hasError = completedJob.hasError || !isComplete\n\n // Extract error information from job if available\n let errorMessage: string | undefined\n if (hasError) {\n // Try to get error from the latest log entry\n if (completedJob.log && completedJob.log.length > 0) {\n const latestLog = completedJob.log[completedJob.log.length - 1]\n errorMessage = latestLog.error?.message || latestLog.error\n }\n\n // Fallback to top-level error\n if (!errorMessage && completedJob.error) {\n errorMessage = completedJob.error.message || completedJob.error\n }\n\n // Final fallback to generic message\n if (!errorMessage) {\n errorMessage = `Task ${taskSlug} failed without detailed error information`\n }\n }\n\n const result: {\n error: string | undefined\n output: unknown\n state: 'failed' | 'succeeded'\n } = {\n error: errorMessage,\n output: taskStatus?.output || {},\n state: isComplete ? 'succeeded' : 'failed'\n }\n\n // Store the output and error\n context.steps[stepName].output = result.output\n context.steps[stepName].state = result.state\n if (result.error) {\n context.steps[stepName].error = result.error\n }\n\n this.logger.debug({context}, 'Step execution context')\n\n if (result.state !== 'succeeded') {\n throw new Error(result.error || `Step ${stepName} failed`)\n }\n\n this.logger.info({\n output: result.output,\n stepName\n }, 'Step completed')\n\n // Update workflow run with current step results if workflowRunId is provided\n if (workflowRunId) {\n await this.updateWorkflowRunContext(workflowRunId, context, req)\n }\n\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error'\n context.steps[stepName].state = 'failed'\n context.steps[stepName].error = errorMessage\n\n this.logger.error({\n error: errorMessage,\n input: context.steps[stepName].input,\n stepName,\n taskSlug\n }, 'Step execution failed')\n\n // Update workflow run with current step results if workflowRunId is provided\n if (workflowRunId) {\n try {\n await this.updateWorkflowRunContext(workflowRunId, context, req)\n } catch (updateError) {\n this.logger.error({\n error: updateError instanceof Error ? updateError.message : 'Unknown error',\n stepName\n }, 'Failed to update workflow run context after step failure')\n }\n }\n\n throw error\n }\n }\n\n /**\n * Resolve step execution order based on dependencies\n */\n private resolveExecutionOrder(steps: WorkflowStep[]): WorkflowStep[][] {\n const stepMap = new Map<string, WorkflowStep>()\n const dependencyGraph = new Map<string, string[]>()\n const indegree = new Map<string, number>()\n\n // Build the step map and dependency graph\n for (const step of steps) {\n const stepName = step.name || `step-${steps.indexOf(step)}`\n const dependencies = step.dependencies || []\n\n stepMap.set(stepName, { ...step, name: stepName, dependencies })\n dependencyGraph.set(stepName, dependencies)\n indegree.set(stepName, dependencies.length)\n }\n\n // Topological sort to determine execution batches\n const executionBatches: WorkflowStep[][] = []\n const processed = new Set<string>()\n\n while (processed.size < steps.length) {\n const currentBatch: WorkflowStep[] = []\n\n // Find all steps with no remaining dependencies\n for (const [stepName, inDegree] of indegree.entries()) {\n if (inDegree === 0 && !processed.has(stepName)) {\n const step = stepMap.get(stepName)\n if (step) {\n currentBatch.push(step)\n }\n }\n }\n\n if (currentBatch.length === 0) {\n throw new Error('Circular dependency detected in workflow steps')\n }\n\n executionBatches.push(currentBatch)\n\n // Update indegrees for next iteration\n for (const step of currentBatch) {\n processed.add(step.name)\n\n // Reduce indegree for steps that depend on completed steps\n for (const [otherStepName, dependencies] of dependencyGraph.entries()) {\n if (dependencies.includes(step.name) && !processed.has(otherStepName)) {\n indegree.set(otherStepName, (indegree.get(otherStepName) || 0) - 1)\n }\n }\n }\n }\n\n return executionBatches\n }\n\n /**\n * Resolve step input using JSONPath expressions\n */\n private resolveStepInput(config: Record<string, unknown>, context: ExecutionContext): Record<string, unknown> {\n const resolved: Record<string, unknown> = {}\n\n this.logger.debug({\n configKeys: Object.keys(config),\n contextSteps: Object.keys(context.steps),\n triggerType: context.trigger?.type\n }, 'Starting step input resolution')\n\n for (const [key, value] of Object.entries(config)) {\n if (typeof value === 'string' && value.startsWith('$')) {\n // This is a JSONPath expression\n this.logger.debug({\n key,\n jsonPath: value,\n availableSteps: Object.keys(context.steps),\n hasTriggerData: !!context.trigger?.data,\n hasTriggerDoc: !!context.trigger?.doc\n }, 'Resolving JSONPath expression')\n\n try {\n const result = JSONPath({\n json: context,\n path: value,\n wrap: false\n })\n \n this.logger.debug({\n key,\n jsonPath: value,\n result: JSON.stringify(result).substring(0, 200),\n resultType: Array.isArray(result) ? 'array' : typeof result\n }, 'JSONPath resolved successfully')\n \n resolved[key] = result\n } catch (error) {\n this.logger.warn({\n error: error instanceof Error ? error.message : 'Unknown error',\n key,\n path: value,\n contextSnapshot: JSON.stringify(context).substring(0, 500)\n }, 'Failed to resolve JSONPath')\n resolved[key] = value // Keep original value if resolution fails\n }\n } else if (typeof value === 'object' && value !== null) {\n // Recursively resolve nested objects\n this.logger.debug({\n key,\n nestedKeys: Object.keys(value as Record<string, unknown>)\n }, 'Recursively resolving nested object')\n \n resolved[key] = this.resolveStepInput(value as Record<string, unknown>, context)\n } else {\n // Keep literal values as-is\n resolved[key] = value\n }\n }\n\n this.logger.debug({\n resolvedKeys: Object.keys(resolved),\n originalKeys: Object.keys(config)\n }, 'Step input resolution completed')\n\n return resolved\n }\n\n /**\n * Update workflow run with current context\n */\n private async updateWorkflowRunContext(\n workflowRunId: number | string,\n context: ExecutionContext,\n req: PayloadRequest\n ): Promise<void> {\n const serializeContext = () => ({\n steps: context.steps,\n trigger: {\n type: context.trigger.type,\n collection: context.trigger.collection,\n data: context.trigger.data,\n doc: context.trigger.doc,\n operation: context.trigger.operation,\n previousDoc: context.trigger.previousDoc,\n triggeredAt: context.trigger.triggeredAt,\n user: context.trigger.req?.user\n }\n })\n\n await this.payload.update({\n id: workflowRunId,\n collection: 'workflow-runs',\n data: {\n context: serializeContext()\n },\n req\n })\n }\n\n /**\n * Evaluate a condition using JSONPath\n */\n public evaluateCondition(condition: string, context: ExecutionContext): boolean {\n this.logger.debug({\n condition,\n contextKeys: Object.keys(context),\n triggerType: context.trigger?.type,\n triggerData: context.trigger?.data,\n triggerDoc: context.trigger?.doc ? 'present' : 'absent'\n }, 'Starting condition evaluation')\n\n try {\n const result = JSONPath({\n json: context,\n path: condition,\n wrap: false\n })\n\n this.logger.debug({\n condition,\n result,\n resultType: Array.isArray(result) ? 'array' : typeof result,\n resultLength: Array.isArray(result) ? result.length : undefined\n }, 'JSONPath evaluation result')\n\n // Handle different result types\n let finalResult: boolean\n if (Array.isArray(result)) {\n finalResult = result.length > 0 && Boolean(result[0])\n } else {\n finalResult = Boolean(result)\n }\n\n this.logger.debug({\n condition,\n finalResult,\n originalResult: result\n }, 'Condition evaluation completed')\n\n return finalResult\n } catch (error) {\n this.logger.warn({\n condition,\n error: error instanceof Error ? error.message : 'Unknown error',\n errorStack: error instanceof Error ? error.stack : undefined\n }, 'Failed to evaluate condition')\n\n // If condition evaluation fails, assume false\n return false\n }\n }\n\n /**\n * Execute a workflow with the given context\n */\n async execute(workflow: Workflow, context: ExecutionContext, req: PayloadRequest): Promise<void> {\n this.logger.info({\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Starting workflow execution')\n\n const serializeContext = () => ({\n steps: context.steps,\n trigger: {\n type: context.trigger.type,\n collection: context.trigger.collection,\n data: context.trigger.data,\n doc: context.trigger.doc,\n operation: context.trigger.operation,\n previousDoc: context.trigger.previousDoc,\n triggeredAt: context.trigger.triggeredAt,\n user: context.trigger.req?.user\n }\n })\n\n // Create a workflow run record\n const workflowRun = await this.payload.create({\n collection: 'workflow-runs',\n data: {\n context: serializeContext(),\n startedAt: new Date().toISOString(),\n status: 'running',\n triggeredBy: context.trigger.req?.user?.email || 'system',\n workflow: workflow.id,\n workflowVersion: workflow._version || 1\n },\n req\n })\n\n try {\n // Resolve execution order based on dependencies\n const executionBatches = this.resolveExecutionOrder(workflow.steps)\n\n this.logger.info({\n batchSizes: executionBatches.map(batch => batch.length),\n totalBatches: executionBatches.length\n }, 'Resolved step execution order')\n\n // Execute each batch in sequence, but steps within each batch in parallel\n for (let batchIndex = 0; batchIndex < executionBatches.length; batchIndex++) {\n const batch = executionBatches[batchIndex]\n\n this.logger.info({\n batchIndex,\n stepCount: batch.length,\n stepNames: batch.map(s => s.name)\n }, 'Executing batch')\n\n // Execute all steps in this batch in parallel\n const batchPromises = batch.map((step, stepIndex) =>\n this.executeStep(step, stepIndex, context, req, workflowRun.id)\n )\n\n // Wait for all steps in the current batch to complete\n await Promise.all(batchPromises)\n\n this.logger.info({\n batchIndex,\n stepCount: batch.length\n }, 'Batch completed')\n }\n\n // Update workflow run as completed\n await this.payload.update({\n id: workflowRun.id,\n collection: 'workflow-runs',\n data: {\n completedAt: new Date().toISOString(),\n context: serializeContext(),\n status: 'completed'\n },\n req\n })\n\n this.logger.info({\n runId: workflowRun.id,\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Workflow execution completed')\n\n } catch (error) {\n // Update workflow run as failed\n await this.payload.update({\n id: workflowRun.id,\n collection: 'workflow-runs',\n data: {\n completedAt: new Date().toISOString(),\n context: serializeContext(),\n error: error instanceof Error ? error.message : 'Unknown error',\n status: 'failed'\n },\n req\n })\n\n this.logger.error({\n error: error instanceof Error ? error.message : 'Unknown error',\n runId: workflowRun.id,\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Workflow execution failed')\n\n throw error\n }\n }\n\n /**\n * Find and execute workflows triggered by a collection operation\n */\n async executeTriggeredWorkflows(\n collection: string,\n operation: 'create' | 'delete' | 'read' | 'update',\n doc: unknown,\n previousDoc: unknown,\n req: PayloadRequest\n ): Promise<void> {\n this.logger.info({\n collection,\n operation,\n docId: (doc as any)?.id\n }, 'executeTriggeredWorkflows called')\n \n try {\n // Find workflows with matching triggers\n const workflows = await this.payload.find({\n collection: 'workflows',\n depth: 2, // Include steps and triggers\n limit: 100,\n req\n })\n \n this.logger.info({\n workflowCount: workflows.docs.length\n }, 'Found workflows to check')\n\n for (const workflow of workflows.docs) {\n // Check if this workflow has a matching trigger\n const triggers = workflow.triggers as Array<{\n collection?: string\n collectionSlug?: string\n condition?: string\n operation: string\n type: string\n }>\n \n this.logger.debug({\n workflowId: workflow.id,\n workflowName: workflow.name,\n triggerCount: triggers?.length || 0,\n triggers: triggers?.map(t => ({\n type: t.type,\n collection: t.collection,\n collectionSlug: t.collectionSlug,\n operation: t.operation\n }))\n }, 'Checking workflow triggers')\n\n const matchingTriggers = triggers?.filter(trigger =>\n trigger.type === 'collection-trigger' &&\n (trigger.collection === collection || trigger.collectionSlug === collection) &&\n trigger.operation === operation\n ) || []\n \n this.logger.info({\n workflowId: workflow.id,\n workflowName: workflow.name,\n matchingTriggerCount: matchingTriggers.length,\n targetCollection: collection,\n targetOperation: operation\n }, 'Matching triggers found')\n\n for (const trigger of matchingTriggers) {\n // Create execution context for condition evaluation\n const context: ExecutionContext = {\n steps: {},\n trigger: {\n type: 'collection',\n collection,\n doc,\n operation,\n previousDoc,\n req\n }\n }\n\n // Check trigger condition if present\n if (trigger.condition) {\n this.logger.debug({\n collection,\n operation,\n condition: trigger.condition,\n docId: (doc as any)?.id,\n docFields: doc ? Object.keys(doc) : [],\n previousDocId: (previousDoc as any)?.id,\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Evaluating collection trigger condition')\n\n const conditionMet = this.evaluateCondition(trigger.condition, context)\n\n if (!conditionMet) {\n this.logger.info({\n collection,\n condition: trigger.condition,\n operation,\n workflowId: workflow.id,\n workflowName: workflow.name,\n docSnapshot: JSON.stringify(doc).substring(0, 200)\n }, 'Trigger condition not met, skipping workflow')\n continue\n }\n\n this.logger.info({\n collection,\n condition: trigger.condition,\n operation,\n workflowId: workflow.id,\n workflowName: workflow.name,\n docSnapshot: JSON.stringify(doc).substring(0, 200)\n }, 'Trigger condition met')\n }\n\n this.logger.info({\n collection,\n operation,\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Triggering workflow')\n\n // Execute the workflow\n await this.execute(workflow as Workflow, context, req)\n }\n }\n } catch (error) {\n this.logger.error({ error: error instanceof Error ? error.message : 'Unknown error' }, 'Workflow execution failed')\n this.logger.error({\n collection,\n error: error instanceof Error ? error.message : 'Unknown error',\n operation\n }, 'Failed to execute triggered workflows')\n }\n }\n}\n"],"names":["JSONPath","WorkflowExecutor","payload","logger","evaluateStepCondition","condition","context","evaluateCondition","executeStep","step","stepIndex","req","workflowRunId","stepName","name","info","hasStep","JSON","stringify","debug","availableSteps","Object","keys","steps","completedSteps","entries","filter","_","s","state","map","triggerType","trigger","type","conditionMet","contextSnapshot","stepOutputs","reduce","acc","hasOutput","output","triggerData","data","error","undefined","input","reason","skipped","updateWorkflowRunContext","taskSlug","resolvedInput","resolveStepInput","Error","hasInput","hasReq","job","jobs","queue","task","run","limit","completedJob","findByID","id","collection","taskStatus","totalTried","isComplete","complete","hasError","errorMessage","log","length","latestLog","message","result","updateError","resolveExecutionOrder","stepMap","Map","dependencyGraph","indegree","indexOf","dependencies","set","executionBatches","processed","Set","size","currentBatch","inDegree","has","get","push","add","otherStepName","includes","config","resolved","configKeys","contextSteps","key","value","startsWith","jsonPath","hasTriggerData","hasTriggerDoc","doc","json","path","wrap","substring","resultType","Array","isArray","warn","nestedKeys","resolvedKeys","originalKeys","serializeContext","operation","previousDoc","triggeredAt","user","update","contextKeys","triggerDoc","resultLength","finalResult","Boolean","originalResult","errorStack","stack","execute","workflow","workflowId","workflowName","workflowRun","create","startedAt","Date","toISOString","status","triggeredBy","email","workflowVersion","_version","batchSizes","batch","totalBatches","batchIndex","stepCount","stepNames","batchPromises","Promise","all","completedAt","runId","executeTriggeredWorkflows","docId","workflows","find","depth","workflowCount","docs","triggers","triggerCount","t","collectionSlug","matchingTriggers","matchingTriggerCount","targetCollection","targetOperation","docFields","previousDocId","docSnapshot"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/core/workflow-executor.ts"],"sourcesContent":["import type { Payload, PayloadRequest } from 'payload'\n\n// We need to reference the generated types dynamically since they're not available at build time\n// Using generic types and casting where necessary\nexport type PayloadWorkflow = {\n id: number\n name: string\n description?: string | null\n triggers?: Array<{\n type?: string | null\n collectionSlug?: string | null\n operation?: string | null\n condition?: string | null\n [key: string]: unknown\n }> | null\n steps?: Array<{\n step?: string | null\n name?: string | null\n input?: unknown\n dependencies?: string[] | null\n condition?: string | null\n [key: string]: unknown\n }> | null\n [key: string]: unknown\n}\n\nimport { JSONPath } from 'jsonpath-plus'\n\n// Helper type to extract workflow step data from the generated types\nexport type WorkflowStep = NonNullable<PayloadWorkflow['steps']>[0] & {\n name: string // Ensure name is always present for our execution logic\n}\n\n// Helper type to extract workflow trigger data from the generated types \nexport type WorkflowTrigger = NonNullable<PayloadWorkflow['triggers']>[0] & {\n type: string // Ensure type is always present for our execution logic\n}\n\nexport interface ExecutionContext {\n steps: Record<string, {\n error?: string\n input: unknown\n output: unknown\n state: 'failed' | 'pending' | 'running' | 'succeeded'\n }>\n trigger: {\n collection?: string\n data?: unknown\n doc?: unknown\n headers?: Record<string, string>\n operation?: string\n path?: string\n previousDoc?: unknown\n req?: PayloadRequest\n triggeredAt?: string\n type: string\n user?: {\n collection?: string\n email?: string\n id?: string\n }\n }\n}\n\nexport class WorkflowExecutor {\n constructor(\n private payload: Payload,\n private logger: Payload['logger']\n ) {}\n\n /**\n * Evaluate a step condition using JSONPath\n */\n private evaluateStepCondition(condition: string, context: ExecutionContext): boolean {\n return this.evaluateCondition(condition, context)\n }\n\n /**\n * Execute a single workflow step\n */\n private async executeStep(\n step: WorkflowStep,\n stepIndex: number,\n context: ExecutionContext,\n req: PayloadRequest,\n workflowRunId?: number | string\n ): Promise<void> {\n const stepName = step.name || 'step-' + stepIndex\n\n this.logger.info({\n hasStep: 'step' in step,\n step: JSON.stringify(step),\n stepName\n }, 'Executing step')\n\n // Check step condition if present\n if (step.condition) {\n this.logger.debug({\n condition: step.condition,\n stepName,\n availableSteps: Object.keys(context.steps),\n completedSteps: Object.entries(context.steps)\n .filter(([_, s]) => s.state === 'succeeded')\n .map(([name]) => name),\n triggerType: context.trigger?.type\n }, 'Evaluating step condition')\n\n const conditionMet = this.evaluateStepCondition(step.condition, context)\n\n if (!conditionMet) {\n this.logger.info({\n condition: step.condition,\n stepName,\n contextSnapshot: JSON.stringify({\n stepOutputs: Object.entries(context.steps).reduce((acc, [name, step]) => {\n acc[name] = { state: step.state, hasOutput: !!step.output }\n return acc\n }, {} as Record<string, any>),\n triggerData: context.trigger?.data ? 'present' : 'absent'\n })\n }, 'Step condition not met, skipping')\n\n // Mark step as completed but skipped\n context.steps[stepName] = {\n error: undefined,\n input: undefined,\n output: { reason: 'Condition not met', skipped: true },\n state: 'succeeded'\n }\n\n // Update workflow run context if needed\n if (workflowRunId) {\n await this.updateWorkflowRunContext(workflowRunId, context, req)\n }\n\n return\n }\n\n this.logger.info({\n condition: step.condition,\n stepName,\n contextSnapshot: JSON.stringify({\n stepOutputs: Object.entries(context.steps).reduce((acc, [name, step]) => {\n acc[name] = { state: step.state, hasOutput: !!step.output }\n return acc\n }, {} as Record<string, any>),\n triggerData: context.trigger?.data ? 'present' : 'absent'\n })\n }, 'Step condition met, proceeding with execution')\n }\n\n // Initialize step context\n context.steps[stepName] = {\n error: undefined,\n input: undefined,\n output: undefined,\n state: 'running'\n }\n\n // Move taskSlug declaration outside try block so it's accessible in catch\n const taskSlug = step.step // Use the 'step' field for task type\n\n try {\n // Resolve input data using JSONPath\n const resolvedInput = this.resolveStepInput(step.input as Record<string, unknown> || {}, context)\n context.steps[stepName].input = resolvedInput\n\n if (!taskSlug) {\n throw new Error(`Step ${stepName} is missing a task type`)\n }\n\n this.logger.info({\n hasInput: !!resolvedInput,\n hasReq: !!req,\n stepName,\n taskSlug\n }, 'Queueing task')\n\n const job = await this.payload.jobs.queue({\n input: resolvedInput,\n req,\n task: taskSlug\n })\n\n // Run the job immediately\n await this.payload.jobs.run({\n limit: 1,\n req\n })\n\n // Get the job result\n const completedJob = await this.payload.findByID({\n id: job.id,\n collection: 'payload-jobs',\n req\n })\n\n const taskStatus = completedJob.taskStatus?.[completedJob.taskSlug]?.[completedJob.totalTried]\n const isComplete = taskStatus?.complete === true\n const hasError = completedJob.hasError || !isComplete\n\n // Extract error information from job if available\n let errorMessage: string | undefined\n if (hasError) {\n // Try to get error from the latest log entry\n if (completedJob.log && completedJob.log.length > 0) {\n const latestLog = completedJob.log[completedJob.log.length - 1]\n errorMessage = latestLog.error?.message || latestLog.error\n }\n\n // Fallback to top-level error\n if (!errorMessage && completedJob.error) {\n errorMessage = completedJob.error.message || completedJob.error\n }\n\n // Final fallback to generic message\n if (!errorMessage) {\n errorMessage = `Task ${taskSlug} failed without detailed error information`\n }\n }\n\n const result: {\n error: string | undefined\n output: unknown\n state: 'failed' | 'succeeded'\n } = {\n error: errorMessage,\n output: taskStatus?.output || {},\n state: isComplete ? 'succeeded' : 'failed'\n }\n\n // Store the output and error\n context.steps[stepName].output = result.output\n context.steps[stepName].state = result.state\n if (result.error) {\n context.steps[stepName].error = result.error\n }\n\n this.logger.debug({context}, 'Step execution context')\n\n if (result.state !== 'succeeded') {\n throw new Error(result.error || `Step ${stepName} failed`)\n }\n\n this.logger.info({\n output: result.output,\n stepName\n }, 'Step completed')\n\n // Update workflow run with current step results if workflowRunId is provided\n if (workflowRunId) {\n await this.updateWorkflowRunContext(workflowRunId, context, req)\n }\n\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error'\n context.steps[stepName].state = 'failed'\n context.steps[stepName].error = errorMessage\n\n this.logger.error({\n error: errorMessage,\n input: context.steps[stepName].input,\n stepName,\n taskSlug\n }, 'Step execution failed')\n\n // Update workflow run with current step results if workflowRunId is provided\n if (workflowRunId) {\n try {\n await this.updateWorkflowRunContext(workflowRunId, context, req)\n } catch (updateError) {\n this.logger.error({\n error: updateError instanceof Error ? updateError.message : 'Unknown error',\n stepName\n }, 'Failed to update workflow run context after step failure')\n }\n }\n\n throw error\n }\n }\n\n /**\n * Resolve step execution order based on dependencies\n */\n private resolveExecutionOrder(steps: WorkflowStep[]): WorkflowStep[][] {\n const stepMap = new Map<string, WorkflowStep>()\n const dependencyGraph = new Map<string, string[]>()\n const indegree = new Map<string, number>()\n\n // Build the step map and dependency graph\n for (const step of steps) {\n const stepName = step.name || `step-${steps.indexOf(step)}`\n const dependencies = step.dependencies || []\n\n stepMap.set(stepName, { ...step, name: stepName, dependencies })\n dependencyGraph.set(stepName, dependencies)\n indegree.set(stepName, dependencies.length)\n }\n\n // Topological sort to determine execution batches\n const executionBatches: WorkflowStep[][] = []\n const processed = new Set<string>()\n\n while (processed.size < steps.length) {\n const currentBatch: WorkflowStep[] = []\n\n // Find all steps with no remaining dependencies\n for (const [stepName, inDegree] of indegree.entries()) {\n if (inDegree === 0 && !processed.has(stepName)) {\n const step = stepMap.get(stepName)\n if (step) {\n currentBatch.push(step)\n }\n }\n }\n\n if (currentBatch.length === 0) {\n throw new Error('Circular dependency detected in workflow steps')\n }\n\n executionBatches.push(currentBatch)\n\n // Update indegrees for next iteration\n for (const step of currentBatch) {\n processed.add(step.name)\n\n // Reduce indegree for steps that depend on completed steps\n for (const [otherStepName, dependencies] of dependencyGraph.entries()) {\n if (dependencies.includes(step.name) && !processed.has(otherStepName)) {\n indegree.set(otherStepName, (indegree.get(otherStepName) || 0) - 1)\n }\n }\n }\n }\n\n return executionBatches\n }\n\n /**\n * Resolve step input using JSONPath expressions\n */\n private resolveStepInput(config: Record<string, unknown>, context: ExecutionContext): Record<string, unknown> {\n const resolved: Record<string, unknown> = {}\n\n this.logger.debug({\n configKeys: Object.keys(config),\n contextSteps: Object.keys(context.steps),\n triggerType: context.trigger?.type\n }, 'Starting step input resolution')\n\n for (const [key, value] of Object.entries(config)) {\n if (typeof value === 'string' && value.startsWith('$')) {\n // This is a JSONPath expression\n this.logger.debug({\n key,\n jsonPath: value,\n availableSteps: Object.keys(context.steps),\n hasTriggerData: !!context.trigger?.data,\n hasTriggerDoc: !!context.trigger?.doc\n }, 'Resolving JSONPath expression')\n\n try {\n const result = JSONPath({\n json: context,\n path: value,\n wrap: false\n })\n \n this.logger.debug({\n key,\n jsonPath: value,\n result: JSON.stringify(result).substring(0, 200),\n resultType: Array.isArray(result) ? 'array' : typeof result\n }, 'JSONPath resolved successfully')\n \n resolved[key] = result\n } catch (error) {\n this.logger.warn({\n error: error instanceof Error ? error.message : 'Unknown error',\n key,\n path: value,\n contextSnapshot: JSON.stringify(context).substring(0, 500)\n }, 'Failed to resolve JSONPath')\n resolved[key] = value // Keep original value if resolution fails\n }\n } else if (typeof value === 'object' && value !== null) {\n // Recursively resolve nested objects\n this.logger.debug({\n key,\n nestedKeys: Object.keys(value as Record<string, unknown>)\n }, 'Recursively resolving nested object')\n \n resolved[key] = this.resolveStepInput(value as Record<string, unknown>, context)\n } else {\n // Keep literal values as-is\n resolved[key] = value\n }\n }\n\n this.logger.debug({\n resolvedKeys: Object.keys(resolved),\n originalKeys: Object.keys(config)\n }, 'Step input resolution completed')\n\n return resolved\n }\n\n /**\n * Safely serialize an object, handling circular references and non-serializable values\n */\n private safeSerialize(obj: unknown): unknown {\n const seen = new WeakSet()\n \n const serialize = (value: unknown): unknown => {\n if (value === null || typeof value !== 'object') {\n return value\n }\n \n if (seen.has(value as object)) {\n return '[Circular Reference]'\n }\n \n seen.add(value as object)\n \n if (Array.isArray(value)) {\n return value.map(serialize)\n }\n \n const result: Record<string, unknown> = {}\n for (const [key, val] of Object.entries(value as Record<string, unknown>)) {\n try {\n // Skip non-serializable properties that are likely internal database objects\n if (key === 'table' || key === 'schema' || key === '_' || key === '__') {\n continue\n }\n result[key] = serialize(val)\n } catch {\n // Skip properties that can't be accessed or serialized\n result[key] = '[Non-serializable]'\n }\n }\n \n return result\n }\n \n return serialize(obj)\n }\n\n /**\n * Update workflow run with current context\n */\n private async updateWorkflowRunContext(\n workflowRunId: number | string,\n context: ExecutionContext,\n req: PayloadRequest\n ): Promise<void> {\n const serializeContext = () => ({\n steps: this.safeSerialize(context.steps),\n trigger: {\n type: context.trigger.type,\n collection: context.trigger.collection,\n data: this.safeSerialize(context.trigger.data),\n doc: this.safeSerialize(context.trigger.doc),\n operation: context.trigger.operation,\n previousDoc: this.safeSerialize(context.trigger.previousDoc),\n triggeredAt: context.trigger.triggeredAt,\n user: context.trigger.req?.user\n }\n })\n\n await this.payload.update({\n id: workflowRunId,\n collection: 'workflow-runs',\n data: {\n context: serializeContext()\n },\n req\n })\n }\n\n /**\n * Evaluate a condition using JSONPath and comparison operators\n */\n public evaluateCondition(condition: string, context: ExecutionContext): boolean {\n this.logger.debug({\n condition,\n contextKeys: Object.keys(context),\n triggerType: context.trigger?.type,\n triggerData: context.trigger?.data,\n triggerDoc: context.trigger?.doc ? 'present' : 'absent'\n }, 'Starting condition evaluation')\n\n try {\n // Check if this is a comparison expression\n const comparisonMatch = condition.match(/^(.+?)\\s*(==|!=|>|<|>=|<=)\\s*(.+)$/)\n \n if (comparisonMatch) {\n const [, leftExpr, operator, rightExpr] = comparisonMatch\n \n // Evaluate left side (should be JSONPath)\n const leftValue = this.resolveJSONPathValue(leftExpr.trim(), context)\n \n // Parse right side (could be string, number, boolean, or JSONPath)\n const rightValue = this.parseConditionValue(rightExpr.trim(), context)\n \n this.logger.debug({\n condition,\n leftExpr: leftExpr.trim(),\n leftValue,\n operator,\n rightExpr: rightExpr.trim(),\n rightValue,\n leftType: typeof leftValue,\n rightType: typeof rightValue\n }, 'Evaluating comparison condition')\n \n // Perform comparison\n let result: boolean\n switch (operator) {\n case '==':\n result = leftValue === rightValue\n break\n case '!=':\n result = leftValue !== rightValue\n break\n case '>':\n result = Number(leftValue) > Number(rightValue)\n break\n case '<':\n result = Number(leftValue) < Number(rightValue)\n break\n case '>=':\n result = Number(leftValue) >= Number(rightValue)\n break\n case '<=':\n result = Number(leftValue) <= Number(rightValue)\n break\n default:\n throw new Error(`Unknown comparison operator: ${operator}`)\n }\n \n this.logger.debug({\n condition,\n result,\n leftValue,\n rightValue,\n operator\n }, 'Comparison condition evaluation completed')\n \n return result\n } else {\n // Treat as simple JSONPath boolean evaluation\n const result = JSONPath({\n json: context,\n path: condition,\n wrap: false\n })\n\n this.logger.debug({\n condition,\n result,\n resultType: Array.isArray(result) ? 'array' : typeof result,\n resultLength: Array.isArray(result) ? result.length : undefined\n }, 'JSONPath boolean evaluation result')\n\n // Handle different result types\n let finalResult: boolean\n if (Array.isArray(result)) {\n finalResult = result.length > 0 && Boolean(result[0])\n } else {\n finalResult = Boolean(result)\n }\n\n this.logger.debug({\n condition,\n finalResult,\n originalResult: result\n }, 'Boolean condition evaluation completed')\n\n return finalResult\n }\n } catch (error) {\n this.logger.warn({\n condition,\n error: error instanceof Error ? error.message : 'Unknown error',\n errorStack: error instanceof Error ? error.stack : undefined\n }, 'Failed to evaluate condition')\n\n // If condition evaluation fails, assume false\n return false\n }\n }\n \n /**\n * Resolve a JSONPath value from the context\n */\n private resolveJSONPathValue(expr: string, context: ExecutionContext): any {\n if (expr.startsWith('$')) {\n const result = JSONPath({\n json: context,\n path: expr,\n wrap: false\n })\n // Return first result if array, otherwise the result itself\n return Array.isArray(result) && result.length > 0 ? result[0] : result\n }\n return expr\n }\n \n /**\n * Parse a condition value (string literal, number, boolean, or JSONPath)\n */\n private parseConditionValue(expr: string, context: ExecutionContext): any {\n // Handle string literals\n if ((expr.startsWith('\"') && expr.endsWith('\"')) || (expr.startsWith(\"'\") && expr.endsWith(\"'\"))) {\n return expr.slice(1, -1) // Remove quotes\n }\n \n // Handle boolean literals\n if (expr === 'true') return true\n if (expr === 'false') return false\n \n // Handle number literals\n if (/^-?\\d+(\\.\\d+)?$/.test(expr)) {\n return Number(expr)\n }\n \n // Handle JSONPath expressions\n if (expr.startsWith('$')) {\n return this.resolveJSONPathValue(expr, context)\n }\n \n // Return as string if nothing else matches\n return expr\n }\n\n /**\n * Execute a workflow with the given context\n */\n async execute(workflow: PayloadWorkflow, context: ExecutionContext, req: PayloadRequest): Promise<void> {\n this.logger.info({\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Starting workflow execution')\n\n const serializeContext = () => ({\n steps: this.safeSerialize(context.steps),\n trigger: {\n type: context.trigger.type,\n collection: context.trigger.collection,\n data: this.safeSerialize(context.trigger.data),\n doc: this.safeSerialize(context.trigger.doc),\n operation: context.trigger.operation,\n previousDoc: this.safeSerialize(context.trigger.previousDoc),\n triggeredAt: context.trigger.triggeredAt,\n user: context.trigger.req?.user\n }\n })\n\n this.logger.info({\n workflowId: workflow.id,\n workflowName: workflow.name,\n contextSummary: {\n triggerType: context.trigger.type,\n triggerCollection: context.trigger.collection,\n triggerOperation: context.trigger.operation,\n hasDoc: !!context.trigger.doc,\n userEmail: context.trigger.req?.user?.email\n }\n }, 'About to create workflow run record')\n\n // Create a workflow run record\n let workflowRun;\n try {\n workflowRun = await this.payload.create({\n collection: 'workflow-runs',\n data: {\n context: serializeContext(),\n startedAt: new Date().toISOString(),\n status: 'running',\n triggeredBy: context.trigger.req?.user?.email || 'system',\n workflow: workflow.id,\n workflowVersion: 1 // Default version since generated type doesn't have _version field\n },\n req\n })\n\n this.logger.info({\n workflowRunId: workflowRun.id,\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Workflow run record created successfully')\n } catch (error) {\n this.logger.error({\n error: error instanceof Error ? error.message : 'Unknown error',\n errorStack: error instanceof Error ? error.stack : undefined,\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Failed to create workflow run record')\n throw error\n }\n\n try {\n // Resolve execution order based on dependencies\n const executionBatches = this.resolveExecutionOrder(workflow.steps as WorkflowStep[] || [])\n\n this.logger.info({\n batchSizes: executionBatches.map(batch => batch.length),\n totalBatches: executionBatches.length\n }, 'Resolved step execution order')\n\n // Execute each batch in sequence, but steps within each batch in parallel\n for (let batchIndex = 0; batchIndex < executionBatches.length; batchIndex++) {\n const batch = executionBatches[batchIndex]\n\n this.logger.info({\n batchIndex,\n stepCount: batch.length,\n stepNames: batch.map(s => s.name)\n }, 'Executing batch')\n\n // Execute all steps in this batch in parallel\n const batchPromises = batch.map((step, stepIndex) =>\n this.executeStep(step, stepIndex, context, req, workflowRun.id)\n )\n\n // Wait for all steps in the current batch to complete\n await Promise.all(batchPromises)\n\n this.logger.info({\n batchIndex,\n stepCount: batch.length\n }, 'Batch completed')\n }\n\n // Update workflow run as completed\n await this.payload.update({\n id: workflowRun.id,\n collection: 'workflow-runs',\n data: {\n completedAt: new Date().toISOString(),\n context: serializeContext(),\n status: 'completed'\n },\n req\n })\n\n this.logger.info({\n runId: workflowRun.id,\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Workflow execution completed')\n\n } catch (error) {\n // Update workflow run as failed\n await this.payload.update({\n id: workflowRun.id,\n collection: 'workflow-runs',\n data: {\n completedAt: new Date().toISOString(),\n context: serializeContext(),\n error: error instanceof Error ? error.message : 'Unknown error',\n status: 'failed'\n },\n req\n })\n\n this.logger.error({\n error: error instanceof Error ? error.message : 'Unknown error',\n runId: workflowRun.id,\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Workflow execution failed')\n\n throw error\n }\n }\n\n /**\n * Find and execute workflows triggered by a collection operation\n */\n async executeTriggeredWorkflows(\n collection: string,\n operation: 'create' | 'delete' | 'read' | 'update',\n doc: unknown,\n previousDoc: unknown,\n req: PayloadRequest\n ): Promise<void> {\n this.logger.info({\n collection,\n operation,\n docId: (doc as any)?.id\n }, 'executeTriggeredWorkflows called')\n \n try {\n // Find workflows with matching triggers\n const workflows = await this.payload.find({\n collection: 'workflows',\n depth: 2, // Include steps and triggers\n limit: 100,\n req\n })\n \n this.logger.info({\n workflowCount: workflows.docs.length\n }, 'Found workflows to check')\n\n for (const workflow of workflows.docs) {\n // Check if this workflow has a matching trigger\n const triggers = workflow.triggers as Array<{\n collection?: string\n collectionSlug?: string\n condition?: string\n operation: string\n type: string\n }>\n \n this.logger.debug({\n workflowId: workflow.id,\n workflowName: workflow.name,\n triggerCount: triggers?.length || 0,\n triggers: triggers?.map(t => ({\n type: t.type,\n collection: t.collection,\n collectionSlug: t.collectionSlug,\n operation: t.operation\n }))\n }, 'Checking workflow triggers')\n\n const matchingTriggers = triggers?.filter(trigger =>\n trigger.type === 'collection-trigger' &&\n (trigger.collection === collection || trigger.collectionSlug === collection) &&\n trigger.operation === operation\n ) || []\n \n this.logger.info({\n workflowId: workflow.id,\n workflowName: workflow.name,\n matchingTriggerCount: matchingTriggers.length,\n targetCollection: collection,\n targetOperation: operation\n }, 'Matching triggers found')\n\n for (const trigger of matchingTriggers) {\n this.logger.info({\n workflowId: workflow.id,\n workflowName: workflow.name,\n triggerDetails: {\n type: trigger.type,\n collection: trigger.collection,\n collectionSlug: trigger.collectionSlug,\n operation: trigger.operation,\n hasCondition: !!trigger.condition\n }\n }, 'Processing matching trigger - about to execute workflow')\n\n // Create execution context for condition evaluation\n const context: ExecutionContext = {\n steps: {},\n trigger: {\n type: 'collection',\n collection,\n doc,\n operation,\n previousDoc,\n req\n }\n }\n\n // Check trigger condition if present\n if (trigger.condition) {\n this.logger.debug({\n collection,\n operation,\n condition: trigger.condition,\n docId: (doc as any)?.id,\n docFields: doc ? Object.keys(doc) : [],\n previousDocId: (previousDoc as any)?.id,\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Evaluating collection trigger condition')\n\n const conditionMet = this.evaluateCondition(trigger.condition, context)\n\n if (!conditionMet) {\n this.logger.info({\n collection,\n condition: trigger.condition,\n operation,\n workflowId: workflow.id,\n workflowName: workflow.name,\n docSnapshot: JSON.stringify(doc).substring(0, 200)\n }, 'Trigger condition not met, skipping workflow')\n continue\n }\n\n this.logger.info({\n collection,\n condition: trigger.condition,\n operation,\n workflowId: workflow.id,\n workflowName: workflow.name,\n docSnapshot: JSON.stringify(doc).substring(0, 200)\n }, 'Trigger condition met')\n }\n\n this.logger.info({\n collection,\n operation,\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Triggering workflow')\n\n // Execute the workflow\n await this.execute(workflow as PayloadWorkflow, context, req)\n }\n }\n } catch (error) {\n this.logger.error({ error: error instanceof Error ? error.message : 'Unknown error' }, 'Workflow execution failed')\n this.logger.error({\n collection,\n error: error instanceof Error ? error.message : 'Unknown error',\n operation\n }, 'Failed to execute triggered workflows')\n }\n }\n}\n"],"names":["JSONPath","WorkflowExecutor","payload","logger","evaluateStepCondition","condition","context","evaluateCondition","executeStep","step","stepIndex","req","workflowRunId","stepName","name","info","hasStep","JSON","stringify","debug","availableSteps","Object","keys","steps","completedSteps","entries","filter","_","s","state","map","triggerType","trigger","type","conditionMet","contextSnapshot","stepOutputs","reduce","acc","hasOutput","output","triggerData","data","error","undefined","input","reason","skipped","updateWorkflowRunContext","taskSlug","resolvedInput","resolveStepInput","Error","hasInput","hasReq","job","jobs","queue","task","run","limit","completedJob","findByID","id","collection","taskStatus","totalTried","isComplete","complete","hasError","errorMessage","log","length","latestLog","message","result","updateError","resolveExecutionOrder","stepMap","Map","dependencyGraph","indegree","indexOf","dependencies","set","executionBatches","processed","Set","size","currentBatch","inDegree","has","get","push","add","otherStepName","includes","config","resolved","configKeys","contextSteps","key","value","startsWith","jsonPath","hasTriggerData","hasTriggerDoc","doc","json","path","wrap","substring","resultType","Array","isArray","warn","nestedKeys","resolvedKeys","originalKeys","safeSerialize","obj","seen","WeakSet","serialize","val","serializeContext","operation","previousDoc","triggeredAt","user","update","contextKeys","triggerDoc","comparisonMatch","match","leftExpr","operator","rightExpr","leftValue","resolveJSONPathValue","trim","rightValue","parseConditionValue","leftType","rightType","Number","resultLength","finalResult","Boolean","originalResult","errorStack","stack","expr","endsWith","slice","test","execute","workflow","workflowId","workflowName","contextSummary","triggerCollection","triggerOperation","hasDoc","userEmail","email","workflowRun","create","startedAt","Date","toISOString","status","triggeredBy","workflowVersion","batchSizes","batch","totalBatches","batchIndex","stepCount","stepNames","batchPromises","Promise","all","completedAt","runId","executeTriggeredWorkflows","docId","workflows","find","depth","workflowCount","docs","triggers","triggerCount","t","collectionSlug","matchingTriggers","matchingTriggerCount","targetCollection","targetOperation","triggerDetails","hasCondition","docFields","previousDocId","docSnapshot"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1 +1,2 @@
1
- export type { CustomTriggerOptions, TriggerResult, ExecutionContext, Workflow, WorkflowStep, WorkflowTrigger, WorkflowsPluginConfig } from './types/index.js';
1
+ export type { CustomTriggerOptions, TriggerResult, ExecutionContext, WorkflowsPluginConfig } from './types/index.js';
2
+ export type { PayloadWorkflow as Workflow, WorkflowStep, WorkflowTrigger } from './core/workflow-executor.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Main export contains only types and client-safe utilities\n// Server-side functions are exported via '@xtr-dev/payload-automation/server'\n\n// Pure types only - completely safe for client bundling\nexport type {\n CustomTriggerOptions,\n TriggerResult,\n ExecutionContext,\n Workflow,\n WorkflowStep,\n WorkflowTrigger,\n WorkflowsPluginConfig\n} from './types/index.js'\n\n// Server-side functions are NOT re-exported here to avoid bundling issues\n// Import server-side functions from the /server export instead\n\n// Server functions and plugin should be imported from '/server':\n// import { workflowsPlugin } from '@xtr-dev/payload-automation/server'\n// UI components should be imported from '/client':\n// import { TriggerWorkflowButton } from '@xtr-dev/payload-automation/client'\n"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,8EAA8E;AAE9E,wDAAwD;AACxD,WAQyB,CAEzB,0EAA0E;CAC1E,+DAA+D;CAE/D,iEAAiE;CACjE,uEAAuE;CACvE,mDAAmD;CACnD,6EAA6E"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Main export contains only types and client-safe utilities\n// Server-side functions are exported via '@xtr-dev/payload-automation/server'\n\n// Pure types only - completely safe for client bundling\nexport type {\n CustomTriggerOptions,\n TriggerResult,\n ExecutionContext,\n WorkflowsPluginConfig\n} from './types/index.js'\n\nexport type {\n PayloadWorkflow as Workflow,\n WorkflowStep,\n WorkflowTrigger\n} from './core/workflow-executor.js'\n\n// Server-side functions are NOT re-exported here to avoid bundling issues\n// Import server-side functions from the /server export instead\n\n// Server functions and plugin should be imported from '/server':\n// import { workflowsPlugin } from '@xtr-dev/payload-automation/server'\n// UI components should be imported from '/client':\n// import { TriggerWorkflowButton } from '@xtr-dev/payload-automation/client'\n"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,8EAA8E;AAE9E,wDAAwD;AAQxD,WAIoC,CAEpC,0EAA0E;CAC1E,+DAA+D;CAE/D,iEAAiE;CACjE,uEAAuE;CACvE,mDAAmD;CACnD,6EAA6E"}
@@ -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 Workflow, 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 Workflow, 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 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 +1 @@
1
- {"version":3,"sources":["../../src/plugin/init-global-hooks.ts"],"sourcesContent":["import type { Payload, PayloadRequest } from \"payload\"\nimport type { Logger } from \"pino\"\n\nimport type { WorkflowExecutor, Workflow } from \"../core/workflow-executor.js\"\n\nexport function initGlobalHooks(payload: Payload, logger: Payload['logger'], executor: WorkflowExecutor) {\n // Get all globals from the config\n const globals = payload.config.globals || []\n\n for (const globalConfig of globals) {\n const globalSlug = globalConfig.slug\n\n // Add afterChange hook to global\n if (!globalConfig.hooks) {\n globalConfig.hooks = {\n afterChange: [],\n afterRead: [],\n beforeChange: [],\n beforeRead: [],\n beforeValidate: []\n }\n }\n\n if (!globalConfig.hooks.afterChange) {\n globalConfig.hooks.afterChange = []\n }\n\n globalConfig.hooks.afterChange.push(async (change) => {\n logger.debug({\n global: globalSlug,\n operation: 'update'\n }, 'Global hook triggered')\n\n // Execute workflows for this global trigger\n await executeTriggeredGlobalWorkflows(\n globalSlug,\n 'update',\n change.doc,\n change.previousDoc,\n change.req,\n payload,\n logger,\n executor\n )\n })\n\n logger.info({ globalSlug }, 'Global hooks registered')\n }\n}\n\nasync function executeTriggeredGlobalWorkflows(\n globalSlug: string,\n operation: 'update',\n doc: Record<string, any>,\n previousDoc: Record<string, any>,\n req: PayloadRequest,\n payload: Payload,\n logger: Payload['logger'],\n executor: WorkflowExecutor\n): Promise<void> {\n try {\n // Find workflows with matching global triggers\n const workflows = await payload.find({\n collection: 'workflows',\n depth: 2,\n limit: 100,\n req,\n where: {\n 'triggers.global': {\n equals: globalSlug\n },\n 'triggers.globalOperation': {\n equals: operation\n },\n 'triggers.type': {\n equals: 'global-trigger'\n }\n }\n })\n\n for (const workflow of workflows.docs) {\n logger.info({\n globalSlug,\n operation,\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Triggering global workflow')\n\n // Create execution context\n const context = {\n steps: {},\n trigger: {\n type: 'global',\n doc,\n global: globalSlug,\n operation,\n previousDoc,\n req\n }\n }\n\n // Execute the workflow\n await executor.execute(workflow as Workflow, context, req)\n }\n } catch (error) {\n logger.error({\n error: error instanceof Error ? error.message : 'Unknown error',\n globalSlug,\n operation\n }, 'Failed to execute triggered global workflows')\n }\n}\n"],"names":["initGlobalHooks","payload","logger","executor","globals","config","globalConfig","globalSlug","slug","hooks","afterChange","afterRead","beforeChange","beforeRead","beforeValidate","push","change","debug","global","operation","executeTriggeredGlobalWorkflows","doc","previousDoc","req","info","workflows","find","collection","depth","limit","where","equals","workflow","docs","workflowId","id","workflowName","name","context","steps","trigger","type","execute","error","Error","message"],"mappings":"AAKA,OAAO,SAASA,gBAAgBC,OAAgB,EAAEC,MAAyB,EAAEC,QAA0B;IACrG,kCAAkC;IAClC,MAAMC,UAAUH,QAAQI,MAAM,CAACD,OAAO,IAAI,EAAE;IAE5C,KAAK,MAAME,gBAAgBF,QAAS;QAClC,MAAMG,aAAaD,aAAaE,IAAI;QAEpC,iCAAiC;QACjC,IAAI,CAACF,aAAaG,KAAK,EAAE;YACvBH,aAAaG,KAAK,GAAG;gBACnBC,aAAa,EAAE;gBACfC,WAAW,EAAE;gBACbC,cAAc,EAAE;gBAChBC,YAAY,EAAE;gBACdC,gBAAgB,EAAE;YACpB;QACF;QAEA,IAAI,CAACR,aAAaG,KAAK,CAACC,WAAW,EAAE;YACnCJ,aAAaG,KAAK,CAACC,WAAW,GAAG,EAAE;QACrC;QAEAJ,aAAaG,KAAK,CAACC,WAAW,CAACK,IAAI,CAAC,OAAOC;YACzCd,OAAOe,KAAK,CAAC;gBACXC,QAAQX;gBACRY,WAAW;YACb,GAAG;YAEH,4CAA4C;YAC5C,MAAMC,gCACJb,YACA,UACAS,OAAOK,GAAG,EACVL,OAAOM,WAAW,EAClBN,OAAOO,GAAG,EACVtB,SACAC,QACAC;QAEJ;QAEAD,OAAOsB,IAAI,CAAC;YAAEjB;QAAW,GAAG;IAC9B;AACF;AAEA,eAAea,gCACbb,UAAkB,EAClBY,SAAmB,EACnBE,GAAwB,EACxBC,WAAgC,EAChCC,GAAmB,EACnBtB,OAAgB,EAChBC,MAAyB,EACzBC,QAA0B;IAE1B,IAAI;QACF,+CAA+C;QAC/C,MAAMsB,YAAY,MAAMxB,QAAQyB,IAAI,CAAC;YACnCC,YAAY;YACZC,OAAO;YACPC,OAAO;YACPN;YACAO,OAAO;gBACL,mBAAmB;oBACjBC,QAAQxB;gBACV;gBACA,4BAA4B;oBAC1BwB,QAAQZ;gBACV;gBACA,iBAAiB;oBACfY,QAAQ;gBACV;YACF;QACF;QAEA,KAAK,MAAMC,YAAYP,UAAUQ,IAAI,CAAE;YACrC/B,OAAOsB,IAAI,CAAC;gBACVjB;gBACAY;gBACAe,YAAYF,SAASG,EAAE;gBACvBC,cAAcJ,SAASK,IAAI;YAC7B,GAAG;YAEH,2BAA2B;YAC3B,MAAMC,UAAU;gBACdC,OAAO,CAAC;gBACRC,SAAS;oBACPC,MAAM;oBACNpB;oBACAH,QAAQX;oBACRY;oBACAG;oBACAC;gBACF;YACF;YAEA,uBAAuB;YACvB,MAAMpB,SAASuC,OAAO,CAACV,UAAsBM,SAASf;QACxD;IACF,EAAE,OAAOoB,OAAO;QACdzC,OAAOyC,KAAK,CAAC;YACXA,OAAOA,iBAAiBC,QAAQD,MAAME,OAAO,GAAG;YAChDtC;YACAY;QACF,GAAG;IACL;AACF"}
1
+ {"version":3,"sources":["../../src/plugin/init-global-hooks.ts"],"sourcesContent":["import type { Payload, PayloadRequest } from \"payload\"\nimport type { Logger } from \"pino\"\n\nimport type { WorkflowExecutor, PayloadWorkflow } from \"../core/workflow-executor.js\"\n\nexport function initGlobalHooks(payload: Payload, logger: Payload['logger'], executor: WorkflowExecutor) {\n // Get all globals from the config\n const globals = payload.config.globals || []\n\n for (const globalConfig of globals) {\n const globalSlug = globalConfig.slug\n\n // Add afterChange hook to global\n if (!globalConfig.hooks) {\n globalConfig.hooks = {\n afterChange: [],\n afterRead: [],\n beforeChange: [],\n beforeRead: [],\n beforeValidate: []\n }\n }\n\n if (!globalConfig.hooks.afterChange) {\n globalConfig.hooks.afterChange = []\n }\n\n globalConfig.hooks.afterChange.push(async (change) => {\n logger.debug({\n global: globalSlug,\n operation: 'update'\n }, 'Global hook triggered')\n\n // Execute workflows for this global trigger\n await executeTriggeredGlobalWorkflows(\n globalSlug,\n 'update',\n change.doc,\n change.previousDoc,\n change.req,\n payload,\n logger,\n executor\n )\n })\n\n logger.info({ globalSlug }, 'Global hooks registered')\n }\n}\n\nasync function executeTriggeredGlobalWorkflows(\n globalSlug: string,\n operation: 'update',\n doc: Record<string, any>,\n previousDoc: Record<string, any>,\n req: PayloadRequest,\n payload: Payload,\n logger: Payload['logger'],\n executor: WorkflowExecutor\n): Promise<void> {\n try {\n // Find workflows with matching global triggers\n const workflows = await payload.find({\n collection: 'workflows',\n depth: 2,\n limit: 100,\n req,\n where: {\n 'triggers.global': {\n equals: globalSlug\n },\n 'triggers.globalOperation': {\n equals: operation\n },\n 'triggers.type': {\n equals: 'global-trigger'\n }\n }\n })\n\n for (const workflow of workflows.docs) {\n logger.info({\n globalSlug,\n operation,\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Triggering global workflow')\n\n // Create execution context\n const context = {\n steps: {},\n trigger: {\n type: 'global',\n doc,\n global: globalSlug,\n operation,\n previousDoc,\n req\n }\n }\n\n // Execute the workflow\n await executor.execute(workflow as PayloadWorkflow, context, req)\n }\n } catch (error) {\n logger.error({\n error: error instanceof Error ? error.message : 'Unknown error',\n globalSlug,\n operation\n }, 'Failed to execute triggered global workflows')\n }\n}\n"],"names":["initGlobalHooks","payload","logger","executor","globals","config","globalConfig","globalSlug","slug","hooks","afterChange","afterRead","beforeChange","beforeRead","beforeValidate","push","change","debug","global","operation","executeTriggeredGlobalWorkflows","doc","previousDoc","req","info","workflows","find","collection","depth","limit","where","equals","workflow","docs","workflowId","id","workflowName","name","context","steps","trigger","type","execute","error","Error","message"],"mappings":"AAKA,OAAO,SAASA,gBAAgBC,OAAgB,EAAEC,MAAyB,EAAEC,QAA0B;IACrG,kCAAkC;IAClC,MAAMC,UAAUH,QAAQI,MAAM,CAACD,OAAO,IAAI,EAAE;IAE5C,KAAK,MAAME,gBAAgBF,QAAS;QAClC,MAAMG,aAAaD,aAAaE,IAAI;QAEpC,iCAAiC;QACjC,IAAI,CAACF,aAAaG,KAAK,EAAE;YACvBH,aAAaG,KAAK,GAAG;gBACnBC,aAAa,EAAE;gBACfC,WAAW,EAAE;gBACbC,cAAc,EAAE;gBAChBC,YAAY,EAAE;gBACdC,gBAAgB,EAAE;YACpB;QACF;QAEA,IAAI,CAACR,aAAaG,KAAK,CAACC,WAAW,EAAE;YACnCJ,aAAaG,KAAK,CAACC,WAAW,GAAG,EAAE;QACrC;QAEAJ,aAAaG,KAAK,CAACC,WAAW,CAACK,IAAI,CAAC,OAAOC;YACzCd,OAAOe,KAAK,CAAC;gBACXC,QAAQX;gBACRY,WAAW;YACb,GAAG;YAEH,4CAA4C;YAC5C,MAAMC,gCACJb,YACA,UACAS,OAAOK,GAAG,EACVL,OAAOM,WAAW,EAClBN,OAAOO,GAAG,EACVtB,SACAC,QACAC;QAEJ;QAEAD,OAAOsB,IAAI,CAAC;YAAEjB;QAAW,GAAG;IAC9B;AACF;AAEA,eAAea,gCACbb,UAAkB,EAClBY,SAAmB,EACnBE,GAAwB,EACxBC,WAAgC,EAChCC,GAAmB,EACnBtB,OAAgB,EAChBC,MAAyB,EACzBC,QAA0B;IAE1B,IAAI;QACF,+CAA+C;QAC/C,MAAMsB,YAAY,MAAMxB,QAAQyB,IAAI,CAAC;YACnCC,YAAY;YACZC,OAAO;YACPC,OAAO;YACPN;YACAO,OAAO;gBACL,mBAAmB;oBACjBC,QAAQxB;gBACV;gBACA,4BAA4B;oBAC1BwB,QAAQZ;gBACV;gBACA,iBAAiB;oBACfY,QAAQ;gBACV;YACF;QACF;QAEA,KAAK,MAAMC,YAAYP,UAAUQ,IAAI,CAAE;YACrC/B,OAAOsB,IAAI,CAAC;gBACVjB;gBACAY;gBACAe,YAAYF,SAASG,EAAE;gBACvBC,cAAcJ,SAASK,IAAI;YAC7B,GAAG;YAEH,2BAA2B;YAC3B,MAAMC,UAAU;gBACdC,OAAO,CAAC;gBACRC,SAAS;oBACPC,MAAM;oBACNpB;oBACAH,QAAQX;oBACRY;oBACAG;oBACAC;gBACF;YACF;YAEA,uBAAuB;YACvB,MAAMpB,SAASuC,OAAO,CAACV,UAA6BM,SAASf;QAC/D;IACF,EAAE,OAAOoB,OAAO;QACdzC,OAAOyC,KAAK,CAAC;YACXA,OAAOA,iBAAiBC,QAAQD,MAAME,OAAO,GAAG;YAChDtC;YACAY;QACF,GAAG;IACL;AACF"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/plugin/init-webhook.ts"],"sourcesContent":["import type {Config, PayloadRequest} from 'payload'\n\nimport {type Workflow, 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 Workflow, 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 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":"AAEA,SAA8BA,gBAAgB,QAAO,+BAA8B;AACnF,SAAQC,eAAe,EAAEC,gBAAgB,QAAO,cAAa;AAE7D,OAAO,SAASC,oBAAoBC,MAAc,EAAEC,gBAAgB,SAAS;IAC3E,MAAMC,SAASL;IACf,wCAAwC;IACxC,MAAMM,mBAAmBF,cAAcG,UAAU,CAAC,OAAOH,gBAAgB,CAAC,CAAC,EAAEA,eAAe;IAC5FC,OAAOG,KAAK,CAAC,CAAC,+CAA+C,EAAEF,kBAAkB;IACjFD,OAAOG,KAAK,CAAC,oCAAoCL,OAAOM,SAAS,EAAEC,UAAU;IAE7E,0BAA0B;IAC1B,MAAMC,kBAAkB;QACtBC,SAAS,OAAOC;YACd,MAAM,EAACC,IAAI,EAAC,GAAGD,IAAIE,WAAW;YAC9B,MAAMC,cAAcH,IAAII,IAAI,IAAI,CAAC;YAEjCZ,OAAOG,KAAK,CAAC,4CAA4CM;YAEzD,IAAI;gBACF,gDAAgD;gBAChD,MAAMI,YAAY,MAAML,IAAIM,OAAO,CAACC,IAAI,CAAC;oBACvCC,YAAY;oBACZC,OAAO;oBACPC,OAAO;oBACPV;oBACAW,OAAO;wBACL,iBAAiB;4BACfC,QAAQ;wBACV;wBACA,wBAAwB;4BACtBA,QAAQX;wBACV;oBACF;gBACF;gBAEA,IAAII,UAAUQ,IAAI,CAAChB,MAAM,KAAK,GAAG;oBAC/B,OAAO,IAAIiB,SACTC,KAAKC,SAAS,CAAC;wBAACC,OAAO;oBAA0C,IACjE;wBACEC,SAAS;4BAAC,gBAAgB;wBAAkB;wBAC5CC,QAAQ;oBACV;gBAEJ;gBAEA,8CAA8C;gBAC9C,MAAM3B,SAASJ,iBAAiBY,IAAIM,OAAO;gBAC3C,MAAMc,WAAW,IAAIlC,iBAAiBc,IAAIM,OAAO,EAAEd;gBAEnD,MAAM6B,oBAAoBhB,UAAUQ,IAAI,CAACS,GAAG,CAAC,OAAOC;oBAClD,IAAI;wBACF,mDAAmD;wBACnD,MAAMC,UAAU;4BACdC,OAAO,CAAC;4BACRC,SAAS;gCACPC,MAAM;gCACNC,MAAMzB;gCACNe,SAASW,OAAOC,WAAW,CAAC9B,IAAIkB,OAAO,EAAEa,aAAa,EAAE;gCACxD9B;gCACAD;4BACF;wBACF;wBAEA,+DAA+D;wBAC/D,MAAMgC,WAAWT,SAASS,QAAQ;wBAMlC,MAAMC,kBAAkBD,UAAUzB,KAAKmB,CAAAA,UACrCA,QAAQC,IAAI,KAAK,qBACjBD,QAAQQ,WAAW,KAAKjC;wBAG1B,qCAAqC;wBACrC,IAAIgC,iBAAiBE,WAAW;4BAC9B3C,OAAOG,KAAK,CAAC;gCACXwC,WAAWF,gBAAgBE,SAAS;gCACpClC;gCACAE,aAAaY,KAAKC,SAAS,CAACb,aAAaiC,SAAS,CAAC,GAAG;gCACtDlB,SAASW,OAAOQ,IAAI,CAACb,QAAQE,OAAO,CAACR,OAAO,IAAI,CAAC;gCACjDoB,YAAYf,SAASgB,EAAE;gCACvBC,cAAcjB,SAASkB,IAAI;4BAC7B,GAAG;4BAEH,MAAMC,eAAetB,SAASuB,iBAAiB,CAACV,gBAAgBE,SAAS,EAAEX;4BAE3E,IAAI,CAACkB,cAAc;gCACjBlD,OAAOoD,IAAI,CAAC;oCACVT,WAAWF,gBAAgBE,SAAS;oCACpClC;oCACA4C,qBAAqB9B,KAAKC,SAAS,CAACb,aAAaiC,SAAS,CAAC,GAAG;oCAC9DE,YAAYf,SAASgB,EAAE;oCACvBC,cAAcjB,SAASkB,IAAI;gCAC7B,GAAG;gCAEH,OAAO;oCAAEK,QAAQ;oCAAqB3B,QAAQ;oCAAWmB,YAAYf,SAASgB,EAAE;gCAAC;4BACnF;4BAEA/C,OAAOoD,IAAI,CAAC;gCACVT,WAAWF,gBAAgBE,SAAS;gCACpClC;gCACA4C,qBAAqB9B,KAAKC,SAAS,CAACb,aAAaiC,SAAS,CAAC,GAAG;gCAC9DE,YAAYf,SAASgB,EAAE;gCACvBC,cAAcjB,SAASkB,IAAI;4BAC7B,GAAG;wBACL;wBAEA,uBAAuB;wBACvB,MAAMrB,SAAS2B,OAAO,CAACxB,UAA6BC,SAASxB;wBAE7D,OAAO;4BAAEmB,QAAQ;4BAAamB,YAAYf,SAASgB,EAAE;wBAAC;oBACxD,EAAE,OAAOtB,OAAO;wBACd,OAAO;4BACLA,OAAOA,iBAAiB+B,QAAQ/B,MAAMgC,OAAO,GAAG;4BAChD9B,QAAQ;4BACRmB,YAAYf,SAASgB,EAAE;wBACzB;oBACF;gBACF;gBAEA,MAAMW,UAAU,MAAMC,QAAQC,UAAU,CAAC/B;gBACzC,MAAMgC,cAAcH,QAAQ5B,GAAG,CAAC,CAACgC,QAAQC;oBACvC,MAAMC,aAAa;wBAAElB,YAAYjC,UAAUQ,IAAI,CAAC0C,MAAM,CAAChB,EAAE;oBAAC;oBAC1D,IAAIe,OAAOnC,MAAM,KAAK,aAAa;wBACjC,OAAO;4BAAE,GAAGqC,UAAU;4BAAE,GAAGF,OAAOG,KAAK;wBAAC;oBAC1C,OAAO;wBACL,OAAO;4BAAE,GAAGD,UAAU;4BAAEvC,OAAOqC,OAAOR,MAAM;4BAAE3B,QAAQ;wBAAS;oBACjE;gBACF;gBAEA,OAAO,IAAIL,SACTC,KAAKC,SAAS,CAAC;oBACbiC,SAAS,CAAC,UAAU,EAAE5C,UAAUQ,IAAI,CAAChB,MAAM,CAAC,YAAY,CAAC;oBACzDqD,SAASG;gBACX,IACA;oBACEnC,SAAS;wBAAE,gBAAgB;oBAAmB;oBAC9CC,QAAQ;gBACV;YAGJ,EAAE,OAAOF,OAAO;gBACd,OAAO,IAAIH,SACTC,KAAKC,SAAS,CAAC;oBACb0C,SAASzC,iBAAiB+B,QAAQ/B,MAAMgC,OAAO,GAAG;oBAClDhC,OAAO;gBACT,IACA;oBACEC,SAAS;wBAAE,gBAAgB;oBAAmB;oBAC9CC,QAAQ;gBACV;YAEJ;QACF;QACAwC,QAAQ;QACR1D,MAAM,GAAGR,iBAAiB,MAAM,CAAC;IACnC;IAEA,mEAAmE;IACnE,MAAMmE,mBAAmBtE,OAAOM,SAAS,EAAEW,KAAKsD,CAAAA,WAC9CA,SAAS5D,IAAI,KAAKH,gBAAgBG,IAAI,IAAI4D,SAASF,MAAM,KAAK7D,gBAAgB6D,MAAM;IAGtF,IAAI,CAACC,kBAAkB;QACrB,uDAAuD;QACvDtE,OAAOM,SAAS,GAAG;eAAKN,OAAOM,SAAS,IAAI,EAAE;YAAGE;SAAgB;QACjEN,OAAOG,KAAK,CAAC,CAAC,gCAAgC,EAAEG,gBAAgBG,IAAI,EAAE;QACtET,OAAOG,KAAK,CAAC,gCAAgCL,OAAOM,SAAS,CAACC,MAAM;IACtE,OAAO;QACLL,OAAOG,KAAK,CAAC,CAAC,yCAAyC,EAAEG,gBAAgBG,IAAI,EAAE;IACjF;AACF"}
@@ -21,28 +21,6 @@ export interface ExecutionContext {
21
21
  payload: any;
22
22
  req: any;
23
23
  }
24
- export interface WorkflowStep {
25
- id: string;
26
- type: string;
27
- input: Record<string, any>;
28
- dependencies?: string[];
29
- }
30
- export interface WorkflowTrigger {
31
- type: 'collection' | 'global' | 'webhook' | 'cron' | 'manual';
32
- collection?: string;
33
- global?: string;
34
- event?: 'create' | 'update' | 'delete' | 'read';
35
- path?: string;
36
- cron?: string;
37
- }
38
- export interface Workflow {
39
- id: string;
40
- name: string;
41
- description?: string;
42
- active: boolean;
43
- triggers: WorkflowTrigger[];
44
- steps: WorkflowStep[];
45
- }
46
24
  export interface WorkflowsPluginConfig {
47
25
  collections?: string[];
48
26
  globals?: string[];
@@ -1,5 +1,8 @@
1
1
  // Pure type definitions for client-safe exports
2
2
  // This file contains NO runtime code and can be safely bundled
3
+ // NOTE: Workflow, WorkflowStep, and WorkflowTrigger types are now imported from the generated PayloadCMS types
4
+ // These interfaces have been removed to avoid duplication and inconsistencies
5
+ // Import them from 'payload' or the generated payload-types.ts file instead
3
6
  export { };
4
7
 
5
8
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/types/index.ts"],"sourcesContent":["// Pure type definitions for client-safe exports\n// This file contains NO runtime code and can be safely bundled\n\nexport interface CustomTriggerOptions {\n workflowId: string\n triggerData?: any\n req?: any // PayloadRequest type, but avoiding import to keep this client-safe\n}\n\nexport interface TriggerResult {\n success: boolean\n runId?: string\n error?: string\n}\n\nexport interface ExecutionContext {\n trigger: {\n type: string\n doc?: any\n data?: any\n }\n steps: Record<string, {\n output?: any\n state: 'pending' | 'running' | 'succeeded' | 'failed'\n }>\n payload: any // Payload instance\n req: any // PayloadRequest\n}\n\nexport interface WorkflowStep {\n id: string\n type: string\n input: Record<string, any>\n dependencies?: string[]\n}\n\nexport interface WorkflowTrigger {\n type: 'collection' | 'global' | 'webhook' | 'cron' | 'manual'\n collection?: string\n global?: string\n event?: 'create' | 'update' | 'delete' | 'read'\n path?: string\n cron?: string\n}\n\nexport interface Workflow {\n id: string\n name: string\n description?: string\n active: boolean\n triggers: WorkflowTrigger[]\n steps: WorkflowStep[]\n}\n\nexport interface WorkflowsPluginConfig {\n collections?: string[]\n globals?: string[]\n logging?: {\n level?: 'debug' | 'info' | 'warn' | 'error'\n enabled?: boolean\n }\n}"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,+DAA+D;AAqD/D,WAOC"}
1
+ {"version":3,"sources":["../../src/types/index.ts"],"sourcesContent":["// Pure type definitions for client-safe exports\n// This file contains NO runtime code and can be safely bundled\n\nexport interface CustomTriggerOptions {\n workflowId: string\n triggerData?: any\n req?: any // PayloadRequest type, but avoiding import to keep this client-safe\n}\n\nexport interface TriggerResult {\n success: boolean\n runId?: string\n error?: string\n}\n\nexport interface ExecutionContext {\n trigger: {\n type: string\n doc?: any\n data?: any\n }\n steps: Record<string, {\n output?: any\n state: 'pending' | 'running' | 'succeeded' | 'failed'\n }>\n payload: any // Payload instance\n req: any // PayloadRequest\n}\n\n// NOTE: Workflow, WorkflowStep, and WorkflowTrigger types are now imported from the generated PayloadCMS types\n// These interfaces have been removed to avoid duplication and inconsistencies\n// Import them from 'payload' or the generated payload-types.ts file instead\n\nexport interface WorkflowsPluginConfig {\n collections?: string[]\n globals?: string[]\n logging?: {\n level?: 'debug' | 'info' | 'warn' | 'error'\n enabled?: boolean\n }\n}"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,+DAA+D;AA4B/D,+GAA+G;AAC/G,8EAA8E;AAC9E,4EAA4E;AAE5E,WAOC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xtr-dev/payload-automation",
3
- "version": "0.0.13",
3
+ "version": "0.0.15",
4
4
  "description": "PayloadCMS Automation Plugin - Comprehensive workflow automation system with visual workflow building, execution tracking, and step types",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -85,6 +85,7 @@
85
85
  "react-dom": "19.1.0",
86
86
  "rimraf": "3.0.2",
87
87
  "sharp": "0.34.3",
88
+ "tsx": "^4.20.5",
88
89
  "typescript": "5.7.3",
89
90
  "vitest": "^3.1.2"
90
91
  },