@open-mercato/core 0.6.5-develop.4516.1.88e6ab71a9 → 0.6.5-develop.4534.1.b459babe6d

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.
Files changed (102) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/dist/generated/entities/step_instance/index.js +2 -0
  3. package/dist/generated/entities/step_instance/index.js.map +2 -2
  4. package/dist/generated/entities/user_task/index.js +2 -0
  5. package/dist/generated/entities/user_task/index.js.map +2 -2
  6. package/dist/generated/entities/workflow_branch_instance/index.js +39 -0
  7. package/dist/generated/entities/workflow_branch_instance/index.js.map +7 -0
  8. package/dist/generated/entities/workflow_event/index.js +2 -0
  9. package/dist/generated/entities/workflow_event/index.js.map +2 -2
  10. package/dist/generated/entities/workflow_instance/index.js +2 -0
  11. package/dist/generated/entities/workflow_instance/index.js.map +2 -2
  12. package/dist/generated/entities.ids.generated.js +1 -0
  13. package/dist/generated/entities.ids.generated.js.map +2 -2
  14. package/dist/generated/entity-fields-registry.js +24 -0
  15. package/dist/generated/entity-fields-registry.js.map +2 -2
  16. package/dist/modules/progress/api/jobs/[id]/route.js +7 -1
  17. package/dist/modules/progress/api/jobs/[id]/route.js.map +2 -2
  18. package/dist/modules/shipping_carriers/api/cancel/route.js +2 -2
  19. package/dist/modules/shipping_carriers/api/cancel/route.js.map +2 -2
  20. package/dist/modules/shipping_carriers/lib/status-sync.js +8 -1
  21. package/dist/modules/shipping_carriers/lib/status-sync.js.map +2 -2
  22. package/dist/modules/workflows/components/NodeEditDialog.js +3 -1
  23. package/dist/modules/workflows/components/NodeEditDialog.js.map +2 -2
  24. package/dist/modules/workflows/components/WorkflowGraphImpl.js +4 -2
  25. package/dist/modules/workflows/components/WorkflowGraphImpl.js.map +2 -2
  26. package/dist/modules/workflows/components/nodes/ParallelForkNode.js +49 -0
  27. package/dist/modules/workflows/components/nodes/ParallelForkNode.js.map +7 -0
  28. package/dist/modules/workflows/components/nodes/ParallelJoinNode.js +49 -0
  29. package/dist/modules/workflows/components/nodes/ParallelJoinNode.js.map +7 -0
  30. package/dist/modules/workflows/components/nodes/index.js +4 -0
  31. package/dist/modules/workflows/components/nodes/index.js.map +2 -2
  32. package/dist/modules/workflows/data/entities.js +81 -0
  33. package/dist/modules/workflows/data/entities.js.map +2 -2
  34. package/dist/modules/workflows/data/validators.js +146 -1
  35. package/dist/modules/workflows/data/validators.js.map +2 -2
  36. package/dist/modules/workflows/events.js +7 -1
  37. package/dist/modules/workflows/events.js.map +2 -2
  38. package/dist/modules/workflows/lib/activity-executor.js +4 -2
  39. package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
  40. package/dist/modules/workflows/lib/activity-queue-types.js.map +2 -2
  41. package/dist/modules/workflows/lib/event-logger.js +2 -0
  42. package/dist/modules/workflows/lib/event-logger.js.map +2 -2
  43. package/dist/modules/workflows/lib/execution-token.js +98 -0
  44. package/dist/modules/workflows/lib/execution-token.js.map +7 -0
  45. package/dist/modules/workflows/lib/node-type-icons.js +14 -5
  46. package/dist/modules/workflows/lib/node-type-icons.js.map +2 -2
  47. package/dist/modules/workflows/lib/parallel-handler.js +364 -0
  48. package/dist/modules/workflows/lib/parallel-handler.js.map +7 -0
  49. package/dist/modules/workflows/lib/signal-handler.js +63 -1
  50. package/dist/modules/workflows/lib/signal-handler.js.map +2 -2
  51. package/dist/modules/workflows/lib/step-handler.js +74 -30
  52. package/dist/modules/workflows/lib/step-handler.js.map +2 -2
  53. package/dist/modules/workflows/lib/task-handler.js +26 -0
  54. package/dist/modules/workflows/lib/task-handler.js.map +2 -2
  55. package/dist/modules/workflows/lib/timer-handler.js +26 -1
  56. package/dist/modules/workflows/lib/timer-handler.js.map +2 -2
  57. package/dist/modules/workflows/lib/transition-handler.js +33 -21
  58. package/dist/modules/workflows/lib/transition-handler.js.map +2 -2
  59. package/dist/modules/workflows/lib/workflow-executor.js +39 -1
  60. package/dist/modules/workflows/lib/workflow-executor.js.map +2 -2
  61. package/dist/modules/workflows/migrations/Migration20260602120000.js +24 -0
  62. package/dist/modules/workflows/migrations/Migration20260602120000.js.map +7 -0
  63. package/dist/modules/workflows/workers/workflow-activities.worker.js +8 -4
  64. package/dist/modules/workflows/workers/workflow-activities.worker.js.map +2 -2
  65. package/generated/entities/step_instance/index.ts +1 -0
  66. package/generated/entities/user_task/index.ts +1 -0
  67. package/generated/entities/workflow_branch_instance/index.ts +18 -0
  68. package/generated/entities/workflow_event/index.ts +1 -0
  69. package/generated/entities/workflow_instance/index.ts +1 -0
  70. package/generated/entities.ids.generated.ts +1 -0
  71. package/generated/entity-fields-registry.ts +24 -0
  72. package/package.json +7 -7
  73. package/src/modules/progress/api/jobs/[id]/route.ts +7 -0
  74. package/src/modules/shipping_carriers/api/cancel/route.ts +2 -2
  75. package/src/modules/shipping_carriers/lib/status-sync.ts +19 -0
  76. package/src/modules/workflows/components/NodeEditDialog.tsx +2 -0
  77. package/src/modules/workflows/components/WorkflowGraphImpl.tsx +3 -1
  78. package/src/modules/workflows/components/nodes/ParallelForkNode.tsx +66 -0
  79. package/src/modules/workflows/components/nodes/ParallelJoinNode.tsx +66 -0
  80. package/src/modules/workflows/components/nodes/index.ts +6 -0
  81. package/src/modules/workflows/data/entities.ts +109 -0
  82. package/src/modules/workflows/data/validators.ts +223 -0
  83. package/src/modules/workflows/events.ts +7 -0
  84. package/src/modules/workflows/i18n/de.json +12 -0
  85. package/src/modules/workflows/i18n/en.json +12 -0
  86. package/src/modules/workflows/i18n/es.json +12 -0
  87. package/src/modules/workflows/i18n/pl.json +12 -0
  88. package/src/modules/workflows/lib/activity-executor.ts +8 -2
  89. package/src/modules/workflows/lib/activity-queue-types.ts +3 -0
  90. package/src/modules/workflows/lib/event-logger.ts +3 -0
  91. package/src/modules/workflows/lib/execution-token.ts +166 -0
  92. package/src/modules/workflows/lib/node-type-icons.ts +11 -2
  93. package/src/modules/workflows/lib/parallel-handler.ts +575 -0
  94. package/src/modules/workflows/lib/signal-handler.ts +72 -1
  95. package/src/modules/workflows/lib/step-handler.ts +94 -34
  96. package/src/modules/workflows/lib/task-handler.ts +32 -0
  97. package/src/modules/workflows/lib/timer-handler.ts +30 -1
  98. package/src/modules/workflows/lib/transition-handler.ts +56 -24
  99. package/src/modules/workflows/lib/workflow-executor.ts +53 -1
  100. package/src/modules/workflows/migrations/.snapshot-open-mercato.json +263 -0
  101. package/src/modules/workflows/migrations/Migration20260602120000.ts +25 -0
  102. package/src/modules/workflows/workers/workflow-activities.worker.ts +9 -4
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/workflows/lib/timer-handler.ts"],
4
- "sourcesContent": ["/**\n * Timer Handler Service\n *\n * Fires timers for WAIT_FOR_TIMER steps: resumes a paused workflow instance\n * when its scheduled timer job is processed by the activity worker.\n */\n\nimport { EntityManager } from '@mikro-orm/core'\nimport type { EntityManager as PostgreSqlEntityManager } from '@mikro-orm/postgresql'\nimport type { AwilixContainer } from 'awilix'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { WorkflowInstance, WorkflowDefinition, StepInstance } from '../data/entities'\nimport type * as eventLoggerModule from './event-logger'\nimport type * as stepHandlerModule from './step-handler'\nimport type * as transitionHandlerModule from './transition-handler'\nimport type * as workflowExecutorModule from './workflow-executor'\n\nexport interface FireTimerOptions {\n instanceId: string\n stepInstanceId?: string\n userId?: string\n tenantId: string\n organizationId: string\n}\n\nexport class TimerError extends Error {\n constructor(\n message: string,\n public code: string,\n public details?: any\n ) {\n super(message)\n this.name = 'TimerError'\n }\n}\n\n/**\n * Fire a timer and resume workflow execution.\n *\n * Mirrors `sendSignal` from signal-handler.ts \u2014 verifies the instance is\n * paused at a WAIT_FOR_TIMER step, logs TIMER_FIRED, exits the step, then\n * executes auto transitions and resumes the workflow.\n */\nexport async function fireTimer(\n em: EntityManager,\n container: AwilixContainer,\n options: FireTimerOptions\n): Promise<void> {\n const { instanceId, stepInstanceId, userId, tenantId, organizationId } = options\n\n const eventLogger = container.resolve<typeof eventLoggerModule>('eventLogger')\n const stepHandler = container.resolve<typeof stepHandlerModule>('stepHandler')\n const transitionHandler = container.resolve<typeof transitionHandlerModule>('transitionHandler')\n const workflowExecutor = container.resolve<typeof workflowExecutorModule>('workflowExecutor')\n\n const instance = await findOneWithDecryption(\n em as PostgreSqlEntityManager,\n WorkflowInstance,\n {\n id: instanceId,\n tenantId,\n organizationId,\n },\n undefined,\n { tenantId, organizationId },\n )\n\n if (!instance) {\n throw new TimerError(\n 'Workflow instance not found',\n 'INSTANCE_NOT_FOUND',\n { instanceId }\n )\n }\n\n if (instance.status !== 'PAUSED') {\n throw new TimerError(\n 'Workflow is not paused',\n 'WORKFLOW_NOT_PAUSED',\n { instanceId, status: instance.status }\n )\n }\n\n const definition = await findOneWithDecryption(\n em as PostgreSqlEntityManager,\n WorkflowDefinition,\n {\n id: instance.definitionId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n deletedAt: null,\n },\n undefined,\n { tenantId: instance.tenantId, organizationId: instance.organizationId },\n )\n if (!definition) {\n throw new TimerError(\n 'Workflow definition not found',\n 'DEFINITION_NOT_FOUND',\n { definitionId: instance.definitionId }\n )\n }\n\n const currentStep = definition.definition.steps.find(\n (s: any) => s.stepId === instance.currentStepId\n )\n\n if (!currentStep || currentStep.stepType !== 'WAIT_FOR_TIMER') {\n throw new TimerError(\n 'Workflow is not waiting for timer',\n 'NOT_WAITING_FOR_TIMER',\n { instanceId, currentStepId: instance.currentStepId }\n )\n }\n\n const now = new Date()\n instance.updatedAt = now\n\n await eventLogger.logWorkflowEvent(em, {\n workflowInstanceId: instance.id,\n stepInstanceId,\n eventType: 'TIMER_FIRED',\n eventData: {\n stepId: instance.currentStepId,\n firedAt: now.toISOString(),\n },\n userId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n const stepInstance = stepInstanceId\n ? await findOneWithDecryption(\n em as PostgreSqlEntityManager,\n StepInstance,\n {\n id: stepInstanceId,\n workflowInstanceId: instance.id,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n },\n undefined,\n { tenantId: instance.tenantId, organizationId: instance.organizationId },\n )\n : await findOneWithDecryption(\n em as PostgreSqlEntityManager,\n StepInstance,\n {\n workflowInstanceId: instance.id,\n stepId: instance.currentStepId,\n status: 'ACTIVE',\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n },\n undefined,\n { tenantId: instance.tenantId, organizationId: instance.organizationId },\n )\n\n if (stepInstance) {\n await stepHandler.exitStep(em, stepInstance, {\n firedAt: now.toISOString(),\n })\n }\n\n const autoTransitions = (definition.definition.transitions || []).filter(\n (t: any) => t.fromStepId === instance.currentStepId && t.trigger === 'auto'\n )\n\n if (autoTransitions.length === 0) {\n instance.status = 'RUNNING'\n await em.flush()\n return\n }\n\n const transitionContext = {\n workflowContext: instance.context,\n userId,\n }\n\n const validTransitions = await transitionHandler.findValidTransitions(\n em,\n instance,\n instance.currentStepId,\n transitionContext\n )\n\n const firstValidTransition = validTransitions.find((t) => t.isValid)\n\n if (!firstValidTransition || !firstValidTransition.transition) {\n instance.status = 'RUNNING'\n await em.flush()\n return\n }\n\n const transitionResult = await transitionHandler.executeTransition(\n em,\n container,\n instance,\n instance.currentStepId,\n firstValidTransition.transition.toStepId,\n transitionContext\n )\n\n if (!transitionResult.success) {\n throw new TimerError(\n 'Transition failed after timer fired',\n 'TRANSITION_FAILED',\n { error: transitionResult.error }\n )\n }\n\n await workflowExecutor.executeWorkflow(em, container, instance.id, { userId })\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Timer Handler Service\n *\n * Fires timers for WAIT_FOR_TIMER steps: resumes a paused workflow instance\n * when its scheduled timer job is processed by the activity worker.\n */\n\nimport { EntityManager } from '@mikro-orm/core'\nimport type { EntityManager as PostgreSqlEntityManager } from '@mikro-orm/postgresql'\nimport type { AwilixContainer } from 'awilix'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { WorkflowInstance, WorkflowDefinition, StepInstance } from '../data/entities'\nimport type * as eventLoggerModule from './event-logger'\nimport type * as stepHandlerModule from './step-handler'\nimport type * as transitionHandlerModule from './transition-handler'\nimport type * as workflowExecutorModule from './workflow-executor'\n\nexport interface FireTimerOptions {\n instanceId: string\n stepInstanceId?: string\n branchInstanceId?: string | null\n userId?: string\n tenantId: string\n organizationId: string\n}\n\nexport class TimerError extends Error {\n constructor(\n message: string,\n public code: string,\n public details?: any\n ) {\n super(message)\n this.name = 'TimerError'\n }\n}\n\n/**\n * Fire a timer and resume workflow execution.\n *\n * Mirrors `sendSignal` from signal-handler.ts \u2014 verifies the instance is\n * paused at a WAIT_FOR_TIMER step, logs TIMER_FIRED, exits the step, then\n * executes auto transitions and resumes the workflow.\n */\nexport async function fireTimer(\n em: EntityManager,\n container: AwilixContainer,\n options: FireTimerOptions\n): Promise<void> {\n const { instanceId, stepInstanceId, branchInstanceId, userId, tenantId, organizationId } = options\n\n const eventLogger = container.resolve<typeof eventLoggerModule>('eventLogger')\n const stepHandler = container.resolve<typeof stepHandlerModule>('stepHandler')\n const transitionHandler = container.resolve<typeof transitionHandlerModule>('transitionHandler')\n const workflowExecutor = container.resolve<typeof workflowExecutorModule>('workflowExecutor')\n\n // Branch-scoped timer: the instance is FORKED and the branch is PAUSED at the\n // WAIT_FOR_TIMER step. Resume just that branch, then drive the parallel loop.\n if (branchInstanceId) {\n await eventLogger.logWorkflowEvent(em, {\n workflowInstanceId: instanceId,\n stepInstanceId,\n branchInstanceId,\n eventType: 'TIMER_FIRED',\n eventData: { firedAt: new Date().toISOString(), branch: true },\n userId,\n tenantId,\n organizationId,\n })\n const { resumeBranch } = await import('./parallel-handler')\n const resumed = await resumeBranch(em, {\n instanceId,\n branchInstanceId,\n tenantId,\n organizationId,\n exitStepInstanceId: stepInstanceId,\n exitOutput: { firedAt: new Date().toISOString() },\n })\n if (resumed) {\n await workflowExecutor.executeWorkflow(em, container, instanceId, { userId })\n }\n return\n }\n\n const instance = await findOneWithDecryption(\n em as PostgreSqlEntityManager,\n WorkflowInstance,\n {\n id: instanceId,\n tenantId,\n organizationId,\n },\n undefined,\n { tenantId, organizationId },\n )\n\n if (!instance) {\n throw new TimerError(\n 'Workflow instance not found',\n 'INSTANCE_NOT_FOUND',\n { instanceId }\n )\n }\n\n if (instance.status !== 'PAUSED') {\n throw new TimerError(\n 'Workflow is not paused',\n 'WORKFLOW_NOT_PAUSED',\n { instanceId, status: instance.status }\n )\n }\n\n const definition = await findOneWithDecryption(\n em as PostgreSqlEntityManager,\n WorkflowDefinition,\n {\n id: instance.definitionId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n deletedAt: null,\n },\n undefined,\n { tenantId: instance.tenantId, organizationId: instance.organizationId },\n )\n if (!definition) {\n throw new TimerError(\n 'Workflow definition not found',\n 'DEFINITION_NOT_FOUND',\n { definitionId: instance.definitionId }\n )\n }\n\n const currentStep = definition.definition.steps.find(\n (s: any) => s.stepId === instance.currentStepId\n )\n\n if (!currentStep || currentStep.stepType !== 'WAIT_FOR_TIMER') {\n throw new TimerError(\n 'Workflow is not waiting for timer',\n 'NOT_WAITING_FOR_TIMER',\n { instanceId, currentStepId: instance.currentStepId }\n )\n }\n\n const now = new Date()\n instance.updatedAt = now\n\n await eventLogger.logWorkflowEvent(em, {\n workflowInstanceId: instance.id,\n stepInstanceId,\n eventType: 'TIMER_FIRED',\n eventData: {\n stepId: instance.currentStepId,\n firedAt: now.toISOString(),\n },\n userId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n const stepInstance = stepInstanceId\n ? await findOneWithDecryption(\n em as PostgreSqlEntityManager,\n StepInstance,\n {\n id: stepInstanceId,\n workflowInstanceId: instance.id,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n },\n undefined,\n { tenantId: instance.tenantId, organizationId: instance.organizationId },\n )\n : await findOneWithDecryption(\n em as PostgreSqlEntityManager,\n StepInstance,\n {\n workflowInstanceId: instance.id,\n stepId: instance.currentStepId,\n status: 'ACTIVE',\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n },\n undefined,\n { tenantId: instance.tenantId, organizationId: instance.organizationId },\n )\n\n if (stepInstance) {\n await stepHandler.exitStep(em, stepInstance, {\n firedAt: now.toISOString(),\n })\n }\n\n const autoTransitions = (definition.definition.transitions || []).filter(\n (t: any) => t.fromStepId === instance.currentStepId && t.trigger === 'auto'\n )\n\n if (autoTransitions.length === 0) {\n instance.status = 'RUNNING'\n await em.flush()\n return\n }\n\n const transitionContext = {\n workflowContext: instance.context,\n userId,\n }\n\n const validTransitions = await transitionHandler.findValidTransitions(\n em,\n instance,\n instance.currentStepId,\n transitionContext\n )\n\n const firstValidTransition = validTransitions.find((t) => t.isValid)\n\n if (!firstValidTransition || !firstValidTransition.transition) {\n instance.status = 'RUNNING'\n await em.flush()\n return\n }\n\n const transitionResult = await transitionHandler.executeTransition(\n em,\n container,\n instance,\n instance.currentStepId,\n firstValidTransition.transition.toStepId,\n transitionContext\n )\n\n if (!transitionResult.success) {\n throw new TimerError(\n 'Transition failed after timer fired',\n 'TRANSITION_FAILED',\n { error: transitionResult.error }\n )\n }\n\n await workflowExecutor.executeWorkflow(em, container, instance.id, { userId })\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -6,6 +6,17 @@ import * as ruleEvaluator from "../../business_rules/lib/rule-evaluator.js";
6
6
  import * as ruleEngine from "../../business_rules/lib/rule-engine.js";
7
7
  import * as activityExecutor from "./activity-executor.js";
8
8
  import * as stepHandler from "./step-handler.js";
9
+ import {
10
+ rootToken,
11
+ tokenBranchInstanceId,
12
+ tokenReadContext,
13
+ setTokenCurrentStepId,
14
+ applyTokenContextWrites,
15
+ mergeTokenContext,
16
+ setTokenWaitingForActivities,
17
+ setTokenPendingTransition,
18
+ touchToken
19
+ } from "./execution-token.js";
9
20
  class TransitionError extends Error {
10
21
  constructor(message, code, details) {
11
22
  super(message);
@@ -145,6 +156,12 @@ async function findValidTransitions(em, instance, fromStepId, context) {
145
156
  }
146
157
  }
147
158
  async function executeTransition(em, container, instance, fromStepId, toStepId, context) {
159
+ return executeTransitionForToken(em, container, rootToken(instance), fromStepId, toStepId, context);
160
+ }
161
+ async function executeTransitionForToken(em, container, token, fromStepId, toStepId, context) {
162
+ const instance = token.instance;
163
+ const branch = token.kind === "branch" ? token.branch : null;
164
+ const branchInstanceId = tokenBranchInstanceId(token);
148
165
  try {
149
166
  let eventBus = null;
150
167
  try {
@@ -210,9 +227,10 @@ async function executeTransition(em, container, instance, fromStepId, toStepId,
210
227
  const activityContext = {
211
228
  workflowInstance: instance,
212
229
  workflowContext: {
213
- ...instance.context,
230
+ ...tokenReadContext(token),
214
231
  ...context.workflowContext
215
232
  },
233
+ branchInstanceId,
216
234
  userId: context.userId
217
235
  };
218
236
  const results = await activityExecutor.executeActivities(
@@ -265,22 +283,19 @@ async function executeTransition(em, container, instance, fromStepId, toStepId,
265
283
  const hasAsyncActivities = activityResults.some((r) => r.async);
266
284
  if (hasAsyncActivities) {
267
285
  const pendingJobIds = activityResults.filter((a) => a.async && a.jobId).map((a) => ({ activityId: a.activityId, jobId: a.jobId }));
268
- instance.pendingTransition = {
286
+ setTokenPendingTransition(token, {
269
287
  toStepId,
270
288
  activityResults,
271
289
  timestamp: /* @__PURE__ */ new Date()
272
- };
273
- instance.context = {
274
- ...instance.context,
275
- ...context.workflowContext,
276
- ...activityOutputs,
277
- _pendingAsyncActivities: pendingJobIds
278
- };
279
- instance.status = "WAITING_FOR_ACTIVITIES";
280
- instance.updatedAt = /* @__PURE__ */ new Date();
290
+ });
291
+ applyTokenContextWrites(token, context.workflowContext, activityOutputs);
292
+ mergeTokenContext(token, { _pendingAsyncActivities: pendingJobIds });
293
+ setTokenWaitingForActivities(token);
294
+ touchToken(token, /* @__PURE__ */ new Date());
281
295
  await em.flush();
282
296
  await logTransitionEvent(em, {
283
297
  workflowInstanceId: instance.id,
298
+ branchInstanceId,
284
299
  eventType: "TRANSITION_PAUSED_FOR_ACTIVITIES",
285
300
  eventData: {
286
301
  fromStepId,
@@ -304,25 +319,21 @@ async function executeTransition(em, container, instance, fromStepId, toStepId,
304
319
  activitiesExecuted: activityResults
305
320
  };
306
321
  }
307
- instance.currentStepId = toStepId;
308
- instance.context = {
309
- ...instance.context,
310
- ...context.workflowContext,
311
- ...activityOutputs
312
- // Include activity outputs
313
- };
314
- instance.updatedAt = /* @__PURE__ */ new Date();
322
+ setTokenCurrentStepId(token, toStepId);
323
+ applyTokenContextWrites(token, context.workflowContext, activityOutputs);
324
+ touchToken(token, /* @__PURE__ */ new Date());
315
325
  await em.flush();
316
326
  const stepExecutionResult = await stepHandler.executeStep(
317
327
  em,
318
328
  instance,
319
329
  toStepId,
320
330
  {
321
- workflowContext: instance.context || {},
331
+ workflowContext: tokenReadContext(token),
322
332
  userId: context.userId,
323
333
  triggerData: context.triggerData
324
334
  },
325
- container
335
+ container,
336
+ branch
326
337
  );
327
338
  await em.flush();
328
339
  if (stepExecutionResult.status === "FAILED") {
@@ -624,6 +635,7 @@ export {
624
635
  TransitionError,
625
636
  evaluateTransition,
626
637
  executeTransition,
638
+ executeTransitionForToken,
627
639
  findValidTransitions
628
640
  };
629
641
  //# sourceMappingURL=transition-handler.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/workflows/lib/transition-handler.ts"],
4
- "sourcesContent": ["/**\n * Workflows Module - Transition Handler Service\n *\n * Handles workflow transitions between steps:\n * - Evaluating if a transition is valid (checking conditions)\n * - Executing transitions (moving from one step to another)\n * - Integrating with business rules engine for pre/post conditions\n * - Executing activities on transition\n *\n * Functional API (no classes) following Open Mercato conventions.\n */\n\nimport { EntityManager } from '@mikro-orm/core'\nimport type { AwilixContainer } from 'awilix'\nimport type { EventBus } from '@open-mercato/events'\nimport {\n WorkflowInstance,\n WorkflowDefinition,\n WorkflowEvent,\n} from '../data/entities'\nimport * as ruleEvaluator from '../../business_rules/lib/rule-evaluator'\nimport * as ruleEngine from '../../business_rules/lib/rule-engine'\nimport * as activityExecutor from './activity-executor'\nimport type { ActivityDefinition } from './activity-executor'\nimport * as stepHandler from './step-handler'\n\n// ============================================================================\n// Types and Interfaces\n// ============================================================================\n\nexport interface TransitionEvaluationContext {\n workflowContext: Record<string, any>\n userId?: string\n triggerData?: any\n}\n\nexport interface TransitionEvaluationResult {\n isValid: boolean\n transition?: any\n reason?: string\n failedConditions?: string[]\n evaluationTime?: number\n}\n\nexport interface TransitionExecutionContext {\n workflowContext: Record<string, any>\n userId?: string\n triggerData?: any\n}\n\nexport interface TransitionExecutionResult {\n success: boolean\n nextStepId?: string\n pausedForActivities?: boolean\n conditionsEvaluated?: {\n preConditions: boolean\n postConditions: boolean\n }\n activitiesExecuted?: activityExecutor.ActivityExecutionResult[]\n error?: string\n}\n\nexport class TransitionError extends Error {\n constructor(\n message: string,\n public code: string,\n public details?: any\n ) {\n super(message)\n this.name = 'TransitionError'\n }\n}\n\n// ============================================================================\n// Main Transition Functions\n// ============================================================================\n\n/**\n * Evaluate if a transition from current step to target step is valid\n *\n * Checks:\n * - Transition exists in workflow definition\n * - Pre-conditions pass (if any business rules defined)\n * - Transition condition evaluates to true (if specified)\n *\n * @param em - Entity manager\n * @param instance - Workflow instance\n * @param fromStepId - Current step ID\n * @param toStepId - Target step ID (optional - will auto-select if not provided)\n * @param context - Evaluation context\n * @returns Evaluation result with validity and reason\n */\nexport async function evaluateTransition(\n em: EntityManager,\n instance: WorkflowInstance,\n fromStepId: string,\n toStepId: string | undefined,\n context: TransitionEvaluationContext\n): Promise<TransitionEvaluationResult> {\n const startTime = Date.now()\n\n try {\n // Load workflow definition\n const definition = await em.findOne(WorkflowDefinition, {\n id: instance.definitionId,\n })\n\n if (!definition) {\n return {\n isValid: false,\n reason: `Workflow definition not found: ${instance.definitionId}`,\n evaluationTime: Date.now() - startTime,\n }\n }\n\n // Find transition\n const transitions = definition.definition.transitions || []\n let transition: any\n\n if (toStepId) {\n // Find specific transition\n transition = transitions.find(\n (t: any) => t.fromStepId === fromStepId && t.toStepId === toStepId\n )\n\n if (!transition) {\n return {\n isValid: false,\n reason: `No transition found from ${fromStepId} to ${toStepId}`,\n evaluationTime: Date.now() - startTime,\n }\n }\n } else {\n // Auto-select first valid transition\n const availableTransitions = transitions.filter(\n (t: any) => t.fromStepId === fromStepId\n )\n\n if (availableTransitions.length === 0) {\n return {\n isValid: false,\n reason: `No transitions available from step ${fromStepId}`,\n evaluationTime: Date.now() - startTime,\n }\n }\n\n // Evaluate each transition to find first valid one\n for (const t of availableTransitions) {\n const result = await evaluateTransitionConditions(\n em,\n instance,\n t,\n context\n )\n\n if (result.isValid) {\n transition = t\n break\n }\n }\n\n if (!transition) {\n return {\n isValid: false,\n reason: `No valid transitions found from step ${fromStepId}`,\n evaluationTime: Date.now() - startTime,\n }\n }\n }\n\n // Evaluate transition conditions (inline condition + business rules pre-conditions)\n const conditionResult = await evaluateTransitionConditions(\n em,\n instance,\n transition,\n context\n )\n\n return {\n ...conditionResult,\n transition,\n evaluationTime: Date.now() - startTime,\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n return {\n isValid: false,\n reason: `Transition evaluation error: ${errorMessage}`,\n evaluationTime: Date.now() - startTime,\n }\n }\n}\n\n/**\n * Find all valid transitions from current step\n *\n * This function evaluates both inline conditions AND preConditions (business rules)\n * to determine which transitions are truly valid. This is important for decision\n * branching where multiple transitions exist with different preConditions.\n *\n * @param em - Entity manager\n * @param instance - Workflow instance\n * @param fromStepId - Current step ID\n * @param context - Evaluation context\n * @returns Array of evaluation results for all transitions, sorted by priority (desc)\n */\nexport async function findValidTransitions(\n em: EntityManager,\n instance: WorkflowInstance,\n fromStepId: string,\n context: TransitionEvaluationContext\n): Promise<TransitionEvaluationResult[]> {\n try {\n // Load workflow definition\n const definition = await em.findOne(WorkflowDefinition, {\n id: instance.definitionId,\n })\n\n if (!definition) {\n return []\n }\n\n // Find all transitions from current step, sorted by priority (highest first)\n const transitions = (definition.definition.transitions || [])\n .filter((t: any) => t.fromStepId === fromStepId)\n .sort((a: any, b: any) => (b.priority || 0) - (a.priority || 0))\n\n // Evaluate each transition including preConditions\n const results: TransitionEvaluationResult[] = []\n\n for (const transition of transitions) {\n // First check inline condition\n const conditionResult = await evaluateTransition(\n em,\n instance,\n fromStepId,\n transition.toStepId,\n context\n )\n\n if (!conditionResult.isValid) {\n results.push(conditionResult)\n continue\n }\n\n // Also evaluate preConditions if they exist\n const preConditions = transition.preConditions || []\n if (preConditions.length > 0) {\n const preConditionsResult = await evaluatePreConditions(\n em,\n instance,\n transition,\n context as TransitionExecutionContext,\n null\n )\n\n if (!preConditionsResult.allowed) {\n // Transition is invalid due to preConditions\n const failedRules = preConditionsResult.executedRules\n .filter((r) => !r.conditionResult)\n .map((r) => r.rule.ruleId || r.rule.ruleName)\n\n results.push({\n isValid: false,\n transition,\n reason: `Pre-conditions failed: ${failedRules.join(', ')}`,\n failedConditions: failedRules,\n })\n continue\n }\n }\n\n // Transition is valid (both condition and preConditions passed)\n results.push({\n ...conditionResult,\n transition,\n })\n }\n\n return results\n } catch (error) {\n console.error('Error finding valid transitions:', error)\n return []\n }\n}\n\n/**\n * Execute a transition from one step to another\n *\n * This is the main entry point for transition execution. It:\n * 1. Validates the transition\n * 2. Evaluates pre-conditions\n * 3. Executes activities (if any)\n * 4. Updates workflow instance state (atomically with activity outputs)\n * 5. Evaluates post-conditions\n * 6. Logs transition event\n *\n * @param em - Entity manager\n * @param container - DI container (for activity execution)\n * @param instance - Workflow instance\n * @param fromStepId - Current step ID\n * @param toStepId - Target step ID\n * @param context - Execution context\n * @returns Execution result\n */\nexport async function executeTransition(\n em: EntityManager,\n container: AwilixContainer,\n instance: WorkflowInstance,\n fromStepId: string,\n toStepId: string,\n context: TransitionExecutionContext\n): Promise<TransitionExecutionResult> {\n try {\n let eventBus: Pick<EventBus, 'emitEvent'> | null = null\n try {\n eventBus = container.resolve('eventBus') as EventBus\n } catch {\n eventBus = null\n }\n\n // First, evaluate if transition is valid\n const evaluation = await evaluateTransition(\n em,\n instance,\n fromStepId,\n toStepId,\n context\n )\n\n if (!evaluation.isValid) {\n return {\n success: false,\n error: evaluation.reason || 'Transition validation failed',\n }\n }\n\n const transition = evaluation.transition!\n\n // Evaluate pre-conditions (business rules)\n const preConditionsResult = await evaluatePreConditions(\n em,\n instance,\n transition,\n context,\n eventBus\n )\n\n if (!preConditionsResult.allowed) {\n // Build detailed failure information\n const failedRules = preConditionsResult.executedRules\n .filter((r) => !r.conditionResult)\n .map((r) => ({\n ruleId: r.rule.ruleId,\n ruleName: r.rule.ruleName,\n error: r.error,\n }))\n\n const failedRulesDetails = failedRules.length > 0\n ? failedRules.map(r => `${r.ruleId}: ${r.error || 'condition failed'}`).join('; ')\n : preConditionsResult.errors?.join(', ') || 'Unknown pre-condition failure'\n\n await logTransitionEvent(em, {\n workflowInstanceId: instance.id,\n eventType: 'TRANSITION_REJECTED',\n eventData: {\n fromStepId,\n toStepId,\n transitionId: transition.transitionId || `${fromStepId}->${toStepId}`,\n reason: 'Pre-conditions failed',\n failedRules: failedRulesDetails,\n failedRulesDetail: failedRules,\n },\n userId: context.userId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n return {\n success: false,\n error: `Pre-conditions failed: ${failedRulesDetails}`,\n conditionsEvaluated: {\n preConditions: false,\n postConditions: false,\n },\n }\n }\n\n // Execute activities (if any)\n let activityOutputs: Record<string, any> = {}\n const activityResults: activityExecutor.ActivityExecutionResult[] = []\n\n if (transition.activities && transition.activities.length > 0) {\n const activityContext: activityExecutor.ActivityContext = {\n workflowInstance: instance,\n workflowContext: {\n ...instance.context,\n ...context.workflowContext,\n },\n userId: context.userId,\n }\n\n // Execute all activities\n const results = await activityExecutor.executeActivities(\n em,\n container,\n transition.activities as ActivityDefinition[],\n activityContext\n )\n\n activityResults.push(...results)\n\n // Check for failures\n const failedActivities = results.filter(r => !r.success)\n\n if (failedActivities.length > 0) {\n const continueOnFailure = transition.continueOnActivityFailure ?? false\n\n // Log activity failures\n await logTransitionEvent(em, {\n workflowInstanceId: instance.id,\n eventType: 'ACTIVITY_FAILED',\n eventData: {\n fromStepId,\n toStepId,\n transitionId: transition.transitionId || `${fromStepId}->${toStepId}`,\n failedActivities: failedActivities.map(f => ({\n activityType: f.activityType,\n activityName: f.activityName,\n error: f.error,\n retryCount: f.retryCount,\n })),\n continueOnFailure,\n },\n userId: context.userId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n if (!continueOnFailure) {\n return {\n success: false,\n error: `Activities failed: ${failedActivities.map(f => f.error).join(', ')}`,\n conditionsEvaluated: {\n preConditions: true,\n postConditions: false,\n },\n }\n }\n }\n\n // Collect activity outputs for context update\n results.forEach(result => {\n if (result.success && result.output) {\n const key = result.activityName || result.activityType\n activityOutputs[key] = result.output\n }\n })\n }\n\n // Check if any activities are async - if so, pause before executing step\n const hasAsyncActivities = activityResults.some(r => r.async)\n\n if (hasAsyncActivities) {\n const pendingJobIds = activityResults\n .filter(a => a.async && a.jobId)\n .map(a => ({ activityId: a.activityId, jobId: a.jobId }))\n\n // Store pending transition state\n instance.pendingTransition = {\n toStepId,\n activityResults,\n timestamp: new Date(),\n }\n\n // Store pending activities in context for tracking\n instance.context = {\n ...instance.context,\n ...context.workflowContext,\n ...activityOutputs,\n _pendingAsyncActivities: pendingJobIds,\n }\n\n // Set status to waiting\n instance.status = 'WAITING_FOR_ACTIVITIES'\n instance.updatedAt = new Date()\n await em.flush()\n\n // Log event\n await logTransitionEvent(em, {\n workflowInstanceId: instance.id,\n eventType: 'TRANSITION_PAUSED_FOR_ACTIVITIES',\n eventData: {\n fromStepId,\n toStepId,\n transitionId: transition.transitionId,\n pendingActivities: pendingJobIds,\n },\n userId: context.userId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n // Return WITHOUT executing step\n return {\n success: true,\n pausedForActivities: true,\n nextStepId: toStepId,\n conditionsEvaluated: {\n preConditions: true,\n postConditions: false, // Not evaluated yet\n },\n activitiesExecuted: activityResults,\n }\n }\n\n // Update workflow instance - set current step and update context atomically\n instance.currentStepId = toStepId\n instance.context = {\n ...instance.context,\n ...context.workflowContext,\n ...activityOutputs, // Include activity outputs\n }\n instance.updatedAt = new Date()\n\n await em.flush()\n\n // Execute the new step (this will create USER_TASK, handle END steps, etc.)\n const stepExecutionResult = await stepHandler.executeStep(\n em,\n instance,\n toStepId,\n {\n workflowContext: instance.context || {},\n userId: context.userId,\n triggerData: context.triggerData,\n },\n container\n )\n\n // Flush to database after step execution completes to make state visible to UI\n await em.flush()\n\n // Handle step execution failure\n if (stepExecutionResult.status === 'FAILED') {\n return {\n success: false,\n error: stepExecutionResult.error || 'Step execution failed',\n }\n }\n\n // Evaluate post-conditions (business rules)\n const postConditionsResult = await evaluatePostConditions(\n em,\n instance,\n transition,\n context,\n eventBus\n )\n\n if (!postConditionsResult.allowed) {\n const failedRules = postConditionsResult.errors?.join(', ') || 'Unknown post-condition failure'\n\n await logTransitionEvent(em, {\n workflowInstanceId: instance.id,\n eventType: 'TRANSITION_POST_CONDITION_FAILED',\n eventData: {\n fromStepId,\n toStepId,\n transitionId: transition.transitionId || `${fromStepId}->${toStepId}`,\n reason: 'Post-conditions failed',\n failedRules,\n },\n userId: context.userId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n // Note: We don't roll back the transition on post-condition failure\n // Post-conditions are warnings, not blockers\n }\n\n // Log successful transition\n await logTransitionEvent(em, {\n workflowInstanceId: instance.id,\n eventType: 'TRANSITION_EXECUTED',\n eventData: {\n fromStepId,\n toStepId,\n transitionId: transition.transitionId || `${fromStepId}->${toStepId}`,\n transitionName: transition.transitionName,\n preConditionsPassed: true,\n postConditionsPassed: postConditionsResult.allowed,\n activitiesExecuted: activityResults.length,\n activitiesSucceeded: activityResults.filter(r => r.success).length,\n activitiesFailed: activityResults.filter(r => !r.success).length,\n },\n userId: context.userId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n return {\n success: true,\n nextStepId: toStepId,\n conditionsEvaluated: {\n preConditions: true,\n postConditions: postConditionsResult.allowed,\n },\n activitiesExecuted: activityResults,\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n\n await logTransitionEvent(em, {\n workflowInstanceId: instance.id,\n eventType: 'TRANSITION_FAILED',\n eventData: {\n fromStepId,\n toStepId,\n error: errorMessage,\n },\n userId: context.userId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n return {\n success: false,\n error: `Transition execution failed: ${errorMessage}`,\n }\n }\n}\n\n// ============================================================================\n// Condition Evaluation\n// ============================================================================\n\n/**\n * Evaluate transition conditions (inline condition expression)\n *\n * @param em - Entity manager\n * @param instance - Workflow instance\n * @param transition - Transition definition\n * @param context - Evaluation context\n * @returns Evaluation result\n */\nasync function evaluateTransitionConditions(\n em: EntityManager,\n instance: WorkflowInstance,\n transition: any,\n context: TransitionEvaluationContext\n): Promise<TransitionEvaluationResult> {\n try {\n // If no condition specified, transition is always valid\n if (!transition.condition) {\n return {\n isValid: true,\n }\n }\n\n // Build data context for rule evaluation\n const data = {\n ...instance.context,\n ...context.workflowContext,\n triggerData: context.triggerData,\n }\n\n // Build evaluation context\n const evalContext: ruleEvaluator.RuleEvaluationContext = {\n entityType: 'workflow:transition',\n entityId: instance.id,\n user: context.userId ? { id: context.userId } : undefined,\n }\n\n // Evaluate condition using expression evaluator\n const result = await ruleEvaluator.evaluateConditions(\n transition.condition,\n data,\n evalContext\n )\n\n return {\n isValid: result,\n reason: result ? undefined : 'Transition condition evaluated to false',\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n return {\n isValid: false,\n reason: `Condition evaluation error: ${errorMessage}`,\n }\n }\n}\n\n/**\n * Evaluate pre-conditions using business rules engine\n *\n * Pre-conditions are GUARD rules that must pass before transition can execute.\n * If any GUARD rule fails, the transition is blocked.\n *\n * If the transition defines specific preConditions with ruleIds, those are\n * executed directly via executeRuleByRuleId. Otherwise, falls back to\n * discovery-based execution via executeRules.\n *\n * @param em - Entity manager\n * @param instance - Workflow instance\n * @param transition - Transition definition\n * @param context - Execution context\n * @returns Rule engine result\n */\nasync function evaluatePreConditions(\n em: EntityManager,\n instance: WorkflowInstance,\n transition: any,\n context: TransitionExecutionContext,\n eventBus: Pick<EventBus, 'emitEvent'> | null\n): Promise<ruleEngine.RuleEngineResult> {\n try {\n // Load workflow definition to get workflow ID\n const definition = await em.findOne(WorkflowDefinition, {\n id: instance.definitionId,\n })\n\n if (!definition) {\n return {\n allowed: true,\n executedRules: [],\n totalExecutionTime: 0,\n }\n }\n\n // Check if transition has specific preConditions defined\n const preConditions = transition.preConditions || []\n\n // If no pre-conditions defined, allow transition\n if (preConditions.length === 0) {\n return {\n allowed: true,\n executedRules: [],\n totalExecutionTime: 0,\n }\n }\n\n // Execute each pre-condition rule directly by ruleId\n const startTime = Date.now()\n const executedRules: ruleEngine.RuleExecutionResult[] = []\n const errors: string[] = []\n let allowed = true\n\n for (const condition of preConditions) {\n const result = await ruleEngine.executeRuleByRuleId(em, {\n ruleId: condition.ruleId, // String identifier\n data: {\n workflowInstanceId: instance.id,\n workflowId: definition.workflowId,\n fromStepId: transition.fromStepId,\n toStepId: transition.toStepId,\n workflowContext: {\n ...instance.context,\n ...context.workflowContext,\n },\n triggerData: context.triggerData,\n },\n user: context.userId ? { id: context.userId } : undefined,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n executedBy: context.userId,\n entityType: `workflow:${definition.workflowId}:transition`,\n entityId: transition.transitionId || `${transition.fromStepId}->${transition.toStepId}`,\n eventType: 'pre_transition',\n })\n\n // Create a compatible RuleExecutionResult for tracking\n // We don't have the full BusinessRule entity, but we can create a partial result\n const ruleResult: ruleEngine.RuleExecutionResult = {\n rule: {\n ruleId: result.ruleId,\n ruleName: result.ruleName,\n ruleType: 'GUARD',\n } as any,\n conditionResult: result.conditionResult,\n actionsExecuted: result.actionsExecuted,\n executionTime: result.executionTime,\n error: result.error,\n logId: result.logId,\n }\n executedRules.push(ruleResult)\n\n // Handle rule errors\n if (result.error) {\n // Rule not found, disabled, or other errors\n const isRequired = condition.required !== false // Default to required\n if (isRequired) {\n allowed = false\n errors.push(`Rule '${result.ruleId}': ${result.error}`)\n }\n continue\n }\n\n // If required and condition failed, block transition\n const isRequired = condition.required !== false // Default to required\n if (isRequired && !result.conditionResult) {\n allowed = false\n errors.push(`Pre-condition '${result.ruleName || result.ruleId}' failed`)\n }\n }\n\n return {\n allowed,\n executedRules,\n totalExecutionTime: Date.now() - startTime,\n errors: errors.length > 0 ? errors : undefined,\n }\n } catch (error) {\n console.error('Error evaluating pre-conditions:', error)\n return {\n allowed: false,\n executedRules: [],\n totalExecutionTime: 0,\n errors: [error instanceof Error ? error.message : String(error)],\n }\n }\n}\n\n/**\n * Evaluate post-conditions using business rules engine\n *\n * Post-conditions are GUARD rules that should pass after transition executes.\n * Unlike pre-conditions, post-condition failures are logged but don't block the transition.\n *\n * If the transition defines specific postConditions with ruleIds, those are\n * executed directly via executeRuleByRuleId. Otherwise, returns allowed: true.\n *\n * @param em - Entity manager\n * @param instance - Workflow instance\n * @param transition - Transition definition\n * @param context - Execution context\n * @returns Rule engine result\n */\nasync function evaluatePostConditions(\n em: EntityManager,\n instance: WorkflowInstance,\n transition: any,\n context: TransitionExecutionContext,\n eventBus: Pick<EventBus, 'emitEvent'> | null\n): Promise<ruleEngine.RuleEngineResult> {\n try {\n // Load workflow definition to get workflow ID\n const definition = await em.findOne(WorkflowDefinition, {\n id: instance.definitionId,\n })\n\n if (!definition) {\n return {\n allowed: true,\n executedRules: [],\n totalExecutionTime: 0,\n }\n }\n\n // Check if transition has specific postConditions defined\n const postConditions = transition.postConditions || []\n\n // If no post-conditions defined, allow\n if (postConditions.length === 0) {\n return {\n allowed: true,\n executedRules: [],\n totalExecutionTime: 0,\n }\n }\n\n // Execute each post-condition rule directly by ruleId\n const startTime = Date.now()\n const executedRules: ruleEngine.RuleExecutionResult[] = []\n const errors: string[] = []\n let allowed = true\n\n for (const condition of postConditions) {\n const result = await ruleEngine.executeRuleByRuleId(em, {\n ruleId: condition.ruleId, // String identifier\n data: {\n workflowInstanceId: instance.id,\n workflowId: definition.workflowId,\n fromStepId: transition.fromStepId,\n toStepId: transition.toStepId,\n workflowContext: {\n ...instance.context,\n ...context.workflowContext,\n },\n triggerData: context.triggerData,\n },\n user: context.userId ? { id: context.userId } : undefined,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n executedBy: context.userId,\n entityType: `workflow:${definition.workflowId}:transition`,\n entityId: transition.transitionId || `${transition.fromStepId}->${transition.toStepId}`,\n eventType: 'post_transition',\n })\n\n // Create a compatible RuleExecutionResult for tracking\n const ruleResult: ruleEngine.RuleExecutionResult = {\n rule: {\n ruleId: result.ruleId,\n ruleName: result.ruleName,\n ruleType: 'GUARD',\n } as any,\n conditionResult: result.conditionResult,\n actionsExecuted: result.actionsExecuted,\n executionTime: result.executionTime,\n error: result.error,\n logId: result.logId,\n }\n executedRules.push(ruleResult)\n\n // Handle rule errors\n if (result.error) {\n errors.push(`Rule '${result.ruleId}': ${result.error}`)\n // Post-conditions don't block, but track the failure\n allowed = false\n continue\n }\n\n // Track condition failures (post-conditions are warnings, not blockers)\n if (!result.conditionResult) {\n allowed = false\n errors.push(`Post-condition '${result.ruleName || result.ruleId}' failed`)\n }\n }\n\n return {\n allowed,\n executedRules,\n totalExecutionTime: Date.now() - startTime,\n errors: errors.length > 0 ? errors : undefined,\n }\n } catch (error) {\n console.error('Error evaluating post-conditions:', error)\n return {\n allowed: false,\n executedRules: [],\n totalExecutionTime: 0,\n errors: [error instanceof Error ? error.message : String(error)],\n }\n }\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Log transition-related event to event sourcing table\n */\nasync function logTransitionEvent(\n em: EntityManager,\n event: {\n workflowInstanceId: string\n eventType: string\n eventData: any\n userId?: string\n tenantId: string\n organizationId: string\n }\n): Promise<WorkflowEvent> {\n const workflowEvent = em.create(WorkflowEvent, {\n ...event,\n occurredAt: new Date(),\n })\n\n await em.persist(workflowEvent).flush()\n return workflowEvent\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Workflows Module - Transition Handler Service\n *\n * Handles workflow transitions between steps:\n * - Evaluating if a transition is valid (checking conditions)\n * - Executing transitions (moving from one step to another)\n * - Integrating with business rules engine for pre/post conditions\n * - Executing activities on transition\n *\n * Functional API (no classes) following Open Mercato conventions.\n */\n\nimport { EntityManager } from '@mikro-orm/core'\nimport type { AwilixContainer } from 'awilix'\nimport type { EventBus } from '@open-mercato/events'\nimport {\n WorkflowInstance,\n WorkflowDefinition,\n WorkflowEvent,\n} from '../data/entities'\nimport * as ruleEvaluator from '../../business_rules/lib/rule-evaluator'\nimport * as ruleEngine from '../../business_rules/lib/rule-engine'\nimport * as activityExecutor from './activity-executor'\nimport type { ActivityDefinition } from './activity-executor'\nimport * as stepHandler from './step-handler'\nimport {\n type ExecutionToken,\n rootToken,\n tokenBranchInstanceId,\n tokenReadContext,\n setTokenCurrentStepId,\n applyTokenContextWrites,\n mergeTokenContext,\n setTokenWaitingForActivities,\n setTokenPendingTransition,\n touchToken,\n} from './execution-token'\n\n// ============================================================================\n// Types and Interfaces\n// ============================================================================\n\nexport interface TransitionEvaluationContext {\n workflowContext: Record<string, any>\n userId?: string\n triggerData?: any\n}\n\nexport interface TransitionEvaluationResult {\n isValid: boolean\n transition?: any\n reason?: string\n failedConditions?: string[]\n evaluationTime?: number\n}\n\nexport interface TransitionExecutionContext {\n workflowContext: Record<string, any>\n userId?: string\n triggerData?: any\n}\n\nexport interface TransitionExecutionResult {\n success: boolean\n nextStepId?: string\n pausedForActivities?: boolean\n conditionsEvaluated?: {\n preConditions: boolean\n postConditions: boolean\n }\n activitiesExecuted?: activityExecutor.ActivityExecutionResult[]\n error?: string\n}\n\nexport class TransitionError extends Error {\n constructor(\n message: string,\n public code: string,\n public details?: any\n ) {\n super(message)\n this.name = 'TransitionError'\n }\n}\n\n// ============================================================================\n// Main Transition Functions\n// ============================================================================\n\n/**\n * Evaluate if a transition from current step to target step is valid\n *\n * Checks:\n * - Transition exists in workflow definition\n * - Pre-conditions pass (if any business rules defined)\n * - Transition condition evaluates to true (if specified)\n *\n * @param em - Entity manager\n * @param instance - Workflow instance\n * @param fromStepId - Current step ID\n * @param toStepId - Target step ID (optional - will auto-select if not provided)\n * @param context - Evaluation context\n * @returns Evaluation result with validity and reason\n */\nexport async function evaluateTransition(\n em: EntityManager,\n instance: WorkflowInstance,\n fromStepId: string,\n toStepId: string | undefined,\n context: TransitionEvaluationContext\n): Promise<TransitionEvaluationResult> {\n const startTime = Date.now()\n\n try {\n // Load workflow definition\n const definition = await em.findOne(WorkflowDefinition, {\n id: instance.definitionId,\n })\n\n if (!definition) {\n return {\n isValid: false,\n reason: `Workflow definition not found: ${instance.definitionId}`,\n evaluationTime: Date.now() - startTime,\n }\n }\n\n // Find transition\n const transitions = definition.definition.transitions || []\n let transition: any\n\n if (toStepId) {\n // Find specific transition\n transition = transitions.find(\n (t: any) => t.fromStepId === fromStepId && t.toStepId === toStepId\n )\n\n if (!transition) {\n return {\n isValid: false,\n reason: `No transition found from ${fromStepId} to ${toStepId}`,\n evaluationTime: Date.now() - startTime,\n }\n }\n } else {\n // Auto-select first valid transition\n const availableTransitions = transitions.filter(\n (t: any) => t.fromStepId === fromStepId\n )\n\n if (availableTransitions.length === 0) {\n return {\n isValid: false,\n reason: `No transitions available from step ${fromStepId}`,\n evaluationTime: Date.now() - startTime,\n }\n }\n\n // Evaluate each transition to find first valid one\n for (const t of availableTransitions) {\n const result = await evaluateTransitionConditions(\n em,\n instance,\n t,\n context\n )\n\n if (result.isValid) {\n transition = t\n break\n }\n }\n\n if (!transition) {\n return {\n isValid: false,\n reason: `No valid transitions found from step ${fromStepId}`,\n evaluationTime: Date.now() - startTime,\n }\n }\n }\n\n // Evaluate transition conditions (inline condition + business rules pre-conditions)\n const conditionResult = await evaluateTransitionConditions(\n em,\n instance,\n transition,\n context\n )\n\n return {\n ...conditionResult,\n transition,\n evaluationTime: Date.now() - startTime,\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n return {\n isValid: false,\n reason: `Transition evaluation error: ${errorMessage}`,\n evaluationTime: Date.now() - startTime,\n }\n }\n}\n\n/**\n * Find all valid transitions from current step\n *\n * This function evaluates both inline conditions AND preConditions (business rules)\n * to determine which transitions are truly valid. This is important for decision\n * branching where multiple transitions exist with different preConditions.\n *\n * @param em - Entity manager\n * @param instance - Workflow instance\n * @param fromStepId - Current step ID\n * @param context - Evaluation context\n * @returns Array of evaluation results for all transitions, sorted by priority (desc)\n */\nexport async function findValidTransitions(\n em: EntityManager,\n instance: WorkflowInstance,\n fromStepId: string,\n context: TransitionEvaluationContext\n): Promise<TransitionEvaluationResult[]> {\n try {\n // Load workflow definition\n const definition = await em.findOne(WorkflowDefinition, {\n id: instance.definitionId,\n })\n\n if (!definition) {\n return []\n }\n\n // Find all transitions from current step, sorted by priority (highest first)\n const transitions = (definition.definition.transitions || [])\n .filter((t: any) => t.fromStepId === fromStepId)\n .sort((a: any, b: any) => (b.priority || 0) - (a.priority || 0))\n\n // Evaluate each transition including preConditions\n const results: TransitionEvaluationResult[] = []\n\n for (const transition of transitions) {\n // First check inline condition\n const conditionResult = await evaluateTransition(\n em,\n instance,\n fromStepId,\n transition.toStepId,\n context\n )\n\n if (!conditionResult.isValid) {\n results.push(conditionResult)\n continue\n }\n\n // Also evaluate preConditions if they exist\n const preConditions = transition.preConditions || []\n if (preConditions.length > 0) {\n const preConditionsResult = await evaluatePreConditions(\n em,\n instance,\n transition,\n context as TransitionExecutionContext,\n null\n )\n\n if (!preConditionsResult.allowed) {\n // Transition is invalid due to preConditions\n const failedRules = preConditionsResult.executedRules\n .filter((r) => !r.conditionResult)\n .map((r) => r.rule.ruleId || r.rule.ruleName)\n\n results.push({\n isValid: false,\n transition,\n reason: `Pre-conditions failed: ${failedRules.join(', ')}`,\n failedConditions: failedRules,\n })\n continue\n }\n }\n\n // Transition is valid (both condition and preConditions passed)\n results.push({\n ...conditionResult,\n transition,\n })\n }\n\n return results\n } catch (error) {\n console.error('Error finding valid transitions:', error)\n return []\n }\n}\n\n/**\n * Execute a transition from one step to another\n *\n * This is the main entry point for transition execution. It:\n * 1. Validates the transition\n * 2. Evaluates pre-conditions\n * 3. Executes activities (if any)\n * 4. Updates workflow instance state (atomically with activity outputs)\n * 5. Evaluates post-conditions\n * 6. Logs transition event\n *\n * @param em - Entity manager\n * @param container - DI container (for activity execution)\n * @param instance - Workflow instance\n * @param fromStepId - Current step ID\n * @param toStepId - Target step ID\n * @param context - Execution context\n * @returns Execution result\n */\nexport async function executeTransition(\n em: EntityManager,\n container: AwilixContainer,\n instance: WorkflowInstance,\n fromStepId: string,\n toStepId: string,\n context: TransitionExecutionContext\n): Promise<TransitionExecutionResult> {\n // Public DI signature preserved: the root token adapts the instance, so the\n // single-token path is behaviourally unchanged.\n return executeTransitionForToken(em, container, rootToken(instance), fromStepId, toStepId, context)\n}\n\n/**\n * Token-aware transition execution. The root token wraps a WorkflowInstance\n * (legacy single-token path); a branch token wraps a WorkflowBranchInstance so\n * a parallel branch advances independently with its own context namespace,\n * status and pending transition.\n */\nexport async function executeTransitionForToken(\n em: EntityManager,\n container: AwilixContainer,\n token: ExecutionToken,\n fromStepId: string,\n toStepId: string,\n context: TransitionExecutionContext\n): Promise<TransitionExecutionResult> {\n const instance = token.instance\n const branch = token.kind === 'branch' ? token.branch : null\n const branchInstanceId = tokenBranchInstanceId(token)\n try {\n let eventBus: Pick<EventBus, 'emitEvent'> | null = null\n try {\n eventBus = container.resolve('eventBus') as EventBus\n } catch {\n eventBus = null\n }\n\n // First, evaluate if transition is valid\n const evaluation = await evaluateTransition(\n em,\n instance,\n fromStepId,\n toStepId,\n context\n )\n\n if (!evaluation.isValid) {\n return {\n success: false,\n error: evaluation.reason || 'Transition validation failed',\n }\n }\n\n const transition = evaluation.transition!\n\n // Evaluate pre-conditions (business rules)\n const preConditionsResult = await evaluatePreConditions(\n em,\n instance,\n transition,\n context,\n eventBus\n )\n\n if (!preConditionsResult.allowed) {\n // Build detailed failure information\n const failedRules = preConditionsResult.executedRules\n .filter((r) => !r.conditionResult)\n .map((r) => ({\n ruleId: r.rule.ruleId,\n ruleName: r.rule.ruleName,\n error: r.error,\n }))\n\n const failedRulesDetails = failedRules.length > 0\n ? failedRules.map(r => `${r.ruleId}: ${r.error || 'condition failed'}`).join('; ')\n : preConditionsResult.errors?.join(', ') || 'Unknown pre-condition failure'\n\n await logTransitionEvent(em, {\n workflowInstanceId: instance.id,\n eventType: 'TRANSITION_REJECTED',\n eventData: {\n fromStepId,\n toStepId,\n transitionId: transition.transitionId || `${fromStepId}->${toStepId}`,\n reason: 'Pre-conditions failed',\n failedRules: failedRulesDetails,\n failedRulesDetail: failedRules,\n },\n userId: context.userId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n return {\n success: false,\n error: `Pre-conditions failed: ${failedRulesDetails}`,\n conditionsEvaluated: {\n preConditions: false,\n postConditions: false,\n },\n }\n }\n\n // Execute activities (if any)\n let activityOutputs: Record<string, any> = {}\n const activityResults: activityExecutor.ActivityExecutionResult[] = []\n\n if (transition.activities && transition.activities.length > 0) {\n const activityContext: activityExecutor.ActivityContext = {\n workflowInstance: instance,\n workflowContext: {\n ...tokenReadContext(token),\n ...context.workflowContext,\n },\n branchInstanceId,\n userId: context.userId,\n }\n\n // Execute all activities\n const results = await activityExecutor.executeActivities(\n em,\n container,\n transition.activities as ActivityDefinition[],\n activityContext\n )\n\n activityResults.push(...results)\n\n // Check for failures\n const failedActivities = results.filter(r => !r.success)\n\n if (failedActivities.length > 0) {\n const continueOnFailure = transition.continueOnActivityFailure ?? false\n\n // Log activity failures\n await logTransitionEvent(em, {\n workflowInstanceId: instance.id,\n eventType: 'ACTIVITY_FAILED',\n eventData: {\n fromStepId,\n toStepId,\n transitionId: transition.transitionId || `${fromStepId}->${toStepId}`,\n failedActivities: failedActivities.map(f => ({\n activityType: f.activityType,\n activityName: f.activityName,\n error: f.error,\n retryCount: f.retryCount,\n })),\n continueOnFailure,\n },\n userId: context.userId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n if (!continueOnFailure) {\n return {\n success: false,\n error: `Activities failed: ${failedActivities.map(f => f.error).join(', ')}`,\n conditionsEvaluated: {\n preConditions: true,\n postConditions: false,\n },\n }\n }\n }\n\n // Collect activity outputs for context update\n results.forEach(result => {\n if (result.success && result.output) {\n const key = result.activityName || result.activityType\n activityOutputs[key] = result.output\n }\n })\n }\n\n // Check if any activities are async - if so, pause before executing step\n const hasAsyncActivities = activityResults.some(r => r.async)\n\n if (hasAsyncActivities) {\n const pendingJobIds = activityResults\n .filter(a => a.async && a.jobId)\n .map(a => ({ activityId: a.activityId, jobId: a.jobId }))\n\n // Store pending transition state (per-token: branch or instance)\n setTokenPendingTransition(token, {\n toStepId,\n activityResults,\n timestamp: new Date(),\n })\n\n // Store activity outputs + pending-activity tracking in the token's own\n // context scope (instance.context for root, branch namespace for a branch)\n applyTokenContextWrites(token, context.workflowContext, activityOutputs)\n mergeTokenContext(token, { _pendingAsyncActivities: pendingJobIds })\n\n // Set status to waiting (branch-scoped when running inside a branch)\n setTokenWaitingForActivities(token)\n touchToken(token, new Date())\n await em.flush()\n\n // Log event\n await logTransitionEvent(em, {\n workflowInstanceId: instance.id,\n branchInstanceId,\n eventType: 'TRANSITION_PAUSED_FOR_ACTIVITIES',\n eventData: {\n fromStepId,\n toStepId,\n transitionId: transition.transitionId,\n pendingActivities: pendingJobIds,\n },\n userId: context.userId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n // Return WITHOUT executing step\n return {\n success: true,\n pausedForActivities: true,\n nextStepId: toStepId,\n conditionsEvaluated: {\n preConditions: true,\n postConditions: false, // Not evaluated yet\n },\n activitiesExecuted: activityResults,\n }\n }\n\n // Advance the token cursor and update context atomically (instance for the\n // root token; branch cursor + namespace for a branch token).\n setTokenCurrentStepId(token, toStepId)\n applyTokenContextWrites(token, context.workflowContext, activityOutputs)\n touchToken(token, new Date())\n\n await em.flush()\n\n // Execute the new step (this will create USER_TASK, handle END steps, etc.)\n const stepExecutionResult = await stepHandler.executeStep(\n em,\n instance,\n toStepId,\n {\n workflowContext: tokenReadContext(token),\n userId: context.userId,\n triggerData: context.triggerData,\n },\n container,\n branch\n )\n\n // Flush to database after step execution completes to make state visible to UI\n await em.flush()\n\n // Handle step execution failure\n if (stepExecutionResult.status === 'FAILED') {\n return {\n success: false,\n error: stepExecutionResult.error || 'Step execution failed',\n }\n }\n\n // Evaluate post-conditions (business rules)\n const postConditionsResult = await evaluatePostConditions(\n em,\n instance,\n transition,\n context,\n eventBus\n )\n\n if (!postConditionsResult.allowed) {\n const failedRules = postConditionsResult.errors?.join(', ') || 'Unknown post-condition failure'\n\n await logTransitionEvent(em, {\n workflowInstanceId: instance.id,\n eventType: 'TRANSITION_POST_CONDITION_FAILED',\n eventData: {\n fromStepId,\n toStepId,\n transitionId: transition.transitionId || `${fromStepId}->${toStepId}`,\n reason: 'Post-conditions failed',\n failedRules,\n },\n userId: context.userId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n // Note: We don't roll back the transition on post-condition failure\n // Post-conditions are warnings, not blockers\n }\n\n // Log successful transition\n await logTransitionEvent(em, {\n workflowInstanceId: instance.id,\n eventType: 'TRANSITION_EXECUTED',\n eventData: {\n fromStepId,\n toStepId,\n transitionId: transition.transitionId || `${fromStepId}->${toStepId}`,\n transitionName: transition.transitionName,\n preConditionsPassed: true,\n postConditionsPassed: postConditionsResult.allowed,\n activitiesExecuted: activityResults.length,\n activitiesSucceeded: activityResults.filter(r => r.success).length,\n activitiesFailed: activityResults.filter(r => !r.success).length,\n },\n userId: context.userId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n return {\n success: true,\n nextStepId: toStepId,\n conditionsEvaluated: {\n preConditions: true,\n postConditions: postConditionsResult.allowed,\n },\n activitiesExecuted: activityResults,\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n\n await logTransitionEvent(em, {\n workflowInstanceId: instance.id,\n eventType: 'TRANSITION_FAILED',\n eventData: {\n fromStepId,\n toStepId,\n error: errorMessage,\n },\n userId: context.userId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n return {\n success: false,\n error: `Transition execution failed: ${errorMessage}`,\n }\n }\n}\n\n// ============================================================================\n// Condition Evaluation\n// ============================================================================\n\n/**\n * Evaluate transition conditions (inline condition expression)\n *\n * @param em - Entity manager\n * @param instance - Workflow instance\n * @param transition - Transition definition\n * @param context - Evaluation context\n * @returns Evaluation result\n */\nasync function evaluateTransitionConditions(\n em: EntityManager,\n instance: WorkflowInstance,\n transition: any,\n context: TransitionEvaluationContext\n): Promise<TransitionEvaluationResult> {\n try {\n // If no condition specified, transition is always valid\n if (!transition.condition) {\n return {\n isValid: true,\n }\n }\n\n // Build data context for rule evaluation\n const data = {\n ...instance.context,\n ...context.workflowContext,\n triggerData: context.triggerData,\n }\n\n // Build evaluation context\n const evalContext: ruleEvaluator.RuleEvaluationContext = {\n entityType: 'workflow:transition',\n entityId: instance.id,\n user: context.userId ? { id: context.userId } : undefined,\n }\n\n // Evaluate condition using expression evaluator\n const result = await ruleEvaluator.evaluateConditions(\n transition.condition,\n data,\n evalContext\n )\n\n return {\n isValid: result,\n reason: result ? undefined : 'Transition condition evaluated to false',\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n return {\n isValid: false,\n reason: `Condition evaluation error: ${errorMessage}`,\n }\n }\n}\n\n/**\n * Evaluate pre-conditions using business rules engine\n *\n * Pre-conditions are GUARD rules that must pass before transition can execute.\n * If any GUARD rule fails, the transition is blocked.\n *\n * If the transition defines specific preConditions with ruleIds, those are\n * executed directly via executeRuleByRuleId. Otherwise, falls back to\n * discovery-based execution via executeRules.\n *\n * @param em - Entity manager\n * @param instance - Workflow instance\n * @param transition - Transition definition\n * @param context - Execution context\n * @returns Rule engine result\n */\nasync function evaluatePreConditions(\n em: EntityManager,\n instance: WorkflowInstance,\n transition: any,\n context: TransitionExecutionContext,\n eventBus: Pick<EventBus, 'emitEvent'> | null\n): Promise<ruleEngine.RuleEngineResult> {\n try {\n // Load workflow definition to get workflow ID\n const definition = await em.findOne(WorkflowDefinition, {\n id: instance.definitionId,\n })\n\n if (!definition) {\n return {\n allowed: true,\n executedRules: [],\n totalExecutionTime: 0,\n }\n }\n\n // Check if transition has specific preConditions defined\n const preConditions = transition.preConditions || []\n\n // If no pre-conditions defined, allow transition\n if (preConditions.length === 0) {\n return {\n allowed: true,\n executedRules: [],\n totalExecutionTime: 0,\n }\n }\n\n // Execute each pre-condition rule directly by ruleId\n const startTime = Date.now()\n const executedRules: ruleEngine.RuleExecutionResult[] = []\n const errors: string[] = []\n let allowed = true\n\n for (const condition of preConditions) {\n const result = await ruleEngine.executeRuleByRuleId(em, {\n ruleId: condition.ruleId, // String identifier\n data: {\n workflowInstanceId: instance.id,\n workflowId: definition.workflowId,\n fromStepId: transition.fromStepId,\n toStepId: transition.toStepId,\n workflowContext: {\n ...instance.context,\n ...context.workflowContext,\n },\n triggerData: context.triggerData,\n },\n user: context.userId ? { id: context.userId } : undefined,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n executedBy: context.userId,\n entityType: `workflow:${definition.workflowId}:transition`,\n entityId: transition.transitionId || `${transition.fromStepId}->${transition.toStepId}`,\n eventType: 'pre_transition',\n })\n\n // Create a compatible RuleExecutionResult for tracking\n // We don't have the full BusinessRule entity, but we can create a partial result\n const ruleResult: ruleEngine.RuleExecutionResult = {\n rule: {\n ruleId: result.ruleId,\n ruleName: result.ruleName,\n ruleType: 'GUARD',\n } as any,\n conditionResult: result.conditionResult,\n actionsExecuted: result.actionsExecuted,\n executionTime: result.executionTime,\n error: result.error,\n logId: result.logId,\n }\n executedRules.push(ruleResult)\n\n // Handle rule errors\n if (result.error) {\n // Rule not found, disabled, or other errors\n const isRequired = condition.required !== false // Default to required\n if (isRequired) {\n allowed = false\n errors.push(`Rule '${result.ruleId}': ${result.error}`)\n }\n continue\n }\n\n // If required and condition failed, block transition\n const isRequired = condition.required !== false // Default to required\n if (isRequired && !result.conditionResult) {\n allowed = false\n errors.push(`Pre-condition '${result.ruleName || result.ruleId}' failed`)\n }\n }\n\n return {\n allowed,\n executedRules,\n totalExecutionTime: Date.now() - startTime,\n errors: errors.length > 0 ? errors : undefined,\n }\n } catch (error) {\n console.error('Error evaluating pre-conditions:', error)\n return {\n allowed: false,\n executedRules: [],\n totalExecutionTime: 0,\n errors: [error instanceof Error ? error.message : String(error)],\n }\n }\n}\n\n/**\n * Evaluate post-conditions using business rules engine\n *\n * Post-conditions are GUARD rules that should pass after transition executes.\n * Unlike pre-conditions, post-condition failures are logged but don't block the transition.\n *\n * If the transition defines specific postConditions with ruleIds, those are\n * executed directly via executeRuleByRuleId. Otherwise, returns allowed: true.\n *\n * @param em - Entity manager\n * @param instance - Workflow instance\n * @param transition - Transition definition\n * @param context - Execution context\n * @returns Rule engine result\n */\nasync function evaluatePostConditions(\n em: EntityManager,\n instance: WorkflowInstance,\n transition: any,\n context: TransitionExecutionContext,\n eventBus: Pick<EventBus, 'emitEvent'> | null\n): Promise<ruleEngine.RuleEngineResult> {\n try {\n // Load workflow definition to get workflow ID\n const definition = await em.findOne(WorkflowDefinition, {\n id: instance.definitionId,\n })\n\n if (!definition) {\n return {\n allowed: true,\n executedRules: [],\n totalExecutionTime: 0,\n }\n }\n\n // Check if transition has specific postConditions defined\n const postConditions = transition.postConditions || []\n\n // If no post-conditions defined, allow\n if (postConditions.length === 0) {\n return {\n allowed: true,\n executedRules: [],\n totalExecutionTime: 0,\n }\n }\n\n // Execute each post-condition rule directly by ruleId\n const startTime = Date.now()\n const executedRules: ruleEngine.RuleExecutionResult[] = []\n const errors: string[] = []\n let allowed = true\n\n for (const condition of postConditions) {\n const result = await ruleEngine.executeRuleByRuleId(em, {\n ruleId: condition.ruleId, // String identifier\n data: {\n workflowInstanceId: instance.id,\n workflowId: definition.workflowId,\n fromStepId: transition.fromStepId,\n toStepId: transition.toStepId,\n workflowContext: {\n ...instance.context,\n ...context.workflowContext,\n },\n triggerData: context.triggerData,\n },\n user: context.userId ? { id: context.userId } : undefined,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n executedBy: context.userId,\n entityType: `workflow:${definition.workflowId}:transition`,\n entityId: transition.transitionId || `${transition.fromStepId}->${transition.toStepId}`,\n eventType: 'post_transition',\n })\n\n // Create a compatible RuleExecutionResult for tracking\n const ruleResult: ruleEngine.RuleExecutionResult = {\n rule: {\n ruleId: result.ruleId,\n ruleName: result.ruleName,\n ruleType: 'GUARD',\n } as any,\n conditionResult: result.conditionResult,\n actionsExecuted: result.actionsExecuted,\n executionTime: result.executionTime,\n error: result.error,\n logId: result.logId,\n }\n executedRules.push(ruleResult)\n\n // Handle rule errors\n if (result.error) {\n errors.push(`Rule '${result.ruleId}': ${result.error}`)\n // Post-conditions don't block, but track the failure\n allowed = false\n continue\n }\n\n // Track condition failures (post-conditions are warnings, not blockers)\n if (!result.conditionResult) {\n allowed = false\n errors.push(`Post-condition '${result.ruleName || result.ruleId}' failed`)\n }\n }\n\n return {\n allowed,\n executedRules,\n totalExecutionTime: Date.now() - startTime,\n errors: errors.length > 0 ? errors : undefined,\n }\n } catch (error) {\n console.error('Error evaluating post-conditions:', error)\n return {\n allowed: false,\n executedRules: [],\n totalExecutionTime: 0,\n errors: [error instanceof Error ? error.message : String(error)],\n }\n }\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Log transition-related event to event sourcing table\n */\nasync function logTransitionEvent(\n em: EntityManager,\n event: {\n workflowInstanceId: string\n branchInstanceId?: string | null\n eventType: string\n eventData: any\n userId?: string\n tenantId: string\n organizationId: string\n }\n): Promise<WorkflowEvent> {\n const workflowEvent = em.create(WorkflowEvent, {\n ...event,\n occurredAt: new Date(),\n })\n\n await em.persist(workflowEvent).flush()\n return workflowEvent\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["isRequired"]
7
7
  }
@@ -175,6 +175,36 @@ async function executeWorkflow(em, container, instanceId, context) {
175
175
  { instanceId }
176
176
  );
177
177
  }
178
+ if (currentInstance.status === "FORKED") {
179
+ const { advanceBranches } = await import("./parallel-handler.js");
180
+ const branchResult = await advanceBranches(trx, container, currentInstance, definition, {
181
+ userId: context?.userId
182
+ });
183
+ if (branchResult.outcome === "joined") {
184
+ continue;
185
+ }
186
+ if (branchResult.outcome === "failed") {
187
+ errors.push(branchResult.error || "Parallel branch failed");
188
+ await completeWorkflow(trx, container, instanceId, "FAILED", {
189
+ error: branchResult.error || "Parallel branch failed"
190
+ });
191
+ return {
192
+ status: "FAILED",
193
+ currentStep: currentInstance.currentStepId,
194
+ context: currentInstance.context,
195
+ events,
196
+ errors,
197
+ executionTime: Date.now() - startTime
198
+ };
199
+ }
200
+ return {
201
+ status: "RUNNING",
202
+ currentStep: currentInstance.currentStepId,
203
+ context: currentInstance.context,
204
+ events,
205
+ executionTime: Date.now() - startTime
206
+ };
207
+ }
178
208
  const currentStep = definition.definition.steps.find(
179
209
  (s) => s.stepId === currentInstance.currentStepId
180
210
  );
@@ -429,8 +459,16 @@ async function completeWorkflow(em, container, instanceId, status, result) {
429
459
  organizationId: instance.organizationId
430
460
  });
431
461
  }
432
- async function resumeWorkflowAfterActivities(em, container, instanceId) {
462
+ async function resumeWorkflowAfterActivities(em, container, instanceId, branchInstanceId) {
433
463
  const transactionalEm = em;
464
+ if (branchInstanceId) {
465
+ const { resumeBranchAfterActivities } = await import("./parallel-handler.js");
466
+ const branchResume = typeof transactionalEm.transactional === "function" ? await transactionalEm.transactional((trx) => resumeBranchAfterActivities(trx, container, instanceId, branchInstanceId)) : await resumeBranchAfterActivities(em, container, instanceId, branchInstanceId);
467
+ if (branchResume.continueExecution) {
468
+ await executeWorkflow(em, container, instanceId);
469
+ }
470
+ return;
471
+ }
434
472
  const runResume = async (trx) => {
435
473
  const instance = await trx.findOne(WorkflowInstance, {
436
474
  id: instanceId,