@open-mercato/core 0.6.6-develop.6365.1.641d695f07 → 0.6.6-develop.6366.1.fba69a7362

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,4 @@
1
+ import { parseBooleanWithDefault } from "@open-mercato/shared/lib/boolean";
1
2
  const metadata = {
2
3
  event: "*",
3
4
  // Subscribe to ALL events
@@ -17,12 +18,17 @@ const EXCLUDED_EVENT_PREFIXES = [
17
18
  "queue."
18
19
  // Queue events
19
20
  ];
21
+ const WORKFLOW_TRIGGER_DEBUG_ENV = "OM_WORKFLOW_TRIGGER_DEBUG";
22
+ function isWorkflowTriggerDebugEnabled() {
23
+ return parseBooleanWithDefault(process.env[WORKFLOW_TRIGGER_DEBUG_ENV], false);
24
+ }
20
25
  function isExcludedEvent(eventName) {
21
26
  return EXCLUDED_EVENT_PREFIXES.some((prefix) => eventName.startsWith(prefix));
22
27
  }
23
28
  async function handle(payload, ctx) {
24
29
  const eventName = ctx.eventName;
25
30
  if (!eventName) {
31
+ console.warn("[workflow-trigger] Skipping trigger evaluation because subscriber context is missing eventName");
26
32
  return;
27
33
  }
28
34
  if (isExcludedEvent(eventName)) {
@@ -57,6 +63,12 @@ async function handle(payload, ctx) {
57
63
  tenantId,
58
64
  organizationId
59
65
  });
66
+ if (isWorkflowTriggerDebugEnabled()) {
67
+ const matched = result.triggered + result.skipped + result.errors.length;
68
+ console.log(
69
+ `[workflow-trigger] Evaluated triggers for "${eventName}": tenant=${tenantId} organization=${organizationId} matched=${matched} triggered=${result.triggered} skipped=${result.skipped} errors=${result.errors.length}`
70
+ );
71
+ }
60
72
  if (result.triggered > 0) {
61
73
  console.log(
62
74
  `[workflow-trigger] Triggered ${result.triggered} workflow(s) for "${eventName}"` + (result.skipped > 0 ? ` (${result.skipped} skipped)` : "") + (result.errors.length > 0 ? ` (${result.errors.length} errors)` : "")
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/workflows/subscribers/event-trigger.ts"],
4
- "sourcesContent": ["/**\n * Workflows Module - Event Trigger Subscriber\n *\n * Wildcard subscriber that listens to all events and evaluates\n * workflow event triggers. When a matching trigger is found,\n * the corresponding workflow is started with mapped context.\n */\n\nimport type { EntityManager } from '@mikro-orm/core'\nimport type { AwilixContainer } from 'awilix'\n\nexport const metadata = {\n event: '*', // Subscribe to ALL events\n persistent: true, // Ensure reliability\n id: 'workflows:event-trigger',\n}\n\n// Events that should never trigger workflows (internal/system events)\nconst EXCLUDED_EVENT_PREFIXES = [\n 'query_index.', // Internal indexing events\n 'search.', // Internal search events\n 'workflows.', // Workflow internal events (avoid recursion)\n 'cache.', // Cache events\n 'queue.', // Queue events\n]\n\n/**\n * Check if an event should be excluded from trigger processing.\n */\nfunction isExcludedEvent(eventName: string): boolean {\n return EXCLUDED_EVENT_PREFIXES.some(prefix => eventName.startsWith(prefix))\n}\n\nexport default async function handle(\n payload: unknown,\n ctx: {\n resolve: <T = unknown>(name: string) => T\n eventName?: string\n tenantId?: string | null\n organizationId?: string | null\n }\n): Promise<void> {\n const eventName = ctx.eventName\n if (!eventName) {\n // Skip if no event name (shouldn't happen, but be safe)\n return\n }\n\n // Skip excluded events\n if (isExcludedEvent(eventName)) {\n return\n }\n\n // Ensure payload is an object\n const eventPayload = (payload && typeof payload === 'object' ? payload : {}) as Record<string, unknown>\n\n // Only trust scope attached by the emitter via event bus options.\n const tenantId = typeof ctx.tenantId === 'string' && ctx.tenantId.length > 0 ? ctx.tenantId : undefined\n const organizationId =\n typeof ctx.organizationId === 'string' && ctx.organizationId.length > 0\n ? ctx.organizationId\n : undefined\n\n // Skip events without trusted tenant context\n if (!tenantId || !organizationId) {\n return\n }\n\n // Get dependencies from container\n let em: EntityManager\n let container: AwilixContainer\n\n try {\n em = ctx.resolve<EntityManager>('em')\n // Create a minimal container wrapper using the resolve function\n // This avoids the need to register 'container' as a self-reference in DI\n container = {\n resolve: ctx.resolve,\n // Provide minimal AwilixContainer interface for type compatibility\n cradle: new Proxy({}, {\n get: (_target, prop: string) => ctx.resolve(prop),\n }),\n } as unknown as AwilixContainer\n } catch (error) {\n // DI not available - skip\n console.warn(`[workflow-trigger] Cannot resolve dependencies for event \"${eventName}\":`, error)\n return\n }\n\n // Import service dynamically to avoid circular dependencies\n const { processEventTriggers } = await import('../lib/event-trigger-service')\n\n try {\n const result = await processEventTriggers(em, container, {\n eventName,\n payload: eventPayload,\n tenantId,\n organizationId,\n })\n\n if (result.triggered > 0) {\n console.log(\n `[workflow-trigger] Triggered ${result.triggered} workflow(s) for \"${eventName}\"` +\n (result.skipped > 0 ? ` (${result.skipped} skipped)` : '') +\n (result.errors.length > 0 ? ` (${result.errors.length} errors)` : '')\n )\n }\n\n if (result.errors.length > 0) {\n for (const err of result.errors) {\n console.error(`[workflow-trigger] Trigger ${err.triggerId} failed:`, err.error)\n }\n }\n } catch (error) {\n console.error(`[workflow-trigger] Error processing triggers for \"${eventName}\":`, error)\n }\n}\n"],
5
- "mappings": "AAWO,MAAM,WAAW;AAAA,EACtB,OAAO;AAAA;AAAA,EACP,YAAY;AAAA;AAAA,EACZ,IAAI;AACN;AAGA,MAAM,0BAA0B;AAAA,EAC9B;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AACF;AAKA,SAAS,gBAAgB,WAA4B;AACnD,SAAO,wBAAwB,KAAK,YAAU,UAAU,WAAW,MAAM,CAAC;AAC5E;AAEA,eAAO,OACL,SACA,KAMe;AACf,QAAM,YAAY,IAAI;AACtB,MAAI,CAAC,WAAW;AAEd;AAAA,EACF;AAGA,MAAI,gBAAgB,SAAS,GAAG;AAC9B;AAAA,EACF;AAGA,QAAM,eAAgB,WAAW,OAAO,YAAY,WAAW,UAAU,CAAC;AAG1E,QAAM,WAAW,OAAO,IAAI,aAAa,YAAY,IAAI,SAAS,SAAS,IAAI,IAAI,WAAW;AAC9F,QAAM,iBACJ,OAAO,IAAI,mBAAmB,YAAY,IAAI,eAAe,SAAS,IAClE,IAAI,iBACJ;AAGN,MAAI,CAAC,YAAY,CAAC,gBAAgB;AAChC;AAAA,EACF;AAGA,MAAI;AACJ,MAAI;AAEJ,MAAI;AACF,SAAK,IAAI,QAAuB,IAAI;AAGpC,gBAAY;AAAA,MACV,SAAS,IAAI;AAAA;AAAA,MAEb,QAAQ,IAAI,MAAM,CAAC,GAAG;AAAA,QACpB,KAAK,CAAC,SAAS,SAAiB,IAAI,QAAQ,IAAI;AAAA,MAClD,CAAC;AAAA,IACH;AAAA,EACF,SAAS,OAAO;AAEd,YAAQ,KAAK,6DAA6D,SAAS,MAAM,KAAK;AAC9F;AAAA,EACF;AAGA,QAAM,EAAE,qBAAqB,IAAI,MAAM,OAAO,8BAA8B;AAE5E,MAAI;AACF,UAAM,SAAS,MAAM,qBAAqB,IAAI,WAAW;AAAA,MACvD;AAAA,MACA,SAAS;AAAA,MACT;AAAA,MACA;AAAA,IACF,CAAC;AAED,QAAI,OAAO,YAAY,GAAG;AACxB,cAAQ;AAAA,QACN,gCAAgC,OAAO,SAAS,qBAAqB,SAAS,OAC7E,OAAO,UAAU,IAAI,KAAK,OAAO,OAAO,cAAc,OACtD,OAAO,OAAO,SAAS,IAAI,KAAK,OAAO,OAAO,MAAM,aAAa;AAAA,MACpE;AAAA,IACF;AAEA,QAAI,OAAO,OAAO,SAAS,GAAG;AAC5B,iBAAW,OAAO,OAAO,QAAQ;AAC/B,gBAAQ,MAAM,8BAA8B,IAAI,SAAS,YAAY,IAAI,KAAK;AAAA,MAChF;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,qDAAqD,SAAS,MAAM,KAAK;AAAA,EACzF;AACF;",
4
+ "sourcesContent": ["/**\n * Workflows Module - Event Trigger Subscriber\n *\n * Wildcard subscriber that listens to all events and evaluates\n * workflow event triggers. When a matching trigger is found,\n * the corresponding workflow is started with mapped context.\n */\n\nimport type { EntityManager } from '@mikro-orm/core'\nimport type { AwilixContainer } from 'awilix'\nimport { parseBooleanWithDefault } from '@open-mercato/shared/lib/boolean'\n\nexport const metadata = {\n event: '*', // Subscribe to ALL events\n persistent: true, // Ensure reliability\n id: 'workflows:event-trigger',\n}\n\n// Events that should never trigger workflows (internal/system events)\nconst EXCLUDED_EVENT_PREFIXES = [\n 'query_index.', // Internal indexing events\n 'search.', // Internal search events\n 'workflows.', // Workflow internal events (avoid recursion)\n 'cache.', // Cache events\n 'queue.', // Queue events\n]\n\nconst WORKFLOW_TRIGGER_DEBUG_ENV = 'OM_WORKFLOW_TRIGGER_DEBUG'\n\nfunction isWorkflowTriggerDebugEnabled(): boolean {\n return parseBooleanWithDefault(process.env[WORKFLOW_TRIGGER_DEBUG_ENV], false)\n}\n\n/**\n * Check if an event should be excluded from trigger processing.\n */\nfunction isExcludedEvent(eventName: string): boolean {\n return EXCLUDED_EVENT_PREFIXES.some(prefix => eventName.startsWith(prefix))\n}\n\nexport default async function handle(\n payload: unknown,\n ctx: {\n resolve: <T = unknown>(name: string) => T\n eventName?: string\n tenantId?: string | null\n organizationId?: string | null\n }\n): Promise<void> {\n const eventName = ctx.eventName\n if (!eventName) {\n console.warn('[workflow-trigger] Skipping trigger evaluation because subscriber context is missing eventName')\n return\n }\n\n // Skip excluded events\n if (isExcludedEvent(eventName)) {\n return\n }\n\n // Ensure payload is an object\n const eventPayload = (payload && typeof payload === 'object' ? payload : {}) as Record<string, unknown>\n\n // Only trust scope attached by the emitter via event bus options.\n const tenantId = typeof ctx.tenantId === 'string' && ctx.tenantId.length > 0 ? ctx.tenantId : undefined\n const organizationId =\n typeof ctx.organizationId === 'string' && ctx.organizationId.length > 0\n ? ctx.organizationId\n : undefined\n\n // Skip events without trusted tenant context\n if (!tenantId || !organizationId) {\n return\n }\n\n // Get dependencies from container\n let em: EntityManager\n let container: AwilixContainer\n\n try {\n em = ctx.resolve<EntityManager>('em')\n // Create a minimal container wrapper using the resolve function\n // This avoids the need to register 'container' as a self-reference in DI\n container = {\n resolve: ctx.resolve,\n // Provide minimal AwilixContainer interface for type compatibility\n cradle: new Proxy({}, {\n get: (_target, prop: string) => ctx.resolve(prop),\n }),\n } as unknown as AwilixContainer\n } catch (error) {\n // DI not available - skip\n console.warn(`[workflow-trigger] Cannot resolve dependencies for event \"${eventName}\":`, error)\n return\n }\n\n // Import service dynamically to avoid circular dependencies\n const { processEventTriggers } = await import('../lib/event-trigger-service')\n\n try {\n const result = await processEventTriggers(em, container, {\n eventName,\n payload: eventPayload,\n tenantId,\n organizationId,\n })\n\n if (isWorkflowTriggerDebugEnabled()) {\n const matched = result.triggered + result.skipped + result.errors.length\n console.log(\n `[workflow-trigger] Evaluated triggers for \"${eventName}\": ` +\n `tenant=${tenantId} organization=${organizationId} matched=${matched} ` +\n `triggered=${result.triggered} skipped=${result.skipped} errors=${result.errors.length}`\n )\n }\n\n if (result.triggered > 0) {\n console.log(\n `[workflow-trigger] Triggered ${result.triggered} workflow(s) for \"${eventName}\"` +\n (result.skipped > 0 ? ` (${result.skipped} skipped)` : '') +\n (result.errors.length > 0 ? ` (${result.errors.length} errors)` : '')\n )\n }\n\n if (result.errors.length > 0) {\n for (const err of result.errors) {\n console.error(`[workflow-trigger] Trigger ${err.triggerId} failed:`, err.error)\n }\n }\n } catch (error) {\n console.error(`[workflow-trigger] Error processing triggers for \"${eventName}\":`, error)\n }\n}\n"],
5
+ "mappings": "AAUA,SAAS,+BAA+B;AAEjC,MAAM,WAAW;AAAA,EACtB,OAAO;AAAA;AAAA,EACP,YAAY;AAAA;AAAA,EACZ,IAAI;AACN;AAGA,MAAM,0BAA0B;AAAA,EAC9B;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AACF;AAEA,MAAM,6BAA6B;AAEnC,SAAS,gCAAyC;AAChD,SAAO,wBAAwB,QAAQ,IAAI,0BAA0B,GAAG,KAAK;AAC/E;AAKA,SAAS,gBAAgB,WAA4B;AACnD,SAAO,wBAAwB,KAAK,YAAU,UAAU,WAAW,MAAM,CAAC;AAC5E;AAEA,eAAO,OACL,SACA,KAMe;AACf,QAAM,YAAY,IAAI;AACtB,MAAI,CAAC,WAAW;AACd,YAAQ,KAAK,gGAAgG;AAC7G;AAAA,EACF;AAGA,MAAI,gBAAgB,SAAS,GAAG;AAC9B;AAAA,EACF;AAGA,QAAM,eAAgB,WAAW,OAAO,YAAY,WAAW,UAAU,CAAC;AAG1E,QAAM,WAAW,OAAO,IAAI,aAAa,YAAY,IAAI,SAAS,SAAS,IAAI,IAAI,WAAW;AAC9F,QAAM,iBACJ,OAAO,IAAI,mBAAmB,YAAY,IAAI,eAAe,SAAS,IAClE,IAAI,iBACJ;AAGN,MAAI,CAAC,YAAY,CAAC,gBAAgB;AAChC;AAAA,EACF;AAGA,MAAI;AACJ,MAAI;AAEJ,MAAI;AACF,SAAK,IAAI,QAAuB,IAAI;AAGpC,gBAAY;AAAA,MACV,SAAS,IAAI;AAAA;AAAA,MAEb,QAAQ,IAAI,MAAM,CAAC,GAAG;AAAA,QACpB,KAAK,CAAC,SAAS,SAAiB,IAAI,QAAQ,IAAI;AAAA,MAClD,CAAC;AAAA,IACH;AAAA,EACF,SAAS,OAAO;AAEd,YAAQ,KAAK,6DAA6D,SAAS,MAAM,KAAK;AAC9F;AAAA,EACF;AAGA,QAAM,EAAE,qBAAqB,IAAI,MAAM,OAAO,8BAA8B;AAE5E,MAAI;AACF,UAAM,SAAS,MAAM,qBAAqB,IAAI,WAAW;AAAA,MACvD;AAAA,MACA,SAAS;AAAA,MACT;AAAA,MACA;AAAA,IACF,CAAC;AAED,QAAI,8BAA8B,GAAG;AACnC,YAAM,UAAU,OAAO,YAAY,OAAO,UAAU,OAAO,OAAO;AAClE,cAAQ;AAAA,QACN,8CAA8C,SAAS,aAC7C,QAAQ,iBAAiB,cAAc,YAAY,OAAO,cACvD,OAAO,SAAS,YAAY,OAAO,OAAO,WAAW,OAAO,OAAO,MAAM;AAAA,MACxF;AAAA,IACF;AAEA,QAAI,OAAO,YAAY,GAAG;AACxB,cAAQ;AAAA,QACN,gCAAgC,OAAO,SAAS,qBAAqB,SAAS,OAC7E,OAAO,UAAU,IAAI,KAAK,OAAO,OAAO,cAAc,OACtD,OAAO,OAAO,SAAS,IAAI,KAAK,OAAO,OAAO,MAAM,aAAa;AAAA,MACpE;AAAA,IACF;AAEA,QAAI,OAAO,OAAO,SAAS,GAAG;AAC5B,iBAAW,OAAO,OAAO,QAAQ;AAC/B,gBAAQ,MAAM,8BAA8B,IAAI,SAAS,YAAY,IAAI,KAAK;AAAA,MAChF;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,qDAAqD,SAAS,MAAM,KAAK;AAAA,EACzF;AACF;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/core",
3
- "version": "0.6.6-develop.6365.1.641d695f07",
3
+ "version": "0.6.6-develop.6366.1.fba69a7362",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -246,16 +246,16 @@
246
246
  "zod": "^4.4.3"
247
247
  },
248
248
  "peerDependencies": {
249
- "@open-mercato/ai-assistant": "0.6.6-develop.6365.1.641d695f07",
250
- "@open-mercato/shared": "0.6.6-develop.6365.1.641d695f07",
251
- "@open-mercato/ui": "0.6.6-develop.6365.1.641d695f07",
249
+ "@open-mercato/ai-assistant": "0.6.6-develop.6366.1.fba69a7362",
250
+ "@open-mercato/shared": "0.6.6-develop.6366.1.fba69a7362",
251
+ "@open-mercato/ui": "0.6.6-develop.6366.1.fba69a7362",
252
252
  "react": "^19.0.0",
253
253
  "react-dom": "^19.0.0"
254
254
  },
255
255
  "devDependencies": {
256
- "@open-mercato/ai-assistant": "0.6.6-develop.6365.1.641d695f07",
257
- "@open-mercato/shared": "0.6.6-develop.6365.1.641d695f07",
258
- "@open-mercato/ui": "0.6.6-develop.6365.1.641d695f07",
256
+ "@open-mercato/ai-assistant": "0.6.6-develop.6366.1.fba69a7362",
257
+ "@open-mercato/shared": "0.6.6-develop.6366.1.fba69a7362",
258
+ "@open-mercato/ui": "0.6.6-develop.6366.1.fba69a7362",
259
259
  "@testing-library/dom": "^10.4.1",
260
260
  "@testing-library/jest-dom": "^6.9.1",
261
261
  "@testing-library/react": "^16.3.1",
@@ -8,6 +8,7 @@
8
8
 
9
9
  import type { EntityManager } from '@mikro-orm/core'
10
10
  import type { AwilixContainer } from 'awilix'
11
+ import { parseBooleanWithDefault } from '@open-mercato/shared/lib/boolean'
11
12
 
12
13
  export const metadata = {
13
14
  event: '*', // Subscribe to ALL events
@@ -24,6 +25,12 @@ const EXCLUDED_EVENT_PREFIXES = [
24
25
  'queue.', // Queue events
25
26
  ]
26
27
 
28
+ const WORKFLOW_TRIGGER_DEBUG_ENV = 'OM_WORKFLOW_TRIGGER_DEBUG'
29
+
30
+ function isWorkflowTriggerDebugEnabled(): boolean {
31
+ return parseBooleanWithDefault(process.env[WORKFLOW_TRIGGER_DEBUG_ENV], false)
32
+ }
33
+
27
34
  /**
28
35
  * Check if an event should be excluded from trigger processing.
29
36
  */
@@ -42,7 +49,7 @@ export default async function handle(
42
49
  ): Promise<void> {
43
50
  const eventName = ctx.eventName
44
51
  if (!eventName) {
45
- // Skip if no event name (shouldn't happen, but be safe)
52
+ console.warn('[workflow-trigger] Skipping trigger evaluation because subscriber context is missing eventName')
46
53
  return
47
54
  }
48
55
 
@@ -98,6 +105,15 @@ export default async function handle(
98
105
  organizationId,
99
106
  })
100
107
 
108
+ if (isWorkflowTriggerDebugEnabled()) {
109
+ const matched = result.triggered + result.skipped + result.errors.length
110
+ console.log(
111
+ `[workflow-trigger] Evaluated triggers for "${eventName}": ` +
112
+ `tenant=${tenantId} organization=${organizationId} matched=${matched} ` +
113
+ `triggered=${result.triggered} skipped=${result.skipped} errors=${result.errors.length}`
114
+ )
115
+ }
116
+
101
117
  if (result.triggered > 0) {
102
118
  console.log(
103
119
  `[workflow-trigger] Triggered ${result.triggered} workflow(s) for "${eventName}"` +