@open-mercato/core 0.6.2-develop.3400.2.d948268f50 → 0.6.2-develop.3406.1.2b403f40da

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 (95) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/generated/entities/workflow_definition/index.js +2 -0
  3. package/dist/generated/entities/workflow_definition/index.js.map +2 -2
  4. package/dist/generated/entity-fields-registry.js +1 -0
  5. package/dist/generated/entity-fields-registry.js.map +2 -2
  6. package/dist/modules/sales/workflows.js +180 -0
  7. package/dist/modules/sales/workflows.js.map +7 -0
  8. package/dist/modules/workflows/api/definitions/[id]/customize/route.js +172 -0
  9. package/dist/modules/workflows/api/definitions/[id]/customize/route.js.map +7 -0
  10. package/dist/modules/workflows/api/definitions/[id]/reset-to-code/route.js +205 -0
  11. package/dist/modules/workflows/api/definitions/[id]/reset-to-code/route.js.map +7 -0
  12. package/dist/modules/workflows/api/definitions/[id]/route.js +91 -2
  13. package/dist/modules/workflows/api/definitions/[id]/route.js.map +2 -2
  14. package/dist/modules/workflows/api/definitions/route.js +32 -9
  15. package/dist/modules/workflows/api/definitions/route.js.map +2 -2
  16. package/dist/modules/workflows/api/definitions/serialize.js +36 -1
  17. package/dist/modules/workflows/api/definitions/serialize.js.map +2 -2
  18. package/dist/modules/workflows/backend/definitions/[id]/page.js +161 -52
  19. package/dist/modules/workflows/backend/definitions/[id]/page.js.map +2 -2
  20. package/dist/modules/workflows/backend/definitions/page.js +37 -34
  21. package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
  22. package/dist/modules/workflows/backend/definitions/visual-editor/page.js +134 -41
  23. package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +2 -2
  24. package/dist/modules/workflows/cli.js +19 -121
  25. package/dist/modules/workflows/cli.js.map +2 -2
  26. package/dist/modules/workflows/components/formConfig.js +1 -1
  27. package/dist/modules/workflows/components/formConfig.js.map +2 -2
  28. package/dist/modules/workflows/data/entities.js +3 -0
  29. package/dist/modules/workflows/data/entities.js.map +2 -2
  30. package/dist/modules/workflows/data/validators.js +2 -2
  31. package/dist/modules/workflows/data/validators.js.map +2 -2
  32. package/dist/modules/workflows/events.js +2 -0
  33. package/dist/modules/workflows/events.js.map +2 -2
  34. package/dist/modules/workflows/examples/guard-rules-example.json +6 -6
  35. package/dist/modules/workflows/examples/order-approval-guard-rules.json +2 -2
  36. package/dist/modules/workflows/frontend/checkout-demo/page.js +4 -4
  37. package/dist/modules/workflows/frontend/checkout-demo/page.js.map +2 -2
  38. package/dist/modules/workflows/lib/code-registry.js +40 -0
  39. package/dist/modules/workflows/lib/code-registry.js.map +7 -0
  40. package/dist/modules/workflows/lib/find-definition.js +58 -0
  41. package/dist/modules/workflows/lib/find-definition.js.map +7 -0
  42. package/dist/modules/workflows/lib/seeds.js +0 -3
  43. package/dist/modules/workflows/lib/seeds.js.map +2 -2
  44. package/dist/modules/workflows/lib/start-validator.js +1 -20
  45. package/dist/modules/workflows/lib/start-validator.js.map +2 -2
  46. package/dist/modules/workflows/lib/workflow-executor.js +1 -19
  47. package/dist/modules/workflows/lib/workflow-executor.js.map +2 -2
  48. package/dist/modules/workflows/migrations/Migration20260414120000.js +13 -0
  49. package/dist/modules/workflows/migrations/Migration20260414120000.js.map +7 -0
  50. package/dist/modules/workflows/migrations/Migration20260428102318.js +32 -0
  51. package/dist/modules/workflows/migrations/Migration20260428102318.js.map +7 -0
  52. package/dist/modules/workflows/widgets/injection/order-approval/widget.client.js +1 -1
  53. package/dist/modules/workflows/widgets/injection/order-approval/widget.client.js.map +1 -1
  54. package/dist/modules/workflows/workflows.js +260 -0
  55. package/dist/modules/workflows/workflows.js.map +7 -0
  56. package/generated/entities/workflow_definition/index.ts +1 -0
  57. package/generated/entity-fields-registry.ts +1 -0
  58. package/package.json +7 -7
  59. package/src/modules/sales/workflows.ts +184 -0
  60. package/src/modules/workflows/api/definitions/[id]/customize/route.ts +197 -0
  61. package/src/modules/workflows/api/definitions/[id]/reset-to-code/route.ts +252 -0
  62. package/src/modules/workflows/api/definitions/[id]/route.ts +108 -4
  63. package/src/modules/workflows/api/definitions/route.ts +54 -10
  64. package/src/modules/workflows/api/definitions/serialize.ts +42 -0
  65. package/src/modules/workflows/backend/definitions/[id]/page.tsx +135 -11
  66. package/src/modules/workflows/backend/definitions/page.tsx +45 -33
  67. package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +222 -97
  68. package/src/modules/workflows/cli.ts +32 -155
  69. package/src/modules/workflows/components/formConfig.tsx +2 -2
  70. package/src/modules/workflows/data/entities.ts +4 -1
  71. package/src/modules/workflows/data/validators.ts +4 -3
  72. package/src/modules/workflows/events.ts +2 -0
  73. package/src/modules/workflows/examples/guard-rules-example.json +6 -6
  74. package/src/modules/workflows/examples/order-approval-guard-rules.json +2 -2
  75. package/src/modules/workflows/frontend/checkout-demo/page.tsx +4 -4
  76. package/src/modules/workflows/i18n/de.json +16 -0
  77. package/src/modules/workflows/i18n/en.json +16 -0
  78. package/src/modules/workflows/i18n/es.json +16 -0
  79. package/src/modules/workflows/i18n/pl.json +16 -0
  80. package/src/modules/workflows/lib/code-registry.ts +65 -0
  81. package/src/modules/workflows/lib/find-definition.ts +100 -0
  82. package/src/modules/workflows/lib/seeds.ts +4 -3
  83. package/src/modules/workflows/lib/start-validator.ts +2 -35
  84. package/src/modules/workflows/lib/workflow-executor.ts +2 -39
  85. package/src/modules/workflows/migrations/.snapshot-open-mercato.json +10 -0
  86. package/src/modules/workflows/migrations/Migration20260414120000.ts +13 -0
  87. package/src/modules/workflows/migrations/Migration20260428102318.ts +57 -0
  88. package/src/modules/workflows/widgets/injection/order-approval/widget.client.tsx +1 -1
  89. package/src/modules/workflows/workflows.ts +278 -0
  90. package/dist/modules/workflows/examples/checkout-demo-definition.json +0 -486
  91. package/dist/modules/workflows/examples/order-approval-definition.json +0 -257
  92. package/dist/modules/workflows/examples/simple-approval-definition.json +0 -134
  93. package/src/modules/workflows/examples/checkout-demo-definition.json +0 -486
  94. package/src/modules/workflows/examples/order-approval-definition.json +0 -257
  95. package/src/modules/workflows/examples/simple-approval-definition.json +0 -134
@@ -0,0 +1,40 @@
1
+ import { workflowDefinitionDataSchema } from "../data/validators.js";
2
+ const codeWorkflowRegistry = /* @__PURE__ */ new Map();
3
+ function registerCodeWorkflows(workflows) {
4
+ for (const wf of workflows) {
5
+ const validation = workflowDefinitionDataSchema.safeParse(wf.definition);
6
+ if (!validation.success) {
7
+ console.warn(
8
+ `[workflows] Code workflow "${wf.workflowId}" failed validation:`,
9
+ validation.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ")
10
+ );
11
+ continue;
12
+ }
13
+ if (codeWorkflowRegistry.has(wf.workflowId)) {
14
+ console.warn(
15
+ `[workflows] Duplicate code workflow ID "${wf.workflowId}" from module "${wf.moduleId}" \u2014 overwriting`
16
+ );
17
+ }
18
+ codeWorkflowRegistry.set(wf.workflowId, wf);
19
+ }
20
+ }
21
+ function getCodeWorkflow(workflowId) {
22
+ return codeWorkflowRegistry.get(workflowId);
23
+ }
24
+ function getAllCodeWorkflows() {
25
+ return Array.from(codeWorkflowRegistry.values());
26
+ }
27
+ function isCodeWorkflow(workflowId) {
28
+ return codeWorkflowRegistry.has(workflowId);
29
+ }
30
+ function clearCodeWorkflowRegistry() {
31
+ codeWorkflowRegistry.clear();
32
+ }
33
+ export {
34
+ clearCodeWorkflowRegistry,
35
+ getAllCodeWorkflows,
36
+ getCodeWorkflow,
37
+ isCodeWorkflow,
38
+ registerCodeWorkflows
39
+ };
40
+ //# sourceMappingURL=code-registry.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/workflows/lib/code-registry.ts"],
4
+ "sourcesContent": ["/**\n * In-Memory Code Workflow Registry\n *\n * Stores code-based workflow definitions populated at bootstrap from\n * the generated workflows.generated.ts. Definitions live purely in memory \u2014\n * no DB row is created until a user customizes the definition.\n */\n\nimport type { CodeWorkflowDefinition } from '@open-mercato/shared/modules/workflows'\nimport { workflowDefinitionDataSchema } from '../data/validators'\n\nconst codeWorkflowRegistry = new Map<string, CodeWorkflowDefinition>()\n\n/**\n * Register code-based workflow definitions at bootstrap time.\n * Validates each definition against the Zod schema and warns on failures.\n */\nexport function registerCodeWorkflows(workflows: CodeWorkflowDefinition[]): void {\n for (const wf of workflows) {\n const validation = workflowDefinitionDataSchema.safeParse(wf.definition)\n if (!validation.success) {\n console.warn(\n `[workflows] Code workflow \"${wf.workflowId}\" failed validation:`,\n validation.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join('; '),\n )\n continue\n }\n\n if (codeWorkflowRegistry.has(wf.workflowId)) {\n console.warn(\n `[workflows] Duplicate code workflow ID \"${wf.workflowId}\" from module \"${wf.moduleId}\" \u2014 overwriting`,\n )\n }\n\n codeWorkflowRegistry.set(wf.workflowId, wf)\n }\n}\n\n/**\n * Get a single code workflow definition by workflowId.\n */\nexport function getCodeWorkflow(workflowId: string): CodeWorkflowDefinition | undefined {\n return codeWorkflowRegistry.get(workflowId)\n}\n\n/**\n * Get all registered code workflow definitions.\n */\nexport function getAllCodeWorkflows(): CodeWorkflowDefinition[] {\n return Array.from(codeWorkflowRegistry.values())\n}\n\n/**\n * Check if a workflowId is a code-based definition.\n */\nexport function isCodeWorkflow(workflowId: string): boolean {\n return codeWorkflowRegistry.has(workflowId)\n}\n\n/**\n * Clear the registry (for testing).\n */\nexport function clearCodeWorkflowRegistry(): void {\n codeWorkflowRegistry.clear()\n}\n"],
5
+ "mappings": "AASA,SAAS,oCAAoC;AAE7C,MAAM,uBAAuB,oBAAI,IAAoC;AAM9D,SAAS,sBAAsB,WAA2C;AAC/E,aAAW,MAAM,WAAW;AAC1B,UAAM,aAAa,6BAA6B,UAAU,GAAG,UAAU;AACvE,QAAI,CAAC,WAAW,SAAS;AACvB,cAAQ;AAAA,QACN,8BAA8B,GAAG,UAAU;AAAA,QAC3C,WAAW,MAAM,OAAO,IAAI,CAAC,MAAM,GAAG,EAAE,KAAK,KAAK,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI;AAAA,MACnF;AACA;AAAA,IACF;AAEA,QAAI,qBAAqB,IAAI,GAAG,UAAU,GAAG;AAC3C,cAAQ;AAAA,QACN,2CAA2C,GAAG,UAAU,kBAAkB,GAAG,QAAQ;AAAA,MACvF;AAAA,IACF;AAEA,yBAAqB,IAAI,GAAG,YAAY,EAAE;AAAA,EAC5C;AACF;AAKO,SAAS,gBAAgB,YAAwD;AACtF,SAAO,qBAAqB,IAAI,UAAU;AAC5C;AAKO,SAAS,sBAAgD;AAC9D,SAAO,MAAM,KAAK,qBAAqB,OAAO,CAAC;AACjD;AAKO,SAAS,eAAe,YAA6B;AAC1D,SAAO,qBAAqB,IAAI,UAAU;AAC5C;AAKO,SAAS,4BAAkC;AAChD,uBAAqB,MAAM;AAC7B;",
6
+ "names": []
7
+ }
@@ -0,0 +1,58 @@
1
+ import { createHash } from "node:crypto";
2
+ import { WorkflowDefinition } from "../data/entities.js";
3
+ import { getCodeWorkflow } from "./code-registry.js";
4
+ function codeWorkflowUuid(workflowId) {
5
+ const hash = createHash("sha256").update(`code-workflow:${workflowId}`).digest("hex");
6
+ return [
7
+ hash.slice(0, 8),
8
+ hash.slice(8, 12),
9
+ `4${hash.slice(13, 16)}`,
10
+ `${(parseInt(hash[16], 16) & 3 | 8).toString(16)}${hash.slice(17, 20)}`,
11
+ hash.slice(20, 32)
12
+ ].join("-");
13
+ }
14
+ async function findWorkflowDefinition(em, options) {
15
+ const { workflowId, version, tenantId, organizationId } = options;
16
+ const where = {
17
+ workflowId,
18
+ tenantId,
19
+ organizationId,
20
+ deletedAt: null
21
+ };
22
+ if (version !== void 0) {
23
+ where.version = version;
24
+ }
25
+ if (version === void 0) {
26
+ where.enabled = true;
27
+ const dbDef = await em.findOne(WorkflowDefinition, where, {
28
+ orderBy: { version: "DESC" }
29
+ });
30
+ if (dbDef) return dbDef;
31
+ } else {
32
+ const dbDef = await em.findOne(WorkflowDefinition, where);
33
+ if (dbDef) return dbDef;
34
+ }
35
+ const codeDef = getCodeWorkflow(workflowId);
36
+ if (!codeDef) return null;
37
+ if (version === void 0 && !codeDef.enabled) return null;
38
+ const virtual = new WorkflowDefinition();
39
+ virtual.id = codeWorkflowUuid(workflowId);
40
+ virtual.workflowId = codeDef.workflowId;
41
+ virtual.workflowName = codeDef.workflowName;
42
+ virtual.description = codeDef.description ?? null;
43
+ virtual.version = codeDef.version;
44
+ virtual.definition = codeDef.definition;
45
+ virtual.metadata = codeDef.metadata ?? null;
46
+ virtual.enabled = codeDef.enabled;
47
+ virtual.codeWorkflowId = codeDef.workflowId;
48
+ virtual.tenantId = tenantId;
49
+ virtual.organizationId = organizationId;
50
+ virtual.createdAt = /* @__PURE__ */ new Date(0);
51
+ virtual.updatedAt = /* @__PURE__ */ new Date(0);
52
+ return virtual;
53
+ }
54
+ export {
55
+ codeWorkflowUuid,
56
+ findWorkflowDefinition
57
+ };
58
+ //# sourceMappingURL=find-definition.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/workflows/lib/find-definition.ts"],
4
+ "sourcesContent": ["/**\n * Unified Workflow Definition Lookup\n *\n * Finds workflow definitions from the database first, falling back to the\n * in-memory code workflow registry. This enables code-based definitions to\n * be used seamlessly by the executor and validators.\n */\n\nimport { createHash } from 'node:crypto'\nimport { EntityManager } from '@mikro-orm/core'\nimport { WorkflowDefinition, type WorkflowDefinitionData } from '../data/entities'\nimport { getCodeWorkflow } from './code-registry'\n\n/**\n * Generate a deterministic UUID for a code workflow definition.\n * Uses SHA-256 truncated to UUID v4 format so the same workflowId always\n * produces the same UUID across restarts and horizontal replicas.\n */\nexport function codeWorkflowUuid(workflowId: string): string {\n const hash = createHash('sha256').update(`code-workflow:${workflowId}`).digest('hex')\n // Format as UUID v4 (set version nibble to 4, variant bits to 10xx)\n return [\n hash.slice(0, 8),\n hash.slice(8, 12),\n `4${hash.slice(13, 16)}`,\n `${(parseInt(hash[16], 16) & 0x3 | 0x8).toString(16)}${hash.slice(17, 20)}`,\n hash.slice(20, 32),\n ].join('-')\n}\n\n/**\n * Find a workflow definition by workflowId, checking the database first\n * and falling back to the code registry.\n *\n * When a DB row exists with `codeWorkflowId` set, it means the user has\n * customized the code definition \u2014 the DB version takes precedence.\n *\n * When no DB row exists but a code definition is registered, a virtual\n * WorkflowDefinition-like object is constructed with a deterministic UUID.\n */\nexport async function findWorkflowDefinition(\n em: EntityManager,\n options: {\n workflowId: string\n version?: number\n tenantId: string\n organizationId: string\n },\n): Promise<WorkflowDefinition | null> {\n const { workflowId, version, tenantId, organizationId } = options\n\n // 1. Try database first\n const where: Record<string, unknown> = {\n workflowId,\n tenantId,\n organizationId,\n deletedAt: null,\n }\n\n if (version !== undefined) {\n where.version = version\n }\n\n if (version === undefined) {\n where.enabled = true\n const dbDef = await em.findOne(WorkflowDefinition, where, {\n orderBy: { version: 'DESC' },\n })\n if (dbDef) return dbDef\n } else {\n const dbDef = await em.findOne(WorkflowDefinition, where)\n if (dbDef) return dbDef\n }\n\n // 2. Fall back to code registry (version filter not applicable to code defs)\n const codeDef = getCodeWorkflow(workflowId)\n if (!codeDef) return null\n\n // When no version was requested, mirror the DB branch's `enabled = true` filter\n // so disabled code workflows aren't silently executable.\n if (version === undefined && !codeDef.enabled) return null\n\n // Construct a virtual WorkflowDefinition object (not persisted)\n const virtual = new WorkflowDefinition()\n virtual.id = codeWorkflowUuid(workflowId)\n virtual.workflowId = codeDef.workflowId\n virtual.workflowName = codeDef.workflowName\n virtual.description = codeDef.description ?? null\n virtual.version = codeDef.version\n virtual.definition = codeDef.definition as WorkflowDefinitionData\n virtual.metadata = codeDef.metadata ?? null\n virtual.enabled = codeDef.enabled\n virtual.codeWorkflowId = codeDef.workflowId\n virtual.tenantId = tenantId\n virtual.organizationId = organizationId\n virtual.createdAt = new Date(0) // code defs have no creation date\n virtual.updatedAt = new Date(0)\n\n return virtual\n}\n"],
5
+ "mappings": "AAQA,SAAS,kBAAkB;AAE3B,SAAS,0BAAuD;AAChE,SAAS,uBAAuB;AAOzB,SAAS,iBAAiB,YAA4B;AAC3D,QAAM,OAAO,WAAW,QAAQ,EAAE,OAAO,iBAAiB,UAAU,EAAE,EAAE,OAAO,KAAK;AAEpF,SAAO;AAAA,IACL,KAAK,MAAM,GAAG,CAAC;AAAA,IACf,KAAK,MAAM,GAAG,EAAE;AAAA,IAChB,IAAI,KAAK,MAAM,IAAI,EAAE,CAAC;AAAA,IACtB,IAAI,SAAS,KAAK,EAAE,GAAG,EAAE,IAAI,IAAM,GAAK,SAAS,EAAE,CAAC,GAAG,KAAK,MAAM,IAAI,EAAE,CAAC;AAAA,IACzE,KAAK,MAAM,IAAI,EAAE;AAAA,EACnB,EAAE,KAAK,GAAG;AACZ;AAYA,eAAsB,uBACpB,IACA,SAMoC;AACpC,QAAM,EAAE,YAAY,SAAS,UAAU,eAAe,IAAI;AAG1D,QAAM,QAAiC;AAAA,IACrC;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW;AAAA,EACb;AAEA,MAAI,YAAY,QAAW;AACzB,UAAM,UAAU;AAAA,EAClB;AAEA,MAAI,YAAY,QAAW;AACzB,UAAM,UAAU;AAChB,UAAM,QAAQ,MAAM,GAAG,QAAQ,oBAAoB,OAAO;AAAA,MACxD,SAAS,EAAE,SAAS,OAAO;AAAA,IAC7B,CAAC;AACD,QAAI,MAAO,QAAO;AAAA,EACpB,OAAO;AACL,UAAM,QAAQ,MAAM,GAAG,QAAQ,oBAAoB,KAAK;AACxD,QAAI,MAAO,QAAO;AAAA,EACpB;AAGA,QAAM,UAAU,gBAAgB,UAAU;AAC1C,MAAI,CAAC,QAAS,QAAO;AAIrB,MAAI,YAAY,UAAa,CAAC,QAAQ,QAAS,QAAO;AAGtD,QAAM,UAAU,IAAI,mBAAmB;AACvC,UAAQ,KAAK,iBAAiB,UAAU;AACxC,UAAQ,aAAa,QAAQ;AAC7B,UAAQ,eAAe,QAAQ;AAC/B,UAAQ,cAAc,QAAQ,eAAe;AAC7C,UAAQ,UAAU,QAAQ;AAC1B,UAAQ,aAAa,QAAQ;AAC7B,UAAQ,WAAW,QAAQ,YAAY;AACvC,UAAQ,UAAU,QAAQ;AAC1B,UAAQ,iBAAiB,QAAQ;AACjC,UAAQ,WAAW;AACnB,UAAQ,iBAAiB;AACzB,UAAQ,YAAY,oBAAI,KAAK,CAAC;AAC9B,UAAQ,YAAY,oBAAI,KAAK,CAAC;AAE9B,SAAO;AACT;",
6
+ "names": []
7
+ }
@@ -119,12 +119,9 @@ async function seedGuardRules(em, scope, fileName) {
119
119
  return { seeded, skipped, updated };
120
120
  }
121
121
  async function seedExampleWorkflows(em, scope) {
122
- await seedWorkflowDefinition(em, scope, "checkout-demo-definition.json");
123
122
  await seedGuardRules(em, scope, "guard-rules-example.json");
124
123
  await seedWorkflowDefinition(em, scope, "sales-pipeline-definition.json");
125
- await seedWorkflowDefinition(em, scope, "simple-approval-definition.json");
126
124
  await seedGuardRules(em, scope, "order-approval-guard-rules.json");
127
- await seedWorkflowDefinition(em, scope, "order-approval-definition.json");
128
125
  }
129
126
  export {
130
127
  seedExampleWorkflows
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/workflows/lib/seeds.ts"],
4
- "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport * as fs from 'fs'\nimport * as path from 'path'\nimport { fileURLToPath } from 'node:url'\nimport { WorkflowDefinition, type WorkflowDefinitionData } from '../data/entities'\nimport { BusinessRule, type RuleType } from '@open-mercato/core/modules/business_rules/data/entities'\n\nconst __esmDirname = path.dirname(fileURLToPath(import.meta.url))\n\nexport type WorkflowSeedScope = { tenantId: string; organizationId: string }\n\ntype WorkflowSeedDefinition = {\n workflowId: string\n workflowName: string\n description?: string | null\n version?: number\n definition: WorkflowDefinitionData\n metadata?: Record<string, unknown> | null\n enabled?: boolean\n effectiveFrom?: string | null\n effectiveTo?: string | null\n createdBy?: string | null\n updatedBy?: string | null\n}\n\ntype GuardRuleSeed = {\n ruleId: string\n ruleName: string\n ruleType: RuleType\n entityType: string\n conditionExpression: unknown\n eventType?: string | null\n ruleCategory?: string | null\n description?: string | null\n successActions?: unknown\n failureActions?: unknown\n enabled?: boolean\n priority?: number\n version?: number\n effectiveFrom?: string | null\n effectiveTo?: string | null\n createdBy?: string | null\n updatedBy?: string | null\n tagsJson?: string[]\n labelsJson?: Record<string, string>\n}\n\nfunction readExampleJson<T>(fileName: string): T {\n const candidates = [\n path.join(__esmDirname, '..', 'examples', fileName),\n path.join(process.cwd(), 'packages', 'core', 'src', 'modules', 'workflows', 'examples', fileName),\n path.join(process.cwd(), 'src', 'modules', 'workflows', 'examples', fileName),\n ]\n const filePath = candidates.find((candidate) => fs.existsSync(candidate))\n if (!filePath) {\n throw new Error(`Missing workflow seed file: ${fileName}`)\n }\n return JSON.parse(fs.readFileSync(filePath, 'utf8')) as T\n}\n\nfunction requireString(value: unknown, label: string): string {\n if (typeof value === 'string' && value.trim().length > 0) return value\n throw new Error(`Invalid ${label} in workflow seed data.`)\n}\n\nasync function seedWorkflowDefinition(\n em: EntityManager,\n scope: WorkflowSeedScope,\n fileName: string,\n): Promise<boolean> {\n const seed = readExampleJson<WorkflowSeedDefinition>(fileName)\n const workflowId = requireString(seed.workflowId, 'workflowId')\n\n const existing = await em.findOne(WorkflowDefinition, {\n workflowId,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n })\n\n if (existing) {\n // Check if the definition needs to be updated by comparing steps and transitions\n const seedStepCount = seed.definition.steps.length\n const existingStepCount = existing.definition.steps.length\n const seedTransitionCount = seed.definition.transitions.length\n const existingTransitionCount = existing.definition.transitions.length\n\n // Check for preConditions on transitions\n const seedHasTransitionPreConditions = seed.definition.transitions.some(\n (t: any) => t.preConditions && t.preConditions.length > 0\n )\n const existingHasTransitionPreConditions = existing.definition.transitions.some(\n (t: any) => t.preConditions && t.preConditions.length > 0\n )\n\n // Check for preConditions on START step\n const seedStartStep = seed.definition.steps.find((s: any) => s.stepType === 'START')\n const existingStartStep = existing.definition.steps.find((s: any) => s.stepType === 'START')\n const seedHasStartPreConditions = seedStartStep?.preConditions && seedStartStep.preConditions.length > 0\n const existingHasStartPreConditions = existingStartStep?.preConditions && existingStartStep.preConditions.length > 0\n\n // Update if structure has changed\n const needsUpdate =\n seedStepCount !== existingStepCount ||\n seedTransitionCount !== existingTransitionCount ||\n (seedHasStartPreConditions && !existingHasStartPreConditions) ||\n (seedHasTransitionPreConditions && !existingHasTransitionPreConditions)\n\n if (needsUpdate) {\n console.log(`[seed] Updating workflow ${workflowId} (steps: ${existingStepCount}\u2192${seedStepCount}, transitions: ${existingTransitionCount}\u2192${seedTransitionCount})`)\n existing.definition = seed.definition\n await em.flush()\n return true\n }\n\n return false\n }\n\n const workflow = em.create(WorkflowDefinition, {\n ...seed,\n workflowId,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n })\n em.persist(workflow)\n await em.flush()\n return true\n}\n\nasync function seedGuardRules(\n em: EntityManager,\n scope: WorkflowSeedScope,\n fileName: string,\n): Promise<{ seeded: number; skipped: number; updated: number }> {\n const seeds = readExampleJson<GuardRuleSeed[]>(fileName)\n if (!Array.isArray(seeds)) {\n throw new Error('Invalid guard rules seed data.')\n }\n\n let seeded = 0\n let skipped = 0\n let updated = 0\n for (const rule of seeds) {\n const ruleId = requireString(rule.ruleId, 'ruleId')\n const existing = await em.findOne(BusinessRule, {\n ruleId,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n })\n if (existing) {\n // Check if entityType or eventType needs updating\n const needsUpdate = existing.entityType !== rule.entityType || existing.eventType !== rule.eventType\n if (needsUpdate) {\n console.log(`[seed] Updating business rule ${ruleId}: entityType=${rule.entityType}, eventType=${rule.eventType}`)\n existing.entityType = rule.entityType\n existing.eventType = rule.eventType ?? null\n updated += 1\n } else {\n skipped += 1\n }\n continue\n }\n const entry = em.create(BusinessRule, {\n ruleId,\n ruleName: rule.ruleName,\n ruleType: rule.ruleType,\n entityType: rule.entityType,\n conditionExpression: rule.conditionExpression,\n eventType: rule.eventType,\n ruleCategory: rule.ruleCategory,\n description: rule.description,\n successActions: rule.successActions,\n failureActions: rule.failureActions,\n enabled: rule.enabled,\n priority: rule.priority,\n version: rule.version,\n effectiveFrom: rule.effectiveFrom,\n effectiveTo: rule.effectiveTo,\n createdBy: rule.createdBy,\n updatedBy: rule.updatedBy,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n })\n em.persist(entry)\n seeded += 1\n }\n if (seeded > 0 || updated > 0) {\n await em.flush()\n }\n return { seeded, skipped, updated }\n}\n\nexport async function seedExampleWorkflows(em: EntityManager, scope: WorkflowSeedScope): Promise<void> {\n await seedWorkflowDefinition(em, scope, 'checkout-demo-definition.json')\n await seedGuardRules(em, scope, 'guard-rules-example.json')\n await seedWorkflowDefinition(em, scope, 'sales-pipeline-definition.json')\n await seedWorkflowDefinition(em, scope, 'simple-approval-definition.json')\n await seedGuardRules(em, scope, 'order-approval-guard-rules.json')\n await seedWorkflowDefinition(em, scope, 'order-approval-definition.json')\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport * as fs from 'fs'\nimport * as path from 'path'\nimport { fileURLToPath } from 'node:url'\nimport { WorkflowDefinition, type WorkflowDefinitionData } from '../data/entities'\nimport { BusinessRule, type RuleType } from '@open-mercato/core/modules/business_rules/data/entities'\n\nconst __esmDirname = path.dirname(fileURLToPath(import.meta.url))\n\nexport type WorkflowSeedScope = { tenantId: string; organizationId: string }\n\ntype WorkflowSeedDefinition = {\n workflowId: string\n workflowName: string\n description?: string | null\n version?: number\n definition: WorkflowDefinitionData\n metadata?: Record<string, unknown> | null\n enabled?: boolean\n effectiveFrom?: string | null\n effectiveTo?: string | null\n createdBy?: string | null\n updatedBy?: string | null\n}\n\ntype GuardRuleSeed = {\n ruleId: string\n ruleName: string\n ruleType: RuleType\n entityType: string\n conditionExpression: unknown\n eventType?: string | null\n ruleCategory?: string | null\n description?: string | null\n successActions?: unknown\n failureActions?: unknown\n enabled?: boolean\n priority?: number\n version?: number\n effectiveFrom?: string | null\n effectiveTo?: string | null\n createdBy?: string | null\n updatedBy?: string | null\n tagsJson?: string[]\n labelsJson?: Record<string, string>\n}\n\nfunction readExampleJson<T>(fileName: string): T {\n const candidates = [\n path.join(__esmDirname, '..', 'examples', fileName),\n path.join(process.cwd(), 'packages', 'core', 'src', 'modules', 'workflows', 'examples', fileName),\n path.join(process.cwd(), 'src', 'modules', 'workflows', 'examples', fileName),\n ]\n const filePath = candidates.find((candidate) => fs.existsSync(candidate))\n if (!filePath) {\n throw new Error(`Missing workflow seed file: ${fileName}`)\n }\n return JSON.parse(fs.readFileSync(filePath, 'utf8')) as T\n}\n\nfunction requireString(value: unknown, label: string): string {\n if (typeof value === 'string' && value.trim().length > 0) return value\n throw new Error(`Invalid ${label} in workflow seed data.`)\n}\n\nasync function seedWorkflowDefinition(\n em: EntityManager,\n scope: WorkflowSeedScope,\n fileName: string,\n): Promise<boolean> {\n const seed = readExampleJson<WorkflowSeedDefinition>(fileName)\n const workflowId = requireString(seed.workflowId, 'workflowId')\n\n const existing = await em.findOne(WorkflowDefinition, {\n workflowId,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n })\n\n if (existing) {\n // Check if the definition needs to be updated by comparing steps and transitions\n const seedStepCount = seed.definition.steps.length\n const existingStepCount = existing.definition.steps.length\n const seedTransitionCount = seed.definition.transitions.length\n const existingTransitionCount = existing.definition.transitions.length\n\n // Check for preConditions on transitions\n const seedHasTransitionPreConditions = seed.definition.transitions.some(\n (t: any) => t.preConditions && t.preConditions.length > 0\n )\n const existingHasTransitionPreConditions = existing.definition.transitions.some(\n (t: any) => t.preConditions && t.preConditions.length > 0\n )\n\n // Check for preConditions on START step\n const seedStartStep = seed.definition.steps.find((s: any) => s.stepType === 'START')\n const existingStartStep = existing.definition.steps.find((s: any) => s.stepType === 'START')\n const seedHasStartPreConditions = seedStartStep?.preConditions && seedStartStep.preConditions.length > 0\n const existingHasStartPreConditions = existingStartStep?.preConditions && existingStartStep.preConditions.length > 0\n\n // Update if structure has changed\n const needsUpdate =\n seedStepCount !== existingStepCount ||\n seedTransitionCount !== existingTransitionCount ||\n (seedHasStartPreConditions && !existingHasStartPreConditions) ||\n (seedHasTransitionPreConditions && !existingHasTransitionPreConditions)\n\n if (needsUpdate) {\n console.log(`[seed] Updating workflow ${workflowId} (steps: ${existingStepCount}\u2192${seedStepCount}, transitions: ${existingTransitionCount}\u2192${seedTransitionCount})`)\n existing.definition = seed.definition\n await em.flush()\n return true\n }\n\n return false\n }\n\n const workflow = em.create(WorkflowDefinition, {\n ...seed,\n workflowId,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n })\n em.persist(workflow)\n await em.flush()\n return true\n}\n\nasync function seedGuardRules(\n em: EntityManager,\n scope: WorkflowSeedScope,\n fileName: string,\n): Promise<{ seeded: number; skipped: number; updated: number }> {\n const seeds = readExampleJson<GuardRuleSeed[]>(fileName)\n if (!Array.isArray(seeds)) {\n throw new Error('Invalid guard rules seed data.')\n }\n\n let seeded = 0\n let skipped = 0\n let updated = 0\n for (const rule of seeds) {\n const ruleId = requireString(rule.ruleId, 'ruleId')\n const existing = await em.findOne(BusinessRule, {\n ruleId,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n })\n if (existing) {\n // Check if entityType or eventType needs updating\n const needsUpdate = existing.entityType !== rule.entityType || existing.eventType !== rule.eventType\n if (needsUpdate) {\n console.log(`[seed] Updating business rule ${ruleId}: entityType=${rule.entityType}, eventType=${rule.eventType}`)\n existing.entityType = rule.entityType\n existing.eventType = rule.eventType ?? null\n updated += 1\n } else {\n skipped += 1\n }\n continue\n }\n const entry = em.create(BusinessRule, {\n ruleId,\n ruleName: rule.ruleName,\n ruleType: rule.ruleType,\n entityType: rule.entityType,\n conditionExpression: rule.conditionExpression,\n eventType: rule.eventType,\n ruleCategory: rule.ruleCategory,\n description: rule.description,\n successActions: rule.successActions,\n failureActions: rule.failureActions,\n enabled: rule.enabled,\n priority: rule.priority,\n version: rule.version,\n effectiveFrom: rule.effectiveFrom,\n effectiveTo: rule.effectiveTo,\n createdBy: rule.createdBy,\n updatedBy: rule.updatedBy,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n })\n em.persist(entry)\n seeded += 1\n }\n if (seeded > 0 || updated > 0) {\n await em.flush()\n }\n return { seeded, skipped, updated }\n}\n\nexport async function seedExampleWorkflows(em: EntityManager, scope: WorkflowSeedScope): Promise<void> {\n // workflows.checkout-demo and workflows.simple-approval are now code-defined\n // (see packages/core/src/modules/workflows/workflows.ts). Seeding DB rows for\n // them would shadow the code definitions in the merge layer, so they are no\n // longer seeded here. Existing tenants are migrated via Migration20260428102318.\n await seedGuardRules(em, scope, 'guard-rules-example.json')\n await seedWorkflowDefinition(em, scope, 'sales-pipeline-definition.json')\n await seedGuardRules(em, scope, 'order-approval-guard-rules.json')\n}\n"],
5
+ "mappings": "AACA,YAAY,QAAQ;AACpB,YAAY,UAAU;AACtB,SAAS,qBAAqB;AAC9B,SAAS,0BAAuD;AAChE,SAAS,oBAAmC;AAE5C,MAAM,eAAe,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC;AAwChE,SAAS,gBAAmB,UAAqB;AAC/C,QAAM,aAAa;AAAA,IACjB,KAAK,KAAK,cAAc,MAAM,YAAY,QAAQ;AAAA,IAClD,KAAK,KAAK,QAAQ,IAAI,GAAG,YAAY,QAAQ,OAAO,WAAW,aAAa,YAAY,QAAQ;AAAA,IAChG,KAAK,KAAK,QAAQ,IAAI,GAAG,OAAO,WAAW,aAAa,YAAY,QAAQ;AAAA,EAC9E;AACA,QAAM,WAAW,WAAW,KAAK,CAAC,cAAc,GAAG,WAAW,SAAS,CAAC;AACxE,MAAI,CAAC,UAAU;AACb,UAAM,IAAI,MAAM,+BAA+B,QAAQ,EAAE;AAAA,EAC3D;AACA,SAAO,KAAK,MAAM,GAAG,aAAa,UAAU,MAAM,CAAC;AACrD;AAEA,SAAS,cAAc,OAAgB,OAAuB;AAC5D,MAAI,OAAO,UAAU,YAAY,MAAM,KAAK,EAAE,SAAS,EAAG,QAAO;AACjE,QAAM,IAAI,MAAM,WAAW,KAAK,yBAAyB;AAC3D;AAEA,eAAe,uBACb,IACA,OACA,UACkB;AAClB,QAAM,OAAO,gBAAwC,QAAQ;AAC7D,QAAM,aAAa,cAAc,KAAK,YAAY,YAAY;AAE9D,QAAM,WAAW,MAAM,GAAG,QAAQ,oBAAoB;AAAA,IACpD;AAAA,IACA,UAAU,MAAM;AAAA,IAChB,gBAAgB,MAAM;AAAA,EACxB,CAAC;AAED,MAAI,UAAU;AAEZ,UAAM,gBAAgB,KAAK,WAAW,MAAM;AAC5C,UAAM,oBAAoB,SAAS,WAAW,MAAM;AACpD,UAAM,sBAAsB,KAAK,WAAW,YAAY;AACxD,UAAM,0BAA0B,SAAS,WAAW,YAAY;AAGhE,UAAM,iCAAiC,KAAK,WAAW,YAAY;AAAA,MACjE,CAAC,MAAW,EAAE,iBAAiB,EAAE,cAAc,SAAS;AAAA,IAC1D;AACA,UAAM,qCAAqC,SAAS,WAAW,YAAY;AAAA,MACzE,CAAC,MAAW,EAAE,iBAAiB,EAAE,cAAc,SAAS;AAAA,IAC1D;AAGA,UAAM,gBAAgB,KAAK,WAAW,MAAM,KAAK,CAAC,MAAW,EAAE,aAAa,OAAO;AACnF,UAAM,oBAAoB,SAAS,WAAW,MAAM,KAAK,CAAC,MAAW,EAAE,aAAa,OAAO;AAC3F,UAAM,4BAA4B,eAAe,iBAAiB,cAAc,cAAc,SAAS;AACvG,UAAM,gCAAgC,mBAAmB,iBAAiB,kBAAkB,cAAc,SAAS;AAGnH,UAAM,cACJ,kBAAkB,qBAClB,wBAAwB,2BACvB,6BAA6B,CAAC,iCAC9B,kCAAkC,CAAC;AAEtC,QAAI,aAAa;AACf,cAAQ,IAAI,4BAA4B,UAAU,YAAY,iBAAiB,SAAI,aAAa,kBAAkB,uBAAuB,SAAI,mBAAmB,GAAG;AACnK,eAAS,aAAa,KAAK;AAC3B,YAAM,GAAG,MAAM;AACf,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,GAAG,OAAO,oBAAoB;AAAA,IAC7C,GAAG;AAAA,IACH;AAAA,IACA,UAAU,MAAM;AAAA,IAChB,gBAAgB,MAAM;AAAA,EACxB,CAAC;AACD,KAAG,QAAQ,QAAQ;AACnB,QAAM,GAAG,MAAM;AACf,SAAO;AACT;AAEA,eAAe,eACb,IACA,OACA,UAC+D;AAC/D,QAAM,QAAQ,gBAAiC,QAAQ;AACvD,MAAI,CAAC,MAAM,QAAQ,KAAK,GAAG;AACzB,UAAM,IAAI,MAAM,gCAAgC;AAAA,EAClD;AAEA,MAAI,SAAS;AACb,MAAI,UAAU;AACd,MAAI,UAAU;AACd,aAAW,QAAQ,OAAO;AACxB,UAAM,SAAS,cAAc,KAAK,QAAQ,QAAQ;AAClD,UAAM,WAAW,MAAM,GAAG,QAAQ,cAAc;AAAA,MAC9C;AAAA,MACA,UAAU,MAAM;AAAA,MAChB,gBAAgB,MAAM;AAAA,IACxB,CAAC;AACD,QAAI,UAAU;AAEZ,YAAM,cAAc,SAAS,eAAe,KAAK,cAAc,SAAS,cAAc,KAAK;AAC3F,UAAI,aAAa;AACf,gBAAQ,IAAI,iCAAiC,MAAM,gBAAgB,KAAK,UAAU,eAAe,KAAK,SAAS,EAAE;AACjH,iBAAS,aAAa,KAAK;AAC3B,iBAAS,YAAY,KAAK,aAAa;AACvC,mBAAW;AAAA,MACb,OAAO;AACL,mBAAW;AAAA,MACb;AACA;AAAA,IACF;AACA,UAAM,QAAQ,GAAG,OAAO,cAAc;AAAA,MACpC;AAAA,MACA,UAAU,KAAK;AAAA,MACf,UAAU,KAAK;AAAA,MACf,YAAY,KAAK;AAAA,MACjB,qBAAqB,KAAK;AAAA,MAC1B,WAAW,KAAK;AAAA,MAChB,cAAc,KAAK;AAAA,MACnB,aAAa,KAAK;AAAA,MAClB,gBAAgB,KAAK;AAAA,MACrB,gBAAgB,KAAK;AAAA,MACrB,SAAS,KAAK;AAAA,MACd,UAAU,KAAK;AAAA,MACf,SAAS,KAAK;AAAA,MACd,eAAe,KAAK;AAAA,MACpB,aAAa,KAAK;AAAA,MAClB,WAAW,KAAK;AAAA,MAChB,WAAW,KAAK;AAAA,MAChB,UAAU,MAAM;AAAA,MAChB,gBAAgB,MAAM;AAAA,IACxB,CAAC;AACD,OAAG,QAAQ,KAAK;AAChB,cAAU;AAAA,EACZ;AACA,MAAI,SAAS,KAAK,UAAU,GAAG;AAC7B,UAAM,GAAG,MAAM;AAAA,EACjB;AACA,SAAO,EAAE,QAAQ,SAAS,QAAQ;AACpC;AAEA,eAAsB,qBAAqB,IAAmB,OAAyC;AAKrG,QAAM,eAAe,IAAI,OAAO,0BAA0B;AAC1D,QAAM,uBAAuB,IAAI,OAAO,gCAAgC;AACxE,QAAM,eAAe,IAAI,OAAO,iCAAiC;AACnE;",
6
6
  "names": []
7
7
  }
@@ -1,5 +1,5 @@
1
- import { WorkflowDefinition } from "../data/entities.js";
2
1
  import * as ruleEngine from "../../business_rules/lib/rule-engine.js";
2
+ import { findWorkflowDefinition } from "./find-definition.js";
3
3
  async function validateWorkflowStart(em, options) {
4
4
  const { workflowId, version, context, locale = "en", tenantId, organizationId } = options;
5
5
  const definition = await findWorkflowDefinition(em, {
@@ -148,25 +148,6 @@ function getLocalizedMessage(condition, rule, locale, defaultMessage) {
148
148
  }
149
149
  return defaultMessage;
150
150
  }
151
- async function findWorkflowDefinition(em, options) {
152
- const { workflowId, version, tenantId, organizationId } = options;
153
- const where = {
154
- workflowId,
155
- tenantId,
156
- organizationId,
157
- deletedAt: null
158
- };
159
- if (version !== void 0) {
160
- where.version = version;
161
- }
162
- if (version === void 0) {
163
- where.enabled = true;
164
- return em.findOne(WorkflowDefinition, where, {
165
- orderBy: { version: "DESC" }
166
- });
167
- }
168
- return em.findOne(WorkflowDefinition, where);
169
- }
170
151
  export {
171
152
  validateWorkflowStart
172
153
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/workflows/lib/start-validator.ts"],
4
- "sourcesContent": ["/**\n * Workflows Module - Start Validator Service\n *\n * Validates pre-conditions on START step before workflow instance creation.\n * This enables guard rules that determine whether a workflow can be started\n * based on the initial context provided.\n */\n\nimport { EntityManager } from '@mikro-orm/core'\nimport { WorkflowDefinition } from '../data/entities'\nimport * as ruleEngine from '../../business_rules/lib/rule-engine'\nimport type { StartPreCondition } from '../data/validators'\n\n// ============================================================================\n// Types and Interfaces\n// ============================================================================\n\nexport interface ValidateStartOptions {\n workflowId: string\n version?: number\n context: Record<string, any>\n locale?: string\n tenantId: string\n organizationId: string\n}\n\nexport interface ValidationError {\n ruleId: string\n message: string\n code: string\n}\n\nexport interface ValidatedRule {\n ruleId: string\n passed: boolean\n executionTime?: number\n}\n\nexport interface ValidateStartResult {\n canStart: boolean\n errors: ValidationError[]\n validatedRules: ValidatedRule[]\n}\n\n// ============================================================================\n// Main Validation Function\n// ============================================================================\n\n/**\n * Validate if a workflow can be started with the given context\n *\n * @param em - Entity manager for database operations\n * @param options - Validation options including workflowId, context, and scope\n * @returns Validation result with canStart flag, errors, and validated rules\n */\nexport async function validateWorkflowStart(\n em: EntityManager,\n options: ValidateStartOptions\n): Promise<ValidateStartResult> {\n const { workflowId, version, context, locale = 'en', tenantId, organizationId } = options\n\n // Find workflow definition\n const definition = await findWorkflowDefinition(em, {\n workflowId,\n version,\n tenantId,\n organizationId,\n })\n\n if (!definition) {\n return {\n canStart: false,\n errors: [{\n ruleId: '_DEFINITION_NOT_FOUND',\n message: `Workflow definition not found: ${workflowId}`,\n code: 'DEFINITION_NOT_FOUND',\n }],\n validatedRules: [],\n }\n }\n\n if (!definition.enabled) {\n return {\n canStart: false,\n errors: [{\n ruleId: '_DEFINITION_DISABLED',\n message: `Workflow is disabled: ${workflowId}`,\n code: 'DEFINITION_DISABLED',\n }],\n validatedRules: [],\n }\n }\n\n // Find START step and get pre-conditions\n const startStep = definition.definition.steps.find(\n (s: any) => s.stepType === 'START'\n )\n\n if (!startStep) {\n return {\n canStart: false,\n errors: [{\n ruleId: '_NO_START_STEP',\n message: 'Workflow has no START step',\n code: 'INVALID_DEFINITION',\n }],\n validatedRules: [],\n }\n }\n\n const preConditions: StartPreCondition[] = startStep.preConditions || []\n\n console.log('[start-validator] START step:', JSON.stringify(startStep, null, 2))\n console.log('[start-validator] preConditions:', preConditions.length, JSON.stringify(preConditions))\n\n // If no pre-conditions, workflow can start\n if (preConditions.length === 0) {\n console.log('[start-validator] No pre-conditions defined, allowing start')\n return {\n canStart: true,\n errors: [],\n validatedRules: [],\n }\n }\n\n // Evaluate each pre-condition using rule engine\n const errors: ValidationError[] = []\n const validatedRules: ValidatedRule[] = []\n\n for (const condition of preConditions) {\n // Execute rule directly by string rule_id\n const result = await ruleEngine.executeRuleByRuleId(em, {\n ruleId: condition.ruleId, // String identifier like \"workflow_checkout_inventory_available\"\n data: {\n workflowId,\n workflowContext: context,\n },\n tenantId,\n organizationId,\n entityType: `workflow:${workflowId}:start`,\n entityId: 'pre_start_validation',\n eventType: 'validate_start',\n dryRun: true, // Don't log execution during validation\n })\n\n validatedRules.push({\n ruleId: condition.ruleId,\n passed: result.conditionResult,\n executionTime: result.executionTime,\n })\n\n // Handle rule not found\n if (result.error === 'Rule not found') {\n if (condition.required) {\n errors.push({\n ruleId: condition.ruleId,\n message: getLocalizedMessage(condition, null, locale, `Business rule not found: ${condition.ruleId}`),\n code: 'RULE_NOT_FOUND',\n })\n }\n continue\n }\n\n // Handle disabled rule\n if (result.error === 'Rule is disabled') {\n if (condition.required) {\n errors.push({\n ruleId: condition.ruleId,\n message: getLocalizedMessage(condition, null, locale, `Business rule is disabled: ${result.ruleName}`),\n code: 'RULE_DISABLED',\n })\n }\n continue\n }\n\n // Handle other errors (not yet effective, expired, etc.)\n if (result.error && condition.required) {\n errors.push({\n ruleId: condition.ruleId,\n message: getLocalizedMessage(condition, null, locale, `Rule error: ${result.error}`),\n code: 'RULE_ERROR',\n })\n continue\n }\n\n // Handle condition failure\n if (!result.conditionResult && condition.required) {\n // Get localized message from condition or use default with rule name\n const message = getLocalizedMessage(\n condition,\n null,\n locale,\n `Pre-condition '${result.ruleName || condition.ruleId}' failed`\n )\n errors.push({\n ruleId: condition.ruleId,\n message,\n code: 'PRE_CONDITION_FAILED',\n })\n }\n }\n\n return {\n canStart: errors.length === 0,\n errors,\n validatedRules,\n }\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Get localized message with fallback chain\n *\n * Priority:\n * 1. condition.validationMessage[locale]\n * 2. condition.validationMessage['en']\n * 3. rule.failureActions[BLOCK_TRANSITION].config.message\n * 4. rule.description\n * 5. defaultMessage\n */\nfunction getLocalizedMessage(\n condition: StartPreCondition,\n rule: any | null,\n locale: string,\n defaultMessage: string\n): string {\n // Priority 1: Localized message in condition definition (requested locale)\n if (condition.validationMessage?.[locale]) {\n return condition.validationMessage[locale]\n }\n\n // Priority 2: English fallback in condition\n if (condition.validationMessage?.['en']) {\n return condition.validationMessage['en']\n }\n\n if (rule) {\n // Priority 3: Message from rule's failureActions\n if (rule.failureActions && Array.isArray(rule.failureActions)) {\n const blockAction = rule.failureActions.find(\n (a: any) => a.type === 'BLOCK_TRANSITION'\n )\n if (blockAction?.config?.message) {\n return blockAction.config.message\n }\n }\n\n // Priority 4: Rule description\n if (rule.description) {\n return rule.description\n }\n }\n\n // Priority 5: Default message\n return defaultMessage\n}\n\n/**\n * Find workflow definition by ID and optional version\n */\nasync function findWorkflowDefinition(\n em: EntityManager,\n options: {\n workflowId: string\n version?: number\n tenantId: string\n organizationId: string\n }\n): Promise<WorkflowDefinition | null> {\n const { workflowId, version, tenantId, organizationId } = options\n\n const where: any = {\n workflowId,\n tenantId,\n organizationId,\n deletedAt: null,\n }\n\n if (version !== undefined) {\n where.version = version\n }\n\n // If no version specified, get latest enabled version\n if (version === undefined) {\n where.enabled = true\n return em.findOne(WorkflowDefinition, where, {\n orderBy: { version: 'DESC' },\n })\n }\n\n return em.findOne(WorkflowDefinition, where)\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Workflows Module - Start Validator Service\n *\n * Validates pre-conditions on START step before workflow instance creation.\n * This enables guard rules that determine whether a workflow can be started\n * based on the initial context provided.\n */\n\nimport { EntityManager } from '@mikro-orm/core'\nimport { WorkflowDefinition } from '../data/entities'\nimport * as ruleEngine from '../../business_rules/lib/rule-engine'\nimport { findWorkflowDefinition } from './find-definition'\nimport type { StartPreCondition } from '../data/validators'\n\n// ============================================================================\n// Types and Interfaces\n// ============================================================================\n\nexport interface ValidateStartOptions {\n workflowId: string\n version?: number\n context: Record<string, any>\n locale?: string\n tenantId: string\n organizationId: string\n}\n\nexport interface ValidationError {\n ruleId: string\n message: string\n code: string\n}\n\nexport interface ValidatedRule {\n ruleId: string\n passed: boolean\n executionTime?: number\n}\n\nexport interface ValidateStartResult {\n canStart: boolean\n errors: ValidationError[]\n validatedRules: ValidatedRule[]\n}\n\n// ============================================================================\n// Main Validation Function\n// ============================================================================\n\n/**\n * Validate if a workflow can be started with the given context\n *\n * @param em - Entity manager for database operations\n * @param options - Validation options including workflowId, context, and scope\n * @returns Validation result with canStart flag, errors, and validated rules\n */\nexport async function validateWorkflowStart(\n em: EntityManager,\n options: ValidateStartOptions\n): Promise<ValidateStartResult> {\n const { workflowId, version, context, locale = 'en', tenantId, organizationId } = options\n\n // Find workflow definition\n const definition = await findWorkflowDefinition(em, {\n workflowId,\n version,\n tenantId,\n organizationId,\n })\n\n if (!definition) {\n return {\n canStart: false,\n errors: [{\n ruleId: '_DEFINITION_NOT_FOUND',\n message: `Workflow definition not found: ${workflowId}`,\n code: 'DEFINITION_NOT_FOUND',\n }],\n validatedRules: [],\n }\n }\n\n if (!definition.enabled) {\n return {\n canStart: false,\n errors: [{\n ruleId: '_DEFINITION_DISABLED',\n message: `Workflow is disabled: ${workflowId}`,\n code: 'DEFINITION_DISABLED',\n }],\n validatedRules: [],\n }\n }\n\n // Find START step and get pre-conditions\n const startStep = definition.definition.steps.find(\n (s: any) => s.stepType === 'START'\n )\n\n if (!startStep) {\n return {\n canStart: false,\n errors: [{\n ruleId: '_NO_START_STEP',\n message: 'Workflow has no START step',\n code: 'INVALID_DEFINITION',\n }],\n validatedRules: [],\n }\n }\n\n const preConditions: StartPreCondition[] = startStep.preConditions || []\n\n console.log('[start-validator] START step:', JSON.stringify(startStep, null, 2))\n console.log('[start-validator] preConditions:', preConditions.length, JSON.stringify(preConditions))\n\n // If no pre-conditions, workflow can start\n if (preConditions.length === 0) {\n console.log('[start-validator] No pre-conditions defined, allowing start')\n return {\n canStart: true,\n errors: [],\n validatedRules: [],\n }\n }\n\n // Evaluate each pre-condition using rule engine\n const errors: ValidationError[] = []\n const validatedRules: ValidatedRule[] = []\n\n for (const condition of preConditions) {\n // Execute rule directly by string rule_id\n const result = await ruleEngine.executeRuleByRuleId(em, {\n ruleId: condition.ruleId, // String identifier like \"workflow_checkout_inventory_available\"\n data: {\n workflowId,\n workflowContext: context,\n },\n tenantId,\n organizationId,\n entityType: `workflow:${workflowId}:start`,\n entityId: 'pre_start_validation',\n eventType: 'validate_start',\n dryRun: true, // Don't log execution during validation\n })\n\n validatedRules.push({\n ruleId: condition.ruleId,\n passed: result.conditionResult,\n executionTime: result.executionTime,\n })\n\n // Handle rule not found\n if (result.error === 'Rule not found') {\n if (condition.required) {\n errors.push({\n ruleId: condition.ruleId,\n message: getLocalizedMessage(condition, null, locale, `Business rule not found: ${condition.ruleId}`),\n code: 'RULE_NOT_FOUND',\n })\n }\n continue\n }\n\n // Handle disabled rule\n if (result.error === 'Rule is disabled') {\n if (condition.required) {\n errors.push({\n ruleId: condition.ruleId,\n message: getLocalizedMessage(condition, null, locale, `Business rule is disabled: ${result.ruleName}`),\n code: 'RULE_DISABLED',\n })\n }\n continue\n }\n\n // Handle other errors (not yet effective, expired, etc.)\n if (result.error && condition.required) {\n errors.push({\n ruleId: condition.ruleId,\n message: getLocalizedMessage(condition, null, locale, `Rule error: ${result.error}`),\n code: 'RULE_ERROR',\n })\n continue\n }\n\n // Handle condition failure\n if (!result.conditionResult && condition.required) {\n // Get localized message from condition or use default with rule name\n const message = getLocalizedMessage(\n condition,\n null,\n locale,\n `Pre-condition '${result.ruleName || condition.ruleId}' failed`\n )\n errors.push({\n ruleId: condition.ruleId,\n message,\n code: 'PRE_CONDITION_FAILED',\n })\n }\n }\n\n return {\n canStart: errors.length === 0,\n errors,\n validatedRules,\n }\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Get localized message with fallback chain\n *\n * Priority:\n * 1. condition.validationMessage[locale]\n * 2. condition.validationMessage['en']\n * 3. rule.failureActions[BLOCK_TRANSITION].config.message\n * 4. rule.description\n * 5. defaultMessage\n */\nfunction getLocalizedMessage(\n condition: StartPreCondition,\n rule: any | null,\n locale: string,\n defaultMessage: string\n): string {\n // Priority 1: Localized message in condition definition (requested locale)\n if (condition.validationMessage?.[locale]) {\n return condition.validationMessage[locale]\n }\n\n // Priority 2: English fallback in condition\n if (condition.validationMessage?.['en']) {\n return condition.validationMessage['en']\n }\n\n if (rule) {\n // Priority 3: Message from rule's failureActions\n if (rule.failureActions && Array.isArray(rule.failureActions)) {\n const blockAction = rule.failureActions.find(\n (a: any) => a.type === 'BLOCK_TRANSITION'\n )\n if (blockAction?.config?.message) {\n return blockAction.config.message\n }\n }\n\n // Priority 4: Rule description\n if (rule.description) {\n return rule.description\n }\n }\n\n // Priority 5: Default message\n return defaultMessage\n}\n\n// findWorkflowDefinition is imported from ./find-definition\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -5,6 +5,7 @@ import {
5
5
  WorkflowEvent
6
6
  } from "../data/entities.js";
7
7
  import { compensateWorkflow } from "./compensation-handler.js";
8
+ import { findWorkflowDefinition } from "./find-definition.js";
8
9
  class WorkflowExecutionError extends Error {
9
10
  constructor(message, code, details) {
10
11
  super(message);
@@ -613,25 +614,6 @@ async function updateWorkflowContext(em, instanceId, updates) {
613
614
  instance.updatedAt = /* @__PURE__ */ new Date();
614
615
  await em.flush();
615
616
  }
616
- async function findWorkflowDefinition(em, options) {
617
- const { workflowId, version, tenantId, organizationId } = options;
618
- const where = {
619
- workflowId,
620
- tenantId,
621
- organizationId,
622
- deletedAt: null
623
- };
624
- if (version !== void 0) {
625
- where.version = version;
626
- }
627
- if (version === void 0) {
628
- where.enabled = true;
629
- return em.findOne(WorkflowDefinition, where, {
630
- orderBy: { version: "DESC" }
631
- });
632
- }
633
- return em.findOne(WorkflowDefinition, where);
634
- }
635
617
  async function logWorkflowEvent(em, event) {
636
618
  const workflowEvent = em.create(WorkflowEvent, {
637
619
  ...event,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/workflows/lib/workflow-executor.ts"],
4
- "sourcesContent": ["/**\n * Workflows Module - Workflow Executor Service\n *\n * Main orchestrator for workflow execution. Handles workflow lifecycle:\n * - Starting workflow instances from definitions\n * - Executing workflow steps and transitions\n * - Completing workflows with final status\n * - Triggering compensation on failure\n *\n * Functional API (no classes) following Open Mercato conventions.\n */\n\nimport { EntityManager, LockMode } from '@mikro-orm/core'\nimport type { AwilixContainer } from 'awilix'\nimport {\n WorkflowDefinition,\n WorkflowInstance,\n WorkflowEvent,\n type WorkflowInstanceStatus,\n} from '../data/entities'\nimport { compensateWorkflow } from './compensation-handler'\n\n// ============================================================================\n// Types and Interfaces\n// ============================================================================\n\nexport interface StartWorkflowOptions {\n workflowId: string\n version?: number // Default to latest enabled version\n initialContext?: Record<string, any>\n correlationKey?: string\n metadata?: {\n entityType?: string\n entityId?: string\n initiatedBy?: string\n labels?: Record<string, string>\n }\n tenantId: string\n organizationId: string\n}\n\nexport interface ExecutionContext {\n userId?: string\n dryRun?: boolean\n timeout?: number\n}\n\nexport interface ExecutionResult {\n status: WorkflowInstanceStatus\n currentStep: string\n context: Record<string, any>\n events: WorkflowEventSummary[]\n errors?: string[]\n executionTime: number\n}\n\nexport interface WorkflowEventSummary {\n eventType: string\n occurredAt: Date\n data?: any\n}\n\nexport class WorkflowExecutionError extends Error {\n constructor(\n message: string,\n public code: string,\n public details?: any\n ) {\n super(message)\n this.name = 'WorkflowExecutionError'\n }\n}\n\n// ============================================================================\n// Main Orchestration Functions\n// ============================================================================\n\n/**\n * Start a new workflow instance from a definition\n *\n * @param em - Entity manager for database operations\n * @param options - Workflow start options\n * @returns Created workflow instance\n * @throws WorkflowExecutionError if definition not found or validation fails\n */\nexport async function startWorkflow(\n em: EntityManager,\n options: StartWorkflowOptions\n): Promise<WorkflowInstance> {\n const {\n workflowId,\n version,\n initialContext = {},\n correlationKey,\n metadata,\n tenantId,\n organizationId,\n } = options\n\n // Find workflow definition\n const definition = await findWorkflowDefinition(em, {\n workflowId,\n version,\n tenantId,\n organizationId,\n })\n\n if (!definition) {\n throw new WorkflowExecutionError(\n `Workflow definition not found: ${workflowId}${version ? ` v${version}` : ''}`,\n 'DEFINITION_NOT_FOUND',\n { workflowId, version }\n )\n }\n\n if (!definition.enabled) {\n throw new WorkflowExecutionError(\n `Workflow definition is disabled: ${workflowId}`,\n 'DEFINITION_DISABLED',\n { workflowId, version: definition.version }\n )\n }\n\n // Validate definition has required steps\n const { steps, transitions } = definition.definition\n if (!steps || steps.length < 2) {\n throw new WorkflowExecutionError(\n 'Workflow definition must have at least START and END steps',\n 'INVALID_DEFINITION',\n { workflowId, stepsCount: steps?.length || 0 }\n )\n }\n\n if (!transitions || transitions.length < 1) {\n throw new WorkflowExecutionError(\n 'Workflow definition must have at least one transition',\n 'INVALID_DEFINITION',\n { workflowId, transitionsCount: transitions?.length || 0 }\n )\n }\n\n // Find START step\n const startStep = steps.find((s: any) => s.stepType === 'START')\n if (!startStep) {\n throw new WorkflowExecutionError(\n 'Workflow definition must have a START step',\n 'INVALID_DEFINITION',\n { workflowId }\n )\n }\n\n // Validate START step pre-conditions if defined\n if (startStep.preConditions && startStep.preConditions.length > 0) {\n const { validateWorkflowStart } = await import('./start-validator')\n\n const validationResult = await validateWorkflowStart(em, {\n workflowId,\n version: definition.version,\n context: initialContext,\n tenantId,\n organizationId,\n })\n\n if (!validationResult.canStart) {\n throw new WorkflowExecutionError(\n `Workflow start pre-conditions failed: ${validationResult.errors.map(e => e.message).join('; ')}`,\n 'START_PRE_CONDITIONS_FAILED',\n {\n workflowId,\n errors: validationResult.errors,\n validatedRules: validationResult.validatedRules,\n }\n )\n }\n }\n\n // Create workflow instance\n const now = new Date()\n const instance = em.create(WorkflowInstance, {\n definitionId: definition.id,\n workflowId: definition.workflowId,\n version: definition.version,\n status: 'RUNNING',\n currentStepId: startStep.stepId,\n context: initialContext,\n correlationKey,\n metadata,\n startedAt: now,\n retryCount: 0,\n tenantId,\n organizationId,\n createdAt: now,\n updatedAt: now,\n })\n\n await em.persist(instance).flush()\n\n // Log WORKFLOW_STARTED event\n await logWorkflowEvent(em, {\n workflowInstanceId: instance.id,\n eventType: 'WORKFLOW_STARTED',\n eventData: {\n workflowId: instance.workflowId,\n version: instance.version,\n startStepId: startStep.stepId,\n initialContext,\n metadata,\n },\n userId: metadata?.initiatedBy,\n tenantId,\n organizationId,\n })\n\n return instance\n}\n\n/**\n * Execute a workflow instance\n *\n * Main execution loop that processes steps and transitions until:\n * - Workflow completes (reaches END step)\n * - Workflow waits (USER_TASK, SIGNAL, TIMER)\n * - Workflow fails (error occurs)\n * - Timeout is reached\n *\n * @param em - Entity manager\n * @param container - DI container (for activity execution and other services)\n * @param instanceId - Workflow instance ID\n * @param context - Execution context (userId, dryRun, timeout)\n * @returns Execution result with status and events\n */\nexport async function executeWorkflow(\n em: EntityManager,\n container: AwilixContainer,\n instanceId: string,\n context?: ExecutionContext\n): Promise<ExecutionResult> {\n const startTime = Date.now()\n const transactionalEm = em as EntityManager & {\n transactional?: <TResult>(\n callback: (trx: EntityManager) => Promise<TResult>,\n ) => Promise<TResult>\n }\n\n const runExecution = async (trx: EntityManager): Promise<ExecutionResult> => {\n const events: WorkflowEventSummary[] = []\n const errors: string[] = []\n\n try {\n const instance = await getWorkflowInstanceForExecution(trx, instanceId)\n if (!instance) {\n throw new WorkflowExecutionError(\n `Workflow instance not found: ${instanceId}`,\n 'INSTANCE_NOT_FOUND',\n { instanceId }\n )\n }\n\n if (instance.status === 'COMPLETED') {\n return {\n status: 'COMPLETED',\n currentStep: instance.currentStepId,\n context: instance.context,\n events: [],\n executionTime: 0,\n }\n }\n\n if (instance.status === 'CANCELLED') {\n throw new WorkflowExecutionError(\n 'Cannot execute cancelled workflow',\n 'WORKFLOW_CANCELLED',\n { instanceId, status: instance.status }\n )\n }\n\n const definition = await trx.findOne(WorkflowDefinition, {\n id: instance.definitionId,\n })\n\n if (!definition) {\n throw new WorkflowExecutionError(\n `Workflow definition not found: ${instance.definitionId}`,\n 'DEFINITION_NOT_FOUND',\n { definitionId: instance.definitionId }\n )\n }\n\n const maxIterations = 100\n let iterations = 0\n\n while (iterations < maxIterations) {\n iterations++\n\n const currentInstance = await getWorkflowInstanceForExecution(trx, instanceId, { refresh: iterations > 1 })\n if (!currentInstance) {\n throw new WorkflowExecutionError(\n 'Instance not found during execution',\n 'INSTANCE_NOT_FOUND',\n { instanceId }\n )\n }\n\n const currentStep = definition.definition.steps.find(\n (s: any) => s.stepId === currentInstance.currentStepId\n )\n\n if (currentStep?.stepType === 'END') {\n await completeWorkflow(trx, container, instanceId, 'COMPLETED')\n events.push({\n eventType: 'WORKFLOW_COMPLETED',\n occurredAt: new Date(),\n })\n\n return {\n status: 'COMPLETED',\n currentStep: currentInstance.currentStepId,\n context: currentInstance.context,\n events,\n executionTime: Date.now() - startTime,\n }\n }\n\n if (\n currentStep?.stepType === 'USER_TASK' ||\n currentStep?.stepType === 'WAIT_FOR_SIGNAL' ||\n currentStep?.stepType === 'TIMER'\n ) {\n return {\n status: 'RUNNING',\n currentStep: currentInstance.currentStepId,\n context: currentInstance.context,\n events,\n executionTime: Date.now() - startTime,\n }\n }\n\n const transitions = definition.definition.transitions.filter(\n (t: any) =>\n t.fromStepId === currentInstance.currentStepId &&\n t.trigger === 'auto'\n )\n\n if (transitions.length === 0) {\n return {\n status: 'RUNNING',\n currentStep: currentInstance.currentStepId,\n context: currentInstance.context,\n events,\n executionTime: Date.now() - startTime,\n }\n }\n\n const transitionHandler = await import('./transition-handler')\n const evalContext: any = {\n workflowContext: currentInstance.context,\n userId: context?.userId,\n }\n\n const validTransitions = await transitionHandler.findValidTransitions(\n trx,\n currentInstance,\n currentInstance.currentStepId!,\n evalContext\n )\n\n const validAutoTransitions = validTransitions.filter(\n (vt) => vt.isValid && vt.transition?.trigger === 'auto'\n )\n\n if (validAutoTransitions.length === 0) {\n return {\n status: 'RUNNING',\n currentStep: currentInstance.currentStepId,\n context: currentInstance.context,\n events,\n executionTime: Date.now() - startTime,\n }\n }\n\n const selectedTransition = validAutoTransitions[0].transition\n\n try {\n const transitionResult = await transitionHandler.executeTransition(\n trx,\n container,\n currentInstance,\n selectedTransition.fromStepId,\n selectedTransition.toStepId,\n evalContext\n )\n\n if (!transitionResult.success) {\n const rejectionMessage = transitionResult.error || 'Transition failed'\n console.error(`[WORKFLOW] Transition rejected (instance: ${currentInstance.id}, workflow: ${currentInstance.workflowId}, step: ${currentInstance.currentStepId} \u2192 ${selectedTransition.toStepId}): ${rejectionMessage}`)\n errors.push(rejectionMessage)\n\n return {\n status: 'FAILED',\n currentStep: currentInstance.currentStepId,\n context: currentInstance.context,\n events,\n errors,\n executionTime: Date.now() - startTime,\n }\n }\n\n events.push({\n eventType: 'TRANSITION_EXECUTED',\n occurredAt: new Date(),\n data: {\n fromStepId: selectedTransition.fromStepId,\n toStepId: selectedTransition.toStepId,\n transitionId: selectedTransition.transitionId,\n },\n })\n\n if (transitionResult.pausedForActivities) {\n await logWorkflowEvent(trx, {\n workflowInstanceId: currentInstance.id,\n eventType: 'WORKFLOW_WAITING_FOR_ACTIVITIES',\n eventData: {\n pendingActivities: transitionResult.activitiesExecuted?.filter(a => a.async),\n pausedAtTransition: {\n fromStepId: selectedTransition.fromStepId,\n toStepId: selectedTransition.toStepId,\n },\n },\n tenantId: currentInstance.tenantId,\n organizationId: currentInstance.organizationId,\n })\n\n events.push({\n eventType: 'WORKFLOW_WAITING_FOR_ACTIVITIES',\n occurredAt: new Date(),\n data: {\n pendingActivities: transitionResult.activitiesExecuted?.filter(a => a.async),\n },\n })\n\n return {\n status: 'WAITING_FOR_ACTIVITIES',\n currentStep: currentInstance.currentStepId,\n context: currentInstance.context,\n events,\n executionTime: Date.now() - startTime,\n }\n }\n\n await trx.flush()\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n console.error(`[WORKFLOW] Transition execution failed (instance: ${currentInstance.id}, workflow: ${currentInstance.workflowId}, step: ${currentInstance.currentStepId} \u2192 ${selectedTransition.toStepId}):`, error)\n console.error('[WORKFLOW] Error stack:', error instanceof Error ? error.stack : 'No stack trace')\n errors.push(errorMessage)\n\n events.push({\n eventType: 'TRANSITION_FAILED',\n occurredAt: new Date(),\n data: {\n transitionId: selectedTransition.transitionId,\n error: errorMessage,\n },\n })\n\n return {\n status: 'FAILED',\n currentStep: currentInstance.currentStepId,\n context: currentInstance.context,\n events,\n errors,\n executionTime: Date.now() - startTime,\n }\n }\n }\n\n errors.push('Maximum execution iterations reached - possible infinite loop')\n return {\n status: 'RUNNING',\n currentStep: instance.currentStepId,\n context: instance.context,\n events,\n errors,\n executionTime: Date.now() - startTime,\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n console.error(`[WORKFLOW] Execution failed (instance: ${instanceId}):`, error)\n if (error instanceof Error && error.stack) {\n console.error('[WORKFLOW] Error stack:', error.stack)\n }\n errors.push(errorMessage)\n\n try {\n const instance = await getWorkflowInstanceForExecution(trx, instanceId, { refresh: true })\n if (instance && instance.status === 'RUNNING') {\n instance.status = 'FAILED'\n instance.errorMessage = errorMessage\n instance.errorDetails = error instanceof WorkflowExecutionError ? error.details : undefined\n instance.updatedAt = new Date()\n await trx.flush()\n\n await logWorkflowEvent(trx, {\n workflowInstanceId: instanceId,\n eventType: 'WORKFLOW_FAILED',\n eventData: { error: errorMessage },\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n }\n } catch (updateError) {\n console.error(`[WORKFLOW] Failed to update instance ${instanceId} with error state:`, updateError)\n }\n\n throw error\n }\n }\n\n return typeof transactionalEm.transactional === 'function'\n ? transactionalEm.transactional((trx) => runExecution(trx))\n : runExecution(em)\n}\n\n/**\n * Complete a workflow instance with final status\n *\n * @param em - Entity manager\n * @param container\n * @param instanceId - Workflow instance ID\n * @param status - Final status (COMPLETED, FAILED, CANCELLED)\n * @param result - Optional result data\n */\nexport async function completeWorkflow(\n em: EntityManager,\n container: AwilixContainer,\n instanceId: string,\n status: 'COMPLETED' | 'FAILED' | 'CANCELLED',\n result?: any\n): Promise<void> {\n const instance = await getWorkflowInstance(em, instanceId)\n if (!instance) {\n throw new WorkflowExecutionError(\n `Workflow instance not found: ${instanceId}`,\n 'INSTANCE_NOT_FOUND',\n { instanceId }\n )\n }\n\n // Trigger compensation if workflow failed and has compensatable activities (Phase 8.2)\n if (status === 'FAILED') {\n const definition = await em.findOne(WorkflowDefinition, { id: instance.definitionId })\n\n if (definition && checkIfCompensationNeeded(definition)) {\n try {\n\n // Set error message before compensation\n if (result?.error) {\n instance.errorMessage = result.error\n instance.errorDetails = result.details\n await em.flush()\n }\n\n const compensationResult = await compensateWorkflow(\n em,\n container,\n instance,\n definition,\n {\n continueOnError: true // Best-effort compensation\n }\n )\n\n console.log(\n `[Workflow] Compensation ${compensationResult.status}: ${compensationResult.compensatedActivities}/${compensationResult.totalActivities} activities`\n )\n\n // Note: instance status already updated by compensateWorkflow\n // It will be COMPENSATED or remain FAILED\n return\n } catch (error: any) {\n console.error(`[Workflow] Compensation failed with exception:`, error)\n // Continue to mark workflow as failed\n }\n }\n }\n\n // Original completion logic (no compensation needed or status is COMPLETED/CANCELLED)\n const now = new Date()\n instance.status = status\n instance.updatedAt = now\n\n switch (status) {\n case 'COMPLETED':\n instance.completedAt = now\n if (result) {\n instance.context = { ...instance.context, __result: result }\n }\n break\n\n case 'FAILED':\n instance.completedAt = now\n if (result?.error) {\n instance.errorMessage = result.error\n instance.errorDetails = result.details\n }\n break\n\n case 'CANCELLED':\n instance.cancelledAt = now\n break\n }\n\n await em.flush()\n\n // Log completion event\n const eventType =\n status === 'COMPLETED'\n ? 'WORKFLOW_COMPLETED'\n : status === 'FAILED'\n ? 'WORKFLOW_FAILED'\n : 'WORKFLOW_CANCELLED'\n\n await logWorkflowEvent(em, {\n workflowInstanceId: instanceId,\n eventType,\n eventData: result || {},\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n}\n\n/**\n * Resume workflow after async activities complete\n *\n * Called by the activity worker after all async activities finish execution.\n * Checks if all activities are done, merges outputs into context, and resumes execution.\n *\n * @param em - Entity manager\n * @param container - DI container\n * @param instanceId - Workflow instance ID\n */\nexport async function resumeWorkflowAfterActivities(\n em: EntityManager,\n container: AwilixContainer,\n instanceId: string\n): Promise<void> {\n const transactionalEm = em as EntityManager & {\n transactional?: <TResult>(callback: (trx: EntityManager) => Promise<TResult>) => Promise<TResult>\n }\n\n const runResume = async (trx: EntityManager): Promise<{ continueExecution: boolean }> => {\n const instance = await trx.findOne(WorkflowInstance, {\n id: instanceId,\n status: 'WAITING_FOR_ACTIVITIES',\n }, { lockMode: LockMode.PESSIMISTIC_WRITE })\n\n if (!instance) {\n throw new Error('Workflow instance not waiting for activities')\n }\n\n const pendingJobIds = (instance.context._pendingAsyncActivities as any[]) || []\n\n const completedActivities = await trx.count(WorkflowEvent, {\n workflowInstanceId: instanceId,\n eventType: 'ACTIVITY_COMPLETED',\n eventData: { async: true },\n })\n\n const failedActivities = await trx.count(WorkflowEvent, {\n workflowInstanceId: instanceId,\n eventType: 'ACTIVITY_FAILED',\n eventData: { async: true },\n })\n\n const totalProcessed = completedActivities + failedActivities\n\n if (totalProcessed < pendingJobIds.length) {\n throw new Error('Activities still pending')\n }\n\n if (failedActivities > 0) {\n const failedEvents = await trx.find(WorkflowEvent, {\n workflowInstanceId: instanceId,\n eventType: 'ACTIVITY_FAILED',\n eventData: { async: true },\n })\n\n instance.status = 'FAILED'\n instance.errorMessage = `${failedActivities} async activities failed`\n instance.errorDetails = {\n failedActivities: failedEvents.map(e => ({\n activityId: e.eventData.activityId,\n error: e.eventData.error,\n jobId: e.eventData.jobId,\n })),\n }\n await trx.flush()\n\n await logWorkflowEvent(trx, {\n workflowInstanceId: instanceId,\n eventType: 'WORKFLOW_FAILED',\n eventData: {\n reason: 'Async activities failed',\n failedActivities: instance.errorDetails.failedActivities,\n },\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n return { continueExecution: false }\n }\n\n const completedEvents = await trx.find(WorkflowEvent, {\n workflowInstanceId: instanceId,\n eventType: 'ACTIVITY_COMPLETED',\n eventData: { async: true },\n })\n\n for (const event of completedEvents) {\n if (event.eventData.output) {\n instance.context = {\n ...instance.context,\n [`${event.eventData.activityId}_result`]: event.eventData.output,\n }\n }\n }\n\n delete instance.context._pendingAsyncActivities\n\n const pendingTransition = instance.pendingTransition\n\n if (!pendingTransition) {\n console.warn('[WORKFLOW] No pending transition found during resume')\n instance.status = 'RUNNING'\n await trx.flush()\n\n await logWorkflowEvent(trx, {\n workflowInstanceId: instanceId,\n eventType: 'WORKFLOW_RESUMED',\n eventData: {\n reason: 'All async activities completed',\n completedActivities: completedActivities,\n },\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n return { continueExecution: true }\n }\n\n console.log('[WORKFLOW] Completing pending transition:', {\n toStepId: pendingTransition.toStepId,\n from: instance.currentStepId,\n })\n\n const definition = await trx.findOneOrFail(WorkflowDefinition, {\n id: instance.definitionId,\n })\n\n const step = definition.definition.steps.find(s => s.stepId === pendingTransition.toStepId)\n\n instance.currentStepId = pendingTransition.toStepId\n instance.status = 'RUNNING'\n instance.pendingTransition = null\n instance.updatedAt = new Date()\n await trx.flush()\n\n await logWorkflowEvent(trx, {\n workflowInstanceId: instance.id,\n eventType: 'STEP_ENTERED',\n eventData: {\n stepId: pendingTransition.toStepId,\n stepName: step?.stepName,\n stepType: step?.stepType,\n },\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n await logWorkflowEvent(trx, {\n workflowInstanceId: instanceId,\n eventType: 'WORKFLOW_RESUMED',\n eventData: {\n reason: 'Async activities completed, resuming pending transition',\n completedActivities: completedActivities,\n completedTransitionTo: pendingTransition.toStepId,\n },\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n const { executeStep } = await import('./step-handler')\n await executeStep(\n trx,\n instance,\n pendingTransition.toStepId,\n {\n workflowContext: instance.context || {},\n userId: undefined,\n },\n container\n )\n\n return { continueExecution: true }\n }\n\n const resumeResult = typeof transactionalEm.transactional === 'function'\n ? await transactionalEm.transactional((trx) => runResume(trx))\n : await runResume(em)\n\n if (resumeResult.continueExecution) {\n await executeWorkflow(em, container, instanceId)\n }\n}\n\n/**\n * Check if workflow definition has any compensatable activities\n */\nfunction checkIfCompensationNeeded(definition: WorkflowDefinition): boolean {\n // Check if any activities have compensation defined\n for (const transition of definition.definition.transitions) {\n if (transition.activities) {\n for (const activity of transition.activities) {\n if (activity.compensation?.activityId) {\n return true\n }\n }\n }\n }\n\n // Check root-level activities (legacy)\n if (definition.definition.activities) {\n for (const activity of definition.definition.activities) {\n if (activity.compensation?.activityId) {\n return true\n }\n }\n }\n\n return false\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Get workflow instance by ID\n *\n * @param em - Entity manager\n * @param instanceId - Workflow instance ID\n * @returns Workflow instance or null if not found\n */\nexport async function getWorkflowInstance(\n em: EntityManager,\n instanceId: string\n): Promise<WorkflowInstance | null> {\n return em.findOne(WorkflowInstance, { id: instanceId })\n}\n\nasync function getWorkflowInstanceForExecution(\n em: EntityManager,\n instanceId: string,\n options?: { refresh?: boolean }\n): Promise<WorkflowInstance | null> {\n return em.findOne(\n WorkflowInstance,\n { id: instanceId },\n {\n lockMode: LockMode.PESSIMISTIC_WRITE,\n ...(options?.refresh ? { refresh: true } : {}),\n }\n )\n}\n\n/**\n * Update workflow context with new data\n *\n * @param em - Entity manager\n * @param instanceId - Workflow instance ID\n * @param updates - Context updates (merged with existing context)\n */\nexport async function updateWorkflowContext(\n em: EntityManager,\n instanceId: string,\n updates: Record<string, any>\n): Promise<void> {\n const instance = await getWorkflowInstance(em, instanceId)\n if (!instance) {\n throw new WorkflowExecutionError(\n `Workflow instance not found: ${instanceId}`,\n 'INSTANCE_NOT_FOUND',\n { instanceId }\n )\n }\n\n instance.context = {\n ...instance.context,\n ...updates,\n }\n instance.updatedAt = new Date()\n\n await em.flush()\n}\n\n/**\n * Find workflow definition by ID and optional version\n *\n * @param em - Entity manager\n * @param options - Search options\n * @returns Workflow definition or null\n */\nasync function findWorkflowDefinition(\n em: EntityManager,\n options: {\n workflowId: string\n version?: number\n tenantId: string\n organizationId: string\n }\n): Promise<WorkflowDefinition | null> {\n const { workflowId, version, tenantId, organizationId } = options\n\n const where: any = {\n workflowId,\n tenantId,\n organizationId,\n deletedAt: null,\n }\n\n if (version !== undefined) {\n where.version = version\n }\n\n // If no version specified, get latest enabled version\n if (version === undefined) {\n where.enabled = true\n return em.findOne(WorkflowDefinition, where, {\n orderBy: { version: 'DESC' },\n })\n }\n\n return em.findOne(WorkflowDefinition, where)\n}\n\n/**\n * Log workflow event to event sourcing table\n *\n * @param em - Entity manager\n * @param event - Event data\n */\nasync function logWorkflowEvent(\n em: EntityManager,\n event: {\n workflowInstanceId: string\n stepInstanceId?: 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 - Workflow Executor Service\n *\n * Main orchestrator for workflow execution. Handles workflow lifecycle:\n * - Starting workflow instances from definitions\n * - Executing workflow steps and transitions\n * - Completing workflows with final status\n * - Triggering compensation on failure\n *\n * Functional API (no classes) following Open Mercato conventions.\n */\n\nimport { EntityManager, LockMode } from '@mikro-orm/core'\nimport type { AwilixContainer } from 'awilix'\nimport {\n WorkflowDefinition,\n WorkflowInstance,\n WorkflowEvent,\n type WorkflowInstanceStatus,\n} from '../data/entities'\nimport { compensateWorkflow } from './compensation-handler'\nimport { findWorkflowDefinition } from './find-definition'\n\n// ============================================================================\n// Types and Interfaces\n// ============================================================================\n\nexport interface StartWorkflowOptions {\n workflowId: string\n version?: number // Default to latest enabled version\n initialContext?: Record<string, any>\n correlationKey?: string\n metadata?: {\n entityType?: string\n entityId?: string\n initiatedBy?: string\n labels?: Record<string, string>\n }\n tenantId: string\n organizationId: string\n}\n\nexport interface ExecutionContext {\n userId?: string\n dryRun?: boolean\n timeout?: number\n}\n\nexport interface ExecutionResult {\n status: WorkflowInstanceStatus\n currentStep: string\n context: Record<string, any>\n events: WorkflowEventSummary[]\n errors?: string[]\n executionTime: number\n}\n\nexport interface WorkflowEventSummary {\n eventType: string\n occurredAt: Date\n data?: any\n}\n\nexport class WorkflowExecutionError extends Error {\n constructor(\n message: string,\n public code: string,\n public details?: any\n ) {\n super(message)\n this.name = 'WorkflowExecutionError'\n }\n}\n\n// ============================================================================\n// Main Orchestration Functions\n// ============================================================================\n\n/**\n * Start a new workflow instance from a definition\n *\n * @param em - Entity manager for database operations\n * @param options - Workflow start options\n * @returns Created workflow instance\n * @throws WorkflowExecutionError if definition not found or validation fails\n */\nexport async function startWorkflow(\n em: EntityManager,\n options: StartWorkflowOptions\n): Promise<WorkflowInstance> {\n const {\n workflowId,\n version,\n initialContext = {},\n correlationKey,\n metadata,\n tenantId,\n organizationId,\n } = options\n\n // Find workflow definition\n const definition = await findWorkflowDefinition(em, {\n workflowId,\n version,\n tenantId,\n organizationId,\n })\n\n if (!definition) {\n throw new WorkflowExecutionError(\n `Workflow definition not found: ${workflowId}${version ? ` v${version}` : ''}`,\n 'DEFINITION_NOT_FOUND',\n { workflowId, version }\n )\n }\n\n if (!definition.enabled) {\n throw new WorkflowExecutionError(\n `Workflow definition is disabled: ${workflowId}`,\n 'DEFINITION_DISABLED',\n { workflowId, version: definition.version }\n )\n }\n\n // Validate definition has required steps\n const { steps, transitions } = definition.definition\n if (!steps || steps.length < 2) {\n throw new WorkflowExecutionError(\n 'Workflow definition must have at least START and END steps',\n 'INVALID_DEFINITION',\n { workflowId, stepsCount: steps?.length || 0 }\n )\n }\n\n if (!transitions || transitions.length < 1) {\n throw new WorkflowExecutionError(\n 'Workflow definition must have at least one transition',\n 'INVALID_DEFINITION',\n { workflowId, transitionsCount: transitions?.length || 0 }\n )\n }\n\n // Find START step\n const startStep = steps.find((s: any) => s.stepType === 'START')\n if (!startStep) {\n throw new WorkflowExecutionError(\n 'Workflow definition must have a START step',\n 'INVALID_DEFINITION',\n { workflowId }\n )\n }\n\n // Validate START step pre-conditions if defined\n if (startStep.preConditions && startStep.preConditions.length > 0) {\n const { validateWorkflowStart } = await import('./start-validator')\n\n const validationResult = await validateWorkflowStart(em, {\n workflowId,\n version: definition.version,\n context: initialContext,\n tenantId,\n organizationId,\n })\n\n if (!validationResult.canStart) {\n throw new WorkflowExecutionError(\n `Workflow start pre-conditions failed: ${validationResult.errors.map(e => e.message).join('; ')}`,\n 'START_PRE_CONDITIONS_FAILED',\n {\n workflowId,\n errors: validationResult.errors,\n validatedRules: validationResult.validatedRules,\n }\n )\n }\n }\n\n // Create workflow instance\n const now = new Date()\n const instance = em.create(WorkflowInstance, {\n definitionId: definition.id,\n workflowId: definition.workflowId,\n version: definition.version,\n status: 'RUNNING',\n currentStepId: startStep.stepId,\n context: initialContext,\n correlationKey,\n metadata,\n startedAt: now,\n retryCount: 0,\n tenantId,\n organizationId,\n createdAt: now,\n updatedAt: now,\n })\n\n await em.persist(instance).flush()\n\n // Log WORKFLOW_STARTED event\n await logWorkflowEvent(em, {\n workflowInstanceId: instance.id,\n eventType: 'WORKFLOW_STARTED',\n eventData: {\n workflowId: instance.workflowId,\n version: instance.version,\n startStepId: startStep.stepId,\n initialContext,\n metadata,\n },\n userId: metadata?.initiatedBy,\n tenantId,\n organizationId,\n })\n\n return instance\n}\n\n/**\n * Execute a workflow instance\n *\n * Main execution loop that processes steps and transitions until:\n * - Workflow completes (reaches END step)\n * - Workflow waits (USER_TASK, SIGNAL, TIMER)\n * - Workflow fails (error occurs)\n * - Timeout is reached\n *\n * @param em - Entity manager\n * @param container - DI container (for activity execution and other services)\n * @param instanceId - Workflow instance ID\n * @param context - Execution context (userId, dryRun, timeout)\n * @returns Execution result with status and events\n */\nexport async function executeWorkflow(\n em: EntityManager,\n container: AwilixContainer,\n instanceId: string,\n context?: ExecutionContext\n): Promise<ExecutionResult> {\n const startTime = Date.now()\n const transactionalEm = em as EntityManager & {\n transactional?: <TResult>(\n callback: (trx: EntityManager) => Promise<TResult>,\n ) => Promise<TResult>\n }\n\n const runExecution = async (trx: EntityManager): Promise<ExecutionResult> => {\n const events: WorkflowEventSummary[] = []\n const errors: string[] = []\n\n try {\n const instance = await getWorkflowInstanceForExecution(trx, instanceId)\n if (!instance) {\n throw new WorkflowExecutionError(\n `Workflow instance not found: ${instanceId}`,\n 'INSTANCE_NOT_FOUND',\n { instanceId }\n )\n }\n\n if (instance.status === 'COMPLETED') {\n return {\n status: 'COMPLETED',\n currentStep: instance.currentStepId,\n context: instance.context,\n events: [],\n executionTime: 0,\n }\n }\n\n if (instance.status === 'CANCELLED') {\n throw new WorkflowExecutionError(\n 'Cannot execute cancelled workflow',\n 'WORKFLOW_CANCELLED',\n { instanceId, status: instance.status }\n )\n }\n\n const definition = await trx.findOne(WorkflowDefinition, {\n id: instance.definitionId,\n })\n\n if (!definition) {\n throw new WorkflowExecutionError(\n `Workflow definition not found: ${instance.definitionId}`,\n 'DEFINITION_NOT_FOUND',\n { definitionId: instance.definitionId }\n )\n }\n\n const maxIterations = 100\n let iterations = 0\n\n while (iterations < maxIterations) {\n iterations++\n\n const currentInstance = await getWorkflowInstanceForExecution(trx, instanceId, { refresh: iterations > 1 })\n if (!currentInstance) {\n throw new WorkflowExecutionError(\n 'Instance not found during execution',\n 'INSTANCE_NOT_FOUND',\n { instanceId }\n )\n }\n\n const currentStep = definition.definition.steps.find(\n (s: any) => s.stepId === currentInstance.currentStepId\n )\n\n if (currentStep?.stepType === 'END') {\n await completeWorkflow(trx, container, instanceId, 'COMPLETED')\n events.push({\n eventType: 'WORKFLOW_COMPLETED',\n occurredAt: new Date(),\n })\n\n return {\n status: 'COMPLETED',\n currentStep: currentInstance.currentStepId,\n context: currentInstance.context,\n events,\n executionTime: Date.now() - startTime,\n }\n }\n\n if (\n currentStep?.stepType === 'USER_TASK' ||\n currentStep?.stepType === 'WAIT_FOR_SIGNAL' ||\n currentStep?.stepType === 'TIMER'\n ) {\n return {\n status: 'RUNNING',\n currentStep: currentInstance.currentStepId,\n context: currentInstance.context,\n events,\n executionTime: Date.now() - startTime,\n }\n }\n\n const transitions = definition.definition.transitions.filter(\n (t: any) =>\n t.fromStepId === currentInstance.currentStepId &&\n t.trigger === 'auto'\n )\n\n if (transitions.length === 0) {\n return {\n status: 'RUNNING',\n currentStep: currentInstance.currentStepId,\n context: currentInstance.context,\n events,\n executionTime: Date.now() - startTime,\n }\n }\n\n const transitionHandler = await import('./transition-handler')\n const evalContext: any = {\n workflowContext: currentInstance.context,\n userId: context?.userId,\n }\n\n const validTransitions = await transitionHandler.findValidTransitions(\n trx,\n currentInstance,\n currentInstance.currentStepId!,\n evalContext\n )\n\n const validAutoTransitions = validTransitions.filter(\n (vt) => vt.isValid && vt.transition?.trigger === 'auto'\n )\n\n if (validAutoTransitions.length === 0) {\n return {\n status: 'RUNNING',\n currentStep: currentInstance.currentStepId,\n context: currentInstance.context,\n events,\n executionTime: Date.now() - startTime,\n }\n }\n\n const selectedTransition = validAutoTransitions[0].transition\n\n try {\n const transitionResult = await transitionHandler.executeTransition(\n trx,\n container,\n currentInstance,\n selectedTransition.fromStepId,\n selectedTransition.toStepId,\n evalContext\n )\n\n if (!transitionResult.success) {\n const rejectionMessage = transitionResult.error || 'Transition failed'\n console.error(`[WORKFLOW] Transition rejected (instance: ${currentInstance.id}, workflow: ${currentInstance.workflowId}, step: ${currentInstance.currentStepId} \u2192 ${selectedTransition.toStepId}): ${rejectionMessage}`)\n errors.push(rejectionMessage)\n\n return {\n status: 'FAILED',\n currentStep: currentInstance.currentStepId,\n context: currentInstance.context,\n events,\n errors,\n executionTime: Date.now() - startTime,\n }\n }\n\n events.push({\n eventType: 'TRANSITION_EXECUTED',\n occurredAt: new Date(),\n data: {\n fromStepId: selectedTransition.fromStepId,\n toStepId: selectedTransition.toStepId,\n transitionId: selectedTransition.transitionId,\n },\n })\n\n if (transitionResult.pausedForActivities) {\n await logWorkflowEvent(trx, {\n workflowInstanceId: currentInstance.id,\n eventType: 'WORKFLOW_WAITING_FOR_ACTIVITIES',\n eventData: {\n pendingActivities: transitionResult.activitiesExecuted?.filter(a => a.async),\n pausedAtTransition: {\n fromStepId: selectedTransition.fromStepId,\n toStepId: selectedTransition.toStepId,\n },\n },\n tenantId: currentInstance.tenantId,\n organizationId: currentInstance.organizationId,\n })\n\n events.push({\n eventType: 'WORKFLOW_WAITING_FOR_ACTIVITIES',\n occurredAt: new Date(),\n data: {\n pendingActivities: transitionResult.activitiesExecuted?.filter(a => a.async),\n },\n })\n\n return {\n status: 'WAITING_FOR_ACTIVITIES',\n currentStep: currentInstance.currentStepId,\n context: currentInstance.context,\n events,\n executionTime: Date.now() - startTime,\n }\n }\n\n await trx.flush()\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n console.error(`[WORKFLOW] Transition execution failed (instance: ${currentInstance.id}, workflow: ${currentInstance.workflowId}, step: ${currentInstance.currentStepId} \u2192 ${selectedTransition.toStepId}):`, error)\n console.error('[WORKFLOW] Error stack:', error instanceof Error ? error.stack : 'No stack trace')\n errors.push(errorMessage)\n\n events.push({\n eventType: 'TRANSITION_FAILED',\n occurredAt: new Date(),\n data: {\n transitionId: selectedTransition.transitionId,\n error: errorMessage,\n },\n })\n\n return {\n status: 'FAILED',\n currentStep: currentInstance.currentStepId,\n context: currentInstance.context,\n events,\n errors,\n executionTime: Date.now() - startTime,\n }\n }\n }\n\n errors.push('Maximum execution iterations reached - possible infinite loop')\n return {\n status: 'RUNNING',\n currentStep: instance.currentStepId,\n context: instance.context,\n events,\n errors,\n executionTime: Date.now() - startTime,\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n console.error(`[WORKFLOW] Execution failed (instance: ${instanceId}):`, error)\n if (error instanceof Error && error.stack) {\n console.error('[WORKFLOW] Error stack:', error.stack)\n }\n errors.push(errorMessage)\n\n try {\n const instance = await getWorkflowInstanceForExecution(trx, instanceId, { refresh: true })\n if (instance && instance.status === 'RUNNING') {\n instance.status = 'FAILED'\n instance.errorMessage = errorMessage\n instance.errorDetails = error instanceof WorkflowExecutionError ? error.details : undefined\n instance.updatedAt = new Date()\n await trx.flush()\n\n await logWorkflowEvent(trx, {\n workflowInstanceId: instanceId,\n eventType: 'WORKFLOW_FAILED',\n eventData: { error: errorMessage },\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n }\n } catch (updateError) {\n console.error(`[WORKFLOW] Failed to update instance ${instanceId} with error state:`, updateError)\n }\n\n throw error\n }\n }\n\n return typeof transactionalEm.transactional === 'function'\n ? transactionalEm.transactional((trx) => runExecution(trx))\n : runExecution(em)\n}\n\n/**\n * Complete a workflow instance with final status\n *\n * @param em - Entity manager\n * @param container\n * @param instanceId - Workflow instance ID\n * @param status - Final status (COMPLETED, FAILED, CANCELLED)\n * @param result - Optional result data\n */\nexport async function completeWorkflow(\n em: EntityManager,\n container: AwilixContainer,\n instanceId: string,\n status: 'COMPLETED' | 'FAILED' | 'CANCELLED',\n result?: any\n): Promise<void> {\n const instance = await getWorkflowInstance(em, instanceId)\n if (!instance) {\n throw new WorkflowExecutionError(\n `Workflow instance not found: ${instanceId}`,\n 'INSTANCE_NOT_FOUND',\n { instanceId }\n )\n }\n\n // Trigger compensation if workflow failed and has compensatable activities (Phase 8.2)\n if (status === 'FAILED') {\n const definition = await em.findOne(WorkflowDefinition, { id: instance.definitionId })\n\n if (definition && checkIfCompensationNeeded(definition)) {\n try {\n\n // Set error message before compensation\n if (result?.error) {\n instance.errorMessage = result.error\n instance.errorDetails = result.details\n await em.flush()\n }\n\n const compensationResult = await compensateWorkflow(\n em,\n container,\n instance,\n definition,\n {\n continueOnError: true // Best-effort compensation\n }\n )\n\n console.log(\n `[Workflow] Compensation ${compensationResult.status}: ${compensationResult.compensatedActivities}/${compensationResult.totalActivities} activities`\n )\n\n // Note: instance status already updated by compensateWorkflow\n // It will be COMPENSATED or remain FAILED\n return\n } catch (error: any) {\n console.error(`[Workflow] Compensation failed with exception:`, error)\n // Continue to mark workflow as failed\n }\n }\n }\n\n // Original completion logic (no compensation needed or status is COMPLETED/CANCELLED)\n const now = new Date()\n instance.status = status\n instance.updatedAt = now\n\n switch (status) {\n case 'COMPLETED':\n instance.completedAt = now\n if (result) {\n instance.context = { ...instance.context, __result: result }\n }\n break\n\n case 'FAILED':\n instance.completedAt = now\n if (result?.error) {\n instance.errorMessage = result.error\n instance.errorDetails = result.details\n }\n break\n\n case 'CANCELLED':\n instance.cancelledAt = now\n break\n }\n\n await em.flush()\n\n // Log completion event\n const eventType =\n status === 'COMPLETED'\n ? 'WORKFLOW_COMPLETED'\n : status === 'FAILED'\n ? 'WORKFLOW_FAILED'\n : 'WORKFLOW_CANCELLED'\n\n await logWorkflowEvent(em, {\n workflowInstanceId: instanceId,\n eventType,\n eventData: result || {},\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n}\n\n/**\n * Resume workflow after async activities complete\n *\n * Called by the activity worker after all async activities finish execution.\n * Checks if all activities are done, merges outputs into context, and resumes execution.\n *\n * @param em - Entity manager\n * @param container - DI container\n * @param instanceId - Workflow instance ID\n */\nexport async function resumeWorkflowAfterActivities(\n em: EntityManager,\n container: AwilixContainer,\n instanceId: string\n): Promise<void> {\n const transactionalEm = em as EntityManager & {\n transactional?: <TResult>(callback: (trx: EntityManager) => Promise<TResult>) => Promise<TResult>\n }\n\n const runResume = async (trx: EntityManager): Promise<{ continueExecution: boolean }> => {\n const instance = await trx.findOne(WorkflowInstance, {\n id: instanceId,\n status: 'WAITING_FOR_ACTIVITIES',\n }, { lockMode: LockMode.PESSIMISTIC_WRITE })\n\n if (!instance) {\n throw new Error('Workflow instance not waiting for activities')\n }\n\n const pendingJobIds = (instance.context._pendingAsyncActivities as any[]) || []\n\n const completedActivities = await trx.count(WorkflowEvent, {\n workflowInstanceId: instanceId,\n eventType: 'ACTIVITY_COMPLETED',\n eventData: { async: true },\n })\n\n const failedActivities = await trx.count(WorkflowEvent, {\n workflowInstanceId: instanceId,\n eventType: 'ACTIVITY_FAILED',\n eventData: { async: true },\n })\n\n const totalProcessed = completedActivities + failedActivities\n\n if (totalProcessed < pendingJobIds.length) {\n throw new Error('Activities still pending')\n }\n\n if (failedActivities > 0) {\n const failedEvents = await trx.find(WorkflowEvent, {\n workflowInstanceId: instanceId,\n eventType: 'ACTIVITY_FAILED',\n eventData: { async: true },\n })\n\n instance.status = 'FAILED'\n instance.errorMessage = `${failedActivities} async activities failed`\n instance.errorDetails = {\n failedActivities: failedEvents.map(e => ({\n activityId: e.eventData.activityId,\n error: e.eventData.error,\n jobId: e.eventData.jobId,\n })),\n }\n await trx.flush()\n\n await logWorkflowEvent(trx, {\n workflowInstanceId: instanceId,\n eventType: 'WORKFLOW_FAILED',\n eventData: {\n reason: 'Async activities failed',\n failedActivities: instance.errorDetails.failedActivities,\n },\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n return { continueExecution: false }\n }\n\n const completedEvents = await trx.find(WorkflowEvent, {\n workflowInstanceId: instanceId,\n eventType: 'ACTIVITY_COMPLETED',\n eventData: { async: true },\n })\n\n for (const event of completedEvents) {\n if (event.eventData.output) {\n instance.context = {\n ...instance.context,\n [`${event.eventData.activityId}_result`]: event.eventData.output,\n }\n }\n }\n\n delete instance.context._pendingAsyncActivities\n\n const pendingTransition = instance.pendingTransition\n\n if (!pendingTransition) {\n console.warn('[WORKFLOW] No pending transition found during resume')\n instance.status = 'RUNNING'\n await trx.flush()\n\n await logWorkflowEvent(trx, {\n workflowInstanceId: instanceId,\n eventType: 'WORKFLOW_RESUMED',\n eventData: {\n reason: 'All async activities completed',\n completedActivities: completedActivities,\n },\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n return { continueExecution: true }\n }\n\n console.log('[WORKFLOW] Completing pending transition:', {\n toStepId: pendingTransition.toStepId,\n from: instance.currentStepId,\n })\n\n const definition = await trx.findOneOrFail(WorkflowDefinition, {\n id: instance.definitionId,\n })\n\n const step = definition.definition.steps.find(s => s.stepId === pendingTransition.toStepId)\n\n instance.currentStepId = pendingTransition.toStepId\n instance.status = 'RUNNING'\n instance.pendingTransition = null\n instance.updatedAt = new Date()\n await trx.flush()\n\n await logWorkflowEvent(trx, {\n workflowInstanceId: instance.id,\n eventType: 'STEP_ENTERED',\n eventData: {\n stepId: pendingTransition.toStepId,\n stepName: step?.stepName,\n stepType: step?.stepType,\n },\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n await logWorkflowEvent(trx, {\n workflowInstanceId: instanceId,\n eventType: 'WORKFLOW_RESUMED',\n eventData: {\n reason: 'Async activities completed, resuming pending transition',\n completedActivities: completedActivities,\n completedTransitionTo: pendingTransition.toStepId,\n },\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n const { executeStep } = await import('./step-handler')\n await executeStep(\n trx,\n instance,\n pendingTransition.toStepId,\n {\n workflowContext: instance.context || {},\n userId: undefined,\n },\n container\n )\n\n return { continueExecution: true }\n }\n\n const resumeResult = typeof transactionalEm.transactional === 'function'\n ? await transactionalEm.transactional((trx) => runResume(trx))\n : await runResume(em)\n\n if (resumeResult.continueExecution) {\n await executeWorkflow(em, container, instanceId)\n }\n}\n\n/**\n * Check if workflow definition has any compensatable activities\n */\nfunction checkIfCompensationNeeded(definition: WorkflowDefinition): boolean {\n // Check if any activities have compensation defined\n for (const transition of definition.definition.transitions) {\n if (transition.activities) {\n for (const activity of transition.activities) {\n if (activity.compensation?.activityId) {\n return true\n }\n }\n }\n }\n\n // Check root-level activities (legacy)\n if (definition.definition.activities) {\n for (const activity of definition.definition.activities) {\n if (activity.compensation?.activityId) {\n return true\n }\n }\n }\n\n return false\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Get workflow instance by ID\n *\n * @param em - Entity manager\n * @param instanceId - Workflow instance ID\n * @returns Workflow instance or null if not found\n */\nexport async function getWorkflowInstance(\n em: EntityManager,\n instanceId: string\n): Promise<WorkflowInstance | null> {\n return em.findOne(WorkflowInstance, { id: instanceId })\n}\n\nasync function getWorkflowInstanceForExecution(\n em: EntityManager,\n instanceId: string,\n options?: { refresh?: boolean }\n): Promise<WorkflowInstance | null> {\n return em.findOne(\n WorkflowInstance,\n { id: instanceId },\n {\n lockMode: LockMode.PESSIMISTIC_WRITE,\n ...(options?.refresh ? { refresh: true } : {}),\n }\n )\n}\n\n/**\n * Update workflow context with new data\n *\n * @param em - Entity manager\n * @param instanceId - Workflow instance ID\n * @param updates - Context updates (merged with existing context)\n */\nexport async function updateWorkflowContext(\n em: EntityManager,\n instanceId: string,\n updates: Record<string, any>\n): Promise<void> {\n const instance = await getWorkflowInstance(em, instanceId)\n if (!instance) {\n throw new WorkflowExecutionError(\n `Workflow instance not found: ${instanceId}`,\n 'INSTANCE_NOT_FOUND',\n { instanceId }\n )\n }\n\n instance.context = {\n ...instance.context,\n ...updates,\n }\n instance.updatedAt = new Date()\n\n await em.flush()\n}\n\n// findWorkflowDefinition is imported from ./find-definition\n\n/**\n * Log workflow event to event sourcing table\n *\n * @param em - Entity manager\n * @param event - Event data\n */\nasync function logWorkflowEvent(\n em: EntityManager,\n event: {\n workflowInstanceId: string\n stepInstanceId?: 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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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,13 @@
1
+ import { Migration } from "@mikro-orm/migrations";
2
+ class Migration20260414120000 extends Migration {
3
+ async up() {
4
+ this.addSql(`alter table "workflow_definitions" add column if not exists "code_workflow_id" varchar(100) null;`);
5
+ }
6
+ async down() {
7
+ this.addSql(`alter table "workflow_definitions" drop column if exists "code_workflow_id";`);
8
+ }
9
+ }
10
+ export {
11
+ Migration20260414120000
12
+ };
13
+ //# sourceMappingURL=Migration20260414120000.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/workflows/migrations/Migration20260414120000.ts"],
4
+ "sourcesContent": ["import { Migration } from '@mikro-orm/migrations';\n\nexport class Migration20260414120000 extends Migration {\n\n override async up(): Promise<void> {\n this.addSql(`alter table \"workflow_definitions\" add column if not exists \"code_workflow_id\" varchar(100) null;`);\n }\n\n override async down(): Promise<void> {\n this.addSql(`alter table \"workflow_definitions\" drop column if exists \"code_workflow_id\";`);\n }\n\n}\n"],
5
+ "mappings": "AAAA,SAAS,iBAAiB;AAEnB,MAAM,gCAAgC,UAAU;AAAA,EAErD,MAAe,KAAoB;AACjC,SAAK,OAAO,mGAAmG;AAAA,EACjH;AAAA,EAEA,MAAe,OAAsB;AACnC,SAAK,OAAO,8EAA8E;AAAA,EAC5F;AAEF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,32 @@
1
+ import { Migration } from "@mikro-orm/migrations";
2
+ const RENAMES = [
3
+ { from: "checkout_simple_v1", to: "workflows.checkout-demo" },
4
+ { from: "sales_order_approval_v1", to: "sales.order-approval" },
5
+ { from: "simple_approval_v1", to: "workflows.simple-approval" }
6
+ ];
7
+ class Migration20260428102318 extends Migration {
8
+ async up() {
9
+ for (const { from, to } of RENAMES) {
10
+ this.addSql(
11
+ `update "workflow_definitions" set "workflow_id" = '${to}' where "workflow_id" = '${from}' and not exists (select 1 from "workflow_definitions" d2 where d2."workflow_id" = '${to}' and d2."tenant_id" = "workflow_definitions"."tenant_id");`
12
+ );
13
+ this.addSql(
14
+ `update "workflow_instances" set "workflow_id" = '${to}' where "workflow_id" = '${from}' and exists (select 1 from "workflow_definitions" d where d."id" = "workflow_instances"."definition_id" and d."workflow_id" = '${to}');`
15
+ );
16
+ }
17
+ }
18
+ async down() {
19
+ for (const { from, to } of RENAMES) {
20
+ this.addSql(
21
+ `update "workflow_definitions" set "workflow_id" = '${from}' where "workflow_id" = '${to}' and not exists (select 1 from "workflow_definitions" d2 where d2."workflow_id" = '${from}' and d2."tenant_id" = "workflow_definitions"."tenant_id");`
22
+ );
23
+ this.addSql(
24
+ `update "workflow_instances" set "workflow_id" = '${from}' where "workflow_id" = '${to}' and exists (select 1 from "workflow_definitions" d where d."id" = "workflow_instances"."definition_id" and d."workflow_id" = '${from}');`
25
+ );
26
+ }
27
+ }
28
+ }
29
+ export {
30
+ Migration20260428102318
31
+ };
32
+ //# sourceMappingURL=Migration20260428102318.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/workflows/migrations/Migration20260428102318.ts"],
4
+ "sourcesContent": ["import { Migration } from '@mikro-orm/migrations';\n\nconst RENAMES: Array<{ from: string; to: string }> = [\n { from: 'checkout_simple_v1', to: 'workflows.checkout-demo' },\n { from: 'sales_order_approval_v1', to: 'sales.order-approval' },\n { from: 'simple_approval_v1', to: 'workflows.simple-approval' },\n];\n\nexport class Migration20260428102318 extends Migration {\n\n override async up(): Promise<void> {\n for (const { from, to } of RENAMES) {\n this.addSql(\n `update \"workflow_definitions\" ` +\n `set \"workflow_id\" = '${to}' ` +\n `where \"workflow_id\" = '${from}' ` +\n `and not exists (` +\n `select 1 from \"workflow_definitions\" d2 ` +\n `where d2.\"workflow_id\" = '${to}' and d2.\"tenant_id\" = \"workflow_definitions\".\"tenant_id\"` +\n `);`\n );\n this.addSql(\n `update \"workflow_instances\" ` +\n `set \"workflow_id\" = '${to}' ` +\n `where \"workflow_id\" = '${from}' ` +\n `and exists (` +\n `select 1 from \"workflow_definitions\" d ` +\n `where d.\"id\" = \"workflow_instances\".\"definition_id\" and d.\"workflow_id\" = '${to}'` +\n `);`\n );\n }\n }\n\n override async down(): Promise<void> {\n for (const { from, to } of RENAMES) {\n this.addSql(\n `update \"workflow_definitions\" ` +\n `set \"workflow_id\" = '${from}' ` +\n `where \"workflow_id\" = '${to}' ` +\n `and not exists (` +\n `select 1 from \"workflow_definitions\" d2 ` +\n `where d2.\"workflow_id\" = '${from}' and d2.\"tenant_id\" = \"workflow_definitions\".\"tenant_id\"` +\n `);`\n );\n this.addSql(\n `update \"workflow_instances\" ` +\n `set \"workflow_id\" = '${from}' ` +\n `where \"workflow_id\" = '${to}' ` +\n `and exists (` +\n `select 1 from \"workflow_definitions\" d ` +\n `where d.\"id\" = \"workflow_instances\".\"definition_id\" and d.\"workflow_id\" = '${from}'` +\n `);`\n );\n }\n }\n\n}\n"],
5
+ "mappings": "AAAA,SAAS,iBAAiB;AAE1B,MAAM,UAA+C;AAAA,EACnD,EAAE,MAAM,sBAAsB,IAAI,0BAA0B;AAAA,EAC5D,EAAE,MAAM,2BAA2B,IAAI,uBAAuB;AAAA,EAC9D,EAAE,MAAM,sBAAsB,IAAI,4BAA4B;AAChE;AAEO,MAAM,gCAAgC,UAAU;AAAA,EAErD,MAAe,KAAoB;AACjC,eAAW,EAAE,MAAM,GAAG,KAAK,SAAS;AAClC,WAAK;AAAA,QACH,sDACwB,EAAE,4BACA,IAAI,uFAGC,EAAE;AAAA,MAEnC;AACA,WAAK;AAAA,QACH,oDACwB,EAAE,4BACA,IAAI,mIAGkD,EAAE;AAAA,MAEpF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAe,OAAsB;AACnC,eAAW,EAAE,MAAM,GAAG,KAAK,SAAS;AAClC,WAAK;AAAA,QACH,sDACwB,IAAI,4BACF,EAAE,uFAGG,IAAI;AAAA,MAErC;AACA,WAAK;AAAA,QACH,oDACwB,IAAI,4BACF,EAAE,mIAGoD,IAAI;AAAA,MAEtF;AAAA,IACF;AAAA,EACF;AAEF;",
6
+ "names": []
7
+ }