@open-mercato/core 0.4.2-canary-ec4978dbb3 → 0.4.2-canary-9074fd41ce
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.
- package/dist/generated/entities.ids.generated.js +0 -1
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +0 -2
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/business_rules/data/validators.js +0 -34
- package/dist/modules/business_rules/data/validators.js.map +2 -2
- package/dist/modules/business_rules/index.js +1 -21
- package/dist/modules/business_rules/index.js.map +2 -2
- package/dist/modules/business_rules/lib/rule-engine.js +1 -182
- package/dist/modules/business_rules/lib/rule-engine.js.map +2 -2
- package/dist/modules/sales/acl.js +0 -1
- package/dist/modules/sales/acl.js.map +2 -2
- package/dist/modules/sales/backend/sales/documents/[id]/page.js +0 -12
- package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +0 -62
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/lib/dictionaries.js +0 -3
- package/dist/modules/sales/lib/dictionaries.js.map +2 -2
- package/dist/modules/workflows/acl.js +0 -2
- package/dist/modules/workflows/acl.js.map +2 -2
- package/dist/modules/workflows/api/instances/route.js +6 -18
- package/dist/modules/workflows/api/instances/route.js.map +2 -2
- package/dist/modules/workflows/api/tasks/route.js +1 -6
- package/dist/modules/workflows/api/tasks/route.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/[id]/page.js +1 -9
- package/dist/modules/workflows/backend/definitions/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/[id]/page.meta.js +1 -1
- package/dist/modules/workflows/backend/definitions/[id]/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/create/page.js +15 -24
- package/dist/modules/workflows/backend/definitions/create/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/create/page.meta.js +1 -1
- package/dist/modules/workflows/backend/definitions/create/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/visual-editor/page.js +132 -150
- package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/visual-editor/page.meta.js +1 -1
- package/dist/modules/workflows/backend/definitions/visual-editor/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/events/[id]/page.js +1 -1
- package/dist/modules/workflows/backend/events/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/events/[id]/page.meta.js +2 -2
- package/dist/modules/workflows/backend/events/[id]/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/instances/[id]/page.meta.js +2 -2
- package/dist/modules/workflows/backend/instances/[id]/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/[id]/page.js +1 -1
- package/dist/modules/workflows/backend/tasks/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/[id]/page.meta.js +2 -2
- package/dist/modules/workflows/backend/tasks/[id]/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/page.js +6 -5
- package/dist/modules/workflows/backend/tasks/page.js.map +2 -2
- package/dist/modules/workflows/cli.js +3 -81
- package/dist/modules/workflows/cli.js.map +3 -3
- package/dist/modules/workflows/data/entities.js +1 -64
- package/dist/modules/workflows/data/entities.js.map +2 -2
- package/dist/modules/workflows/data/validators.js +0 -115
- package/dist/modules/workflows/data/validators.js.map +2 -2
- package/dist/modules/workflows/examples/checkout-demo-definition.json +5 -1
- package/dist/modules/workflows/lib/activity-executor.js +13 -75
- package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
- package/dist/modules/workflows/lib/graph-utils.js +2 -71
- package/dist/modules/workflows/lib/graph-utils.js.map +2 -2
- package/dist/modules/workflows/lib/seeds.js +5 -22
- package/dist/modules/workflows/lib/seeds.js.map +2 -2
- package/dist/modules/workflows/lib/start-validator.js +23 -33
- package/dist/modules/workflows/lib/start-validator.js.map +2 -2
- package/dist/modules/workflows/lib/transition-handler.js +45 -157
- package/dist/modules/workflows/lib/transition-handler.js.map +3 -3
- package/generated/entities.ids.generated.ts +0 -1
- package/generated/entity-fields-registry.ts +0 -2
- package/package.json +2 -2
- package/src/modules/business_rules/data/validators.ts +0 -40
- package/src/modules/business_rules/index.ts +0 -25
- package/src/modules/business_rules/lib/rule-engine.ts +1 -281
- package/src/modules/sales/acl.ts +0 -1
- package/src/modules/sales/backend/sales/documents/[id]/page.tsx +0 -16
- package/src/modules/sales/commands/documents.ts +1 -74
- package/src/modules/sales/lib/dictionaries.ts +0 -3
- package/src/modules/workflows/acl.ts +0 -2
- package/src/modules/workflows/api/instances/route.ts +7 -21
- package/src/modules/workflows/api/tasks/route.ts +1 -7
- package/src/modules/workflows/backend/definitions/[id]/page.meta.ts +1 -1
- package/src/modules/workflows/backend/definitions/[id]/page.tsx +0 -9
- package/src/modules/workflows/backend/definitions/create/page.meta.ts +1 -1
- package/src/modules/workflows/backend/definitions/create/page.tsx +0 -9
- package/src/modules/workflows/backend/definitions/visual-editor/page.meta.ts +1 -1
- package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +3 -21
- package/src/modules/workflows/backend/events/[id]/page.meta.ts +2 -2
- package/src/modules/workflows/backend/events/[id]/page.tsx +1 -1
- package/src/modules/workflows/backend/instances/[id]/page.meta.ts +2 -2
- package/src/modules/workflows/backend/tasks/[id]/page.meta.ts +2 -2
- package/src/modules/workflows/backend/tasks/[id]/page.tsx +1 -1
- package/src/modules/workflows/backend/tasks/page.tsx +6 -5
- package/src/modules/workflows/cli.ts +0 -111
- package/src/modules/workflows/data/entities.ts +0 -124
- package/src/modules/workflows/data/validators.ts +0 -138
- package/src/modules/workflows/examples/checkout-demo-definition.json +5 -1
- package/src/modules/workflows/i18n/en.json +0 -71
- package/src/modules/workflows/lib/activity-executor.ts +16 -129
- package/src/modules/workflows/lib/graph-utils.ts +2 -117
- package/src/modules/workflows/lib/seeds.ts +8 -34
- package/src/modules/workflows/lib/start-validator.ts +28 -38
- package/src/modules/workflows/lib/transition-handler.ts +55 -208
- package/dist/generated/entities/workflow_event_trigger/index.js +0 -33
- package/dist/generated/entities/workflow_event_trigger/index.js.map +0 -7
- package/dist/modules/auth/events.js +0 -30
- package/dist/modules/auth/events.js.map +0 -7
- package/dist/modules/business_rules/api/execute/[ruleId]/route.js +0 -145
- package/dist/modules/business_rules/api/execute/[ruleId]/route.js.map +0 -7
- package/dist/modules/catalog/events.js +0 -34
- package/dist/modules/catalog/events.js.map +0 -7
- package/dist/modules/customers/events.js +0 -49
- package/dist/modules/customers/events.js.map +0 -7
- package/dist/modules/directory/events.js +0 -23
- package/dist/modules/directory/events.js.map +0 -7
- package/dist/modules/sales/events.js +0 -63
- package/dist/modules/sales/events.js.map +0 -7
- package/dist/modules/sales/lib/frontend/documentDataEvents.js +0 -25
- package/dist/modules/sales/lib/frontend/documentDataEvents.js.map +0 -7
- package/dist/modules/workflows/components/DefinitionTriggersEditor.js +0 -481
- package/dist/modules/workflows/components/DefinitionTriggersEditor.js.map +0 -7
- package/dist/modules/workflows/components/EventTriggersEditor.js +0 -553
- package/dist/modules/workflows/components/EventTriggersEditor.js.map +0 -7
- package/dist/modules/workflows/events.js +0 -38
- package/dist/modules/workflows/events.js.map +0 -7
- package/dist/modules/workflows/examples/order-approval-definition.json +0 -257
- package/dist/modules/workflows/examples/order-approval-guard-rules.json +0 -32
- package/dist/modules/workflows/lib/event-trigger-service.js +0 -308
- package/dist/modules/workflows/lib/event-trigger-service.js.map +0 -7
- package/dist/modules/workflows/migrations/Migration20260123143500.js +0 -36
- package/dist/modules/workflows/migrations/Migration20260123143500.js.map +0 -7
- package/dist/modules/workflows/subscribers/event-trigger.js +0 -78
- package/dist/modules/workflows/subscribers/event-trigger.js.map +0 -7
- package/dist/modules/workflows/widgets/injection/order-approval/widget.client.js +0 -323
- package/dist/modules/workflows/widgets/injection/order-approval/widget.client.js.map +0 -7
- package/dist/modules/workflows/widgets/injection/order-approval/widget.js +0 -17
- package/dist/modules/workflows/widgets/injection/order-approval/widget.js.map +0 -7
- package/dist/modules/workflows/widgets/injection-table.js +0 -19
- package/dist/modules/workflows/widgets/injection-table.js.map +0 -7
- package/generated/entities/workflow_event_trigger/index.ts +0 -15
- package/src/modules/auth/events.ts +0 -39
- package/src/modules/business_rules/api/execute/[ruleId]/route.ts +0 -163
- package/src/modules/catalog/events.ts +0 -45
- package/src/modules/customers/events.ts +0 -63
- package/src/modules/directory/events.ts +0 -31
- package/src/modules/sales/events.ts +0 -82
- package/src/modules/sales/lib/frontend/documentDataEvents.ts +0 -28
- package/src/modules/workflows/components/DefinitionTriggersEditor.tsx +0 -581
- package/src/modules/workflows/components/EventTriggersEditor.tsx +0 -664
- package/src/modules/workflows/events.ts +0 -49
- package/src/modules/workflows/examples/order-approval-definition.json +0 -257
- package/src/modules/workflows/examples/order-approval-guard-rules.json +0 -32
- package/src/modules/workflows/lib/event-trigger-service.ts +0 -557
- package/src/modules/workflows/migrations/Migration20260123143500.ts +0 -38
- package/src/modules/workflows/subscribers/event-trigger.ts +0 -109
- package/src/modules/workflows/widgets/injection/order-approval/widget.client.tsx +0 -446
- package/src/modules/workflows/widgets/injection/order-approval/widget.ts +0 -16
- package/src/modules/workflows/widgets/injection-table.ts +0 -21
|
@@ -46,63 +46,6 @@ export type UserTaskStatus =
|
|
|
46
46
|
| 'CANCELLED'
|
|
47
47
|
| 'ESCALATED'
|
|
48
48
|
|
|
49
|
-
// ============================================================================
|
|
50
|
-
// Event Trigger Types
|
|
51
|
-
// ============================================================================
|
|
52
|
-
|
|
53
|
-
export type TriggerFilterOperator =
|
|
54
|
-
| 'eq'
|
|
55
|
-
| 'neq'
|
|
56
|
-
| 'gt'
|
|
57
|
-
| 'gte'
|
|
58
|
-
| 'lt'
|
|
59
|
-
| 'lte'
|
|
60
|
-
| 'contains'
|
|
61
|
-
| 'startsWith'
|
|
62
|
-
| 'endsWith'
|
|
63
|
-
| 'in'
|
|
64
|
-
| 'notIn'
|
|
65
|
-
| 'exists'
|
|
66
|
-
| 'notExists'
|
|
67
|
-
| 'regex'
|
|
68
|
-
|
|
69
|
-
export interface TriggerFilterCondition {
|
|
70
|
-
field: string // JSON path (e.g., "status", "metadata.type")
|
|
71
|
-
operator: TriggerFilterOperator
|
|
72
|
-
value: unknown
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export interface TriggerContextMapping {
|
|
76
|
-
targetKey: string // Key in workflow initial context
|
|
77
|
-
sourceExpression: string // Path from event payload (supports dot notation)
|
|
78
|
-
defaultValue?: unknown
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export interface WorkflowEventTriggerConfig {
|
|
82
|
-
filterConditions?: TriggerFilterCondition[]
|
|
83
|
-
contextMapping?: TriggerContextMapping[]
|
|
84
|
-
debounceMs?: number // Debounce rapid events
|
|
85
|
-
maxConcurrentInstances?: number // Limit concurrent instances
|
|
86
|
-
entityType?: string // Entity type for workflow instance metadata (e.g., "SalesOrder")
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* WorkflowDefinitionTrigger - Embedded trigger configuration
|
|
91
|
-
*
|
|
92
|
-
* Triggers are now embedded directly in the workflow definition,
|
|
93
|
-
* allowing users to configure event-based workflow starts during
|
|
94
|
-
* workflow creation in the visual editor.
|
|
95
|
-
*/
|
|
96
|
-
export interface WorkflowDefinitionTrigger {
|
|
97
|
-
triggerId: string
|
|
98
|
-
name: string
|
|
99
|
-
description?: string | null
|
|
100
|
-
eventPattern: string // e.g., "sales.orders.created", "customers.*"
|
|
101
|
-
config?: WorkflowEventTriggerConfig | null
|
|
102
|
-
enabled: boolean
|
|
103
|
-
priority: number
|
|
104
|
-
}
|
|
105
|
-
|
|
106
49
|
// ============================================================================
|
|
107
50
|
// JSONB Structure Interfaces
|
|
108
51
|
// ============================================================================
|
|
@@ -110,7 +53,6 @@ export interface WorkflowDefinitionTrigger {
|
|
|
110
53
|
export interface WorkflowDefinitionData {
|
|
111
54
|
steps: any[] // WorkflowStep[] - will define schema in validators.ts
|
|
112
55
|
transitions: any[] // WorkflowTransition[] - will define schema in validators.ts
|
|
113
|
-
triggers?: WorkflowDefinitionTrigger[] // Event triggers for automatic workflow start
|
|
114
56
|
activities?: any[] // ActivityDefinition[] - will define schema in validators.ts
|
|
115
57
|
queries?: any[]
|
|
116
58
|
signals?: any[]
|
|
@@ -487,71 +429,6 @@ export class WorkflowEvent {
|
|
|
487
429
|
organizationId!: string
|
|
488
430
|
}
|
|
489
431
|
|
|
490
|
-
// ============================================================================
|
|
491
|
-
// Entity: WorkflowEventTrigger
|
|
492
|
-
// ============================================================================
|
|
493
|
-
|
|
494
|
-
/**
|
|
495
|
-
* WorkflowEventTrigger entity
|
|
496
|
-
*
|
|
497
|
-
* Maps event patterns to workflow definitions for automatic triggering.
|
|
498
|
-
* When a matching event is emitted, the corresponding workflow is started
|
|
499
|
-
* with context mapped from the event payload.
|
|
500
|
-
*/
|
|
501
|
-
@Entity({ tableName: 'workflow_event_triggers' })
|
|
502
|
-
@Index({ name: 'workflow_event_triggers_event_pattern_idx', properties: ['eventPattern', 'enabled'] })
|
|
503
|
-
@Index({ name: 'workflow_event_triggers_definition_idx', properties: ['workflowDefinitionId'] })
|
|
504
|
-
@Index({ name: 'workflow_event_triggers_tenant_org_idx', properties: ['tenantId', 'organizationId'] })
|
|
505
|
-
@Index({ name: 'workflow_event_triggers_enabled_priority_idx', properties: ['enabled', 'priority'] })
|
|
506
|
-
export class WorkflowEventTrigger {
|
|
507
|
-
[OptionalProps]?: 'enabled' | 'priority' | 'createdAt' | 'updatedAt' | 'deletedAt'
|
|
508
|
-
|
|
509
|
-
@PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })
|
|
510
|
-
id!: string
|
|
511
|
-
|
|
512
|
-
@Property({ name: 'name', type: 'varchar', length: 255 })
|
|
513
|
-
name!: string
|
|
514
|
-
|
|
515
|
-
@Property({ name: 'description', type: 'text', nullable: true })
|
|
516
|
-
description?: string | null
|
|
517
|
-
|
|
518
|
-
@Property({ name: 'workflow_definition_id', type: 'uuid' })
|
|
519
|
-
workflowDefinitionId!: string
|
|
520
|
-
|
|
521
|
-
@Property({ name: 'event_pattern', type: 'varchar', length: 255 })
|
|
522
|
-
eventPattern!: string
|
|
523
|
-
|
|
524
|
-
@Property({ name: 'config', type: 'jsonb', nullable: true })
|
|
525
|
-
config?: WorkflowEventTriggerConfig | null
|
|
526
|
-
|
|
527
|
-
@Property({ name: 'enabled', type: 'boolean', default: true })
|
|
528
|
-
enabled: boolean = true
|
|
529
|
-
|
|
530
|
-
@Property({ name: 'priority', type: 'integer', default: 0 })
|
|
531
|
-
priority: number = 0
|
|
532
|
-
|
|
533
|
-
@Property({ name: 'tenant_id', type: 'uuid' })
|
|
534
|
-
tenantId!: string
|
|
535
|
-
|
|
536
|
-
@Property({ name: 'organization_id', type: 'uuid' })
|
|
537
|
-
organizationId!: string
|
|
538
|
-
|
|
539
|
-
@Property({ name: 'created_by', type: 'varchar', length: 255, nullable: true })
|
|
540
|
-
createdBy?: string | null
|
|
541
|
-
|
|
542
|
-
@Property({ name: 'updated_by', type: 'varchar', length: 255, nullable: true })
|
|
543
|
-
updatedBy?: string | null
|
|
544
|
-
|
|
545
|
-
@Property({ name: 'created_at', type: Date, onCreate: () => new Date() })
|
|
546
|
-
createdAt: Date = new Date()
|
|
547
|
-
|
|
548
|
-
@Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })
|
|
549
|
-
updatedAt: Date = new Date()
|
|
550
|
-
|
|
551
|
-
@Property({ name: 'deleted_at', type: Date, nullable: true })
|
|
552
|
-
deletedAt?: Date | null
|
|
553
|
-
}
|
|
554
|
-
|
|
555
432
|
// Export all entities as default for MikroORM discovery
|
|
556
433
|
export default [
|
|
557
434
|
WorkflowDefinition,
|
|
@@ -559,5 +436,4 @@ export default [
|
|
|
559
436
|
StepInstance,
|
|
560
437
|
UserTask,
|
|
561
438
|
WorkflowEvent,
|
|
562
|
-
WorkflowEventTrigger,
|
|
563
439
|
]
|
|
@@ -215,43 +215,10 @@ export const workflowTransitionSchema = z.object({
|
|
|
215
215
|
priority: z.number().int().min(0).max(9999).default(0),
|
|
216
216
|
})
|
|
217
217
|
|
|
218
|
-
// Workflow definition trigger schema (embedded in definition)
|
|
219
|
-
// Note: Uses forward reference pattern since eventPatternSchema and eventTriggerConfigSchema are defined later
|
|
220
|
-
export const workflowDefinitionTriggerSchema = z.object({
|
|
221
|
-
triggerId: z.string().min(1).max(100).regex(/^[a-z0-9_-]+$/, 'Trigger ID must contain only lowercase letters, numbers, hyphens, and underscores'),
|
|
222
|
-
name: z.string().min(1).max(255),
|
|
223
|
-
description: z.string().max(2000).optional().nullable(),
|
|
224
|
-
eventPattern: z.string()
|
|
225
|
-
.min(1, 'Event pattern is required')
|
|
226
|
-
.max(255, 'Event pattern must be at most 255 characters')
|
|
227
|
-
.regex(
|
|
228
|
-
/^(\*|[a-z0-9_]+(\.[a-z0-9_*]+)*)$/i,
|
|
229
|
-
'Event pattern must be "*" or a dot-separated pattern with optional wildcards (e.g., "customers.people.created", "sales.orders.*")'
|
|
230
|
-
),
|
|
231
|
-
config: z.object({
|
|
232
|
-
filterConditions: z.array(z.object({
|
|
233
|
-
field: z.string().min(1).max(255),
|
|
234
|
-
operator: z.enum(['eq', 'neq', 'gt', 'gte', 'lt', 'lte', 'contains', 'startsWith', 'endsWith', 'in', 'notIn', 'exists', 'notExists', 'regex']),
|
|
235
|
-
value: z.any(),
|
|
236
|
-
})).max(20).optional(),
|
|
237
|
-
contextMapping: z.array(z.object({
|
|
238
|
-
targetKey: z.string().min(1).max(100),
|
|
239
|
-
sourceExpression: z.string().min(1).max(255),
|
|
240
|
-
defaultValue: z.any().optional(),
|
|
241
|
-
})).max(50).optional(),
|
|
242
|
-
debounceMs: z.number().int().min(0).max(3600000).optional(),
|
|
243
|
-
maxConcurrentInstances: z.number().int().min(1).max(1000).optional(),
|
|
244
|
-
}).optional().nullable(),
|
|
245
|
-
enabled: z.boolean().default(true),
|
|
246
|
-
priority: z.number().int().min(0).max(9999).default(0),
|
|
247
|
-
})
|
|
248
|
-
export type WorkflowDefinitionTrigger = z.infer<typeof workflowDefinitionTriggerSchema>
|
|
249
|
-
|
|
250
218
|
// Workflow definition data (JSONB structure)
|
|
251
219
|
export const workflowDefinitionDataSchema = z.object({
|
|
252
220
|
steps: z.array(workflowStepSchema).min(2, 'Workflow must have at least START and END steps'),
|
|
253
221
|
transitions: z.array(workflowTransitionSchema).min(1, 'Workflow must have at least one transition'),
|
|
254
|
-
triggers: z.array(workflowDefinitionTriggerSchema).optional(), // Event triggers for automatic workflow start
|
|
255
222
|
queries: z.array(z.any()).optional(), // For Phase 7
|
|
256
223
|
signals: z.array(z.any()).optional(), // For Phase 9
|
|
257
224
|
timers: z.array(z.any()).optional(), // For Phase 9
|
|
@@ -521,108 +488,3 @@ export const startWorkflowInputSchema = z.object({
|
|
|
521
488
|
})
|
|
522
489
|
|
|
523
490
|
export type StartWorkflowApiInput = z.infer<typeof startWorkflowInputSchema>
|
|
524
|
-
|
|
525
|
-
// ============================================================================
|
|
526
|
-
// WorkflowEventTrigger Schemas
|
|
527
|
-
// ============================================================================
|
|
528
|
-
|
|
529
|
-
export const triggerFilterOperatorSchema = z.enum([
|
|
530
|
-
'eq',
|
|
531
|
-
'neq',
|
|
532
|
-
'gt',
|
|
533
|
-
'gte',
|
|
534
|
-
'lt',
|
|
535
|
-
'lte',
|
|
536
|
-
'contains',
|
|
537
|
-
'startsWith',
|
|
538
|
-
'endsWith',
|
|
539
|
-
'in',
|
|
540
|
-
'notIn',
|
|
541
|
-
'exists',
|
|
542
|
-
'notExists',
|
|
543
|
-
'regex',
|
|
544
|
-
])
|
|
545
|
-
export type TriggerFilterOperator = z.infer<typeof triggerFilterOperatorSchema>
|
|
546
|
-
|
|
547
|
-
export const triggerFilterConditionSchema = z.object({
|
|
548
|
-
field: z.string().min(1).max(255, 'Field path must be at most 255 characters'),
|
|
549
|
-
operator: triggerFilterOperatorSchema,
|
|
550
|
-
value: z.any(),
|
|
551
|
-
})
|
|
552
|
-
export type TriggerFilterCondition = z.infer<typeof triggerFilterConditionSchema>
|
|
553
|
-
|
|
554
|
-
export const triggerContextMappingSchema = z.object({
|
|
555
|
-
targetKey: z.string().min(1).max(100, 'Target key must be at most 100 characters'),
|
|
556
|
-
sourceExpression: z.string().min(1).max(255, 'Source expression must be at most 255 characters'),
|
|
557
|
-
defaultValue: z.any().optional(),
|
|
558
|
-
})
|
|
559
|
-
export type TriggerContextMapping = z.infer<typeof triggerContextMappingSchema>
|
|
560
|
-
|
|
561
|
-
export const eventTriggerConfigSchema = z.object({
|
|
562
|
-
filterConditions: z.array(triggerFilterConditionSchema).max(20, 'Maximum 20 filter conditions allowed').optional(),
|
|
563
|
-
contextMapping: z.array(triggerContextMappingSchema).max(50, 'Maximum 50 context mappings allowed').optional(),
|
|
564
|
-
debounceMs: z.number().int().min(0).max(3600000, 'Debounce cannot exceed 1 hour').optional(),
|
|
565
|
-
maxConcurrentInstances: z.number().int().min(1).max(1000, 'Max concurrent instances must be between 1 and 1000').optional(),
|
|
566
|
-
})
|
|
567
|
-
export type EventTriggerConfig = z.infer<typeof eventTriggerConfigSchema>
|
|
568
|
-
|
|
569
|
-
export const eventPatternSchema = z.string()
|
|
570
|
-
.min(1, 'Event pattern is required')
|
|
571
|
-
.max(255, 'Event pattern must be at most 255 characters')
|
|
572
|
-
.regex(
|
|
573
|
-
/^(\*|[a-z0-9_]+(\.[a-z0-9_*]+)*)$/i,
|
|
574
|
-
'Event pattern must be "*" or a dot-separated pattern with optional wildcards (e.g., "customers.people.created", "sales.orders.*")'
|
|
575
|
-
)
|
|
576
|
-
|
|
577
|
-
export const createEventTriggerSchema = z.object({
|
|
578
|
-
name: z.string().min(1).max(255),
|
|
579
|
-
description: z.string().max(2000).optional().nullable(),
|
|
580
|
-
workflowDefinitionId: uuid,
|
|
581
|
-
eventPattern: eventPatternSchema,
|
|
582
|
-
config: eventTriggerConfigSchema.optional().nullable(),
|
|
583
|
-
enabled: z.boolean().default(true),
|
|
584
|
-
priority: z.number().int().min(0).max(9999).default(0),
|
|
585
|
-
tenantId: uuid,
|
|
586
|
-
organizationId: uuid,
|
|
587
|
-
createdBy: z.string().max(255).optional().nullable(),
|
|
588
|
-
})
|
|
589
|
-
export type CreateEventTriggerInput = z.infer<typeof createEventTriggerSchema>
|
|
590
|
-
|
|
591
|
-
// API input schema (omits tenant fields - injected from auth context)
|
|
592
|
-
export const createEventTriggerInputSchema = z.object({
|
|
593
|
-
name: z.string().min(1).max(255),
|
|
594
|
-
description: z.string().max(2000).optional().nullable(),
|
|
595
|
-
workflowDefinitionId: uuid,
|
|
596
|
-
eventPattern: eventPatternSchema,
|
|
597
|
-
config: eventTriggerConfigSchema.optional().nullable(),
|
|
598
|
-
enabled: z.boolean().default(true).optional(),
|
|
599
|
-
priority: z.number().int().min(0).max(9999).default(0).optional(),
|
|
600
|
-
})
|
|
601
|
-
export type CreateEventTriggerApiInput = z.infer<typeof createEventTriggerInputSchema>
|
|
602
|
-
|
|
603
|
-
export const updateEventTriggerSchema = createEventTriggerSchema.partial().extend({
|
|
604
|
-
id: uuid,
|
|
605
|
-
})
|
|
606
|
-
export type UpdateEventTriggerInput = z.infer<typeof updateEventTriggerSchema>
|
|
607
|
-
|
|
608
|
-
// API update schema (omits tenant fields and allows partial updates)
|
|
609
|
-
export const updateEventTriggerInputSchema = z.object({
|
|
610
|
-
name: z.string().min(1).max(255).optional(),
|
|
611
|
-
description: z.string().max(2000).optional().nullable(),
|
|
612
|
-
workflowDefinitionId: uuid.optional(),
|
|
613
|
-
eventPattern: eventPatternSchema.optional(),
|
|
614
|
-
config: eventTriggerConfigSchema.optional().nullable(),
|
|
615
|
-
enabled: z.boolean().optional(),
|
|
616
|
-
priority: z.number().int().min(0).max(9999).optional(),
|
|
617
|
-
}).strict()
|
|
618
|
-
export type UpdateEventTriggerApiInput = z.infer<typeof updateEventTriggerInputSchema>
|
|
619
|
-
|
|
620
|
-
export const eventTriggerFilterSchema = z.object({
|
|
621
|
-
name: z.string().optional(),
|
|
622
|
-
workflowDefinitionId: uuid.optional(),
|
|
623
|
-
eventPattern: z.string().optional(),
|
|
624
|
-
enabled: z.boolean().optional(),
|
|
625
|
-
tenantId: uuid.optional(),
|
|
626
|
-
organizationId: uuid.optional(),
|
|
627
|
-
})
|
|
628
|
-
export type EventTriggerFilter = z.infer<typeof eventTriggerFilterSchema>
|
|
@@ -161,7 +161,6 @@
|
|
|
161
161
|
"title": "Workflow Instances",
|
|
162
162
|
"singular": "Workflow Instance",
|
|
163
163
|
"plural": "Workflow Instances",
|
|
164
|
-
"duration": "Duration",
|
|
165
164
|
"fields": {
|
|
166
165
|
"instanceId": "Instance ID",
|
|
167
166
|
"workflowId": "Workflow ID",
|
|
@@ -564,55 +563,6 @@
|
|
|
564
563
|
"CompensationCompleted": "Compensation Completed"
|
|
565
564
|
}
|
|
566
565
|
},
|
|
567
|
-
"triggers": {
|
|
568
|
-
"title": "Event Triggers",
|
|
569
|
-
"add": "Add Trigger",
|
|
570
|
-
"description": "Configure events that automatically start this workflow. When a matching event occurs in the system, a new workflow instance will be created with the mapped context.",
|
|
571
|
-
"empty": {
|
|
572
|
-
"title": "No triggers configured",
|
|
573
|
-
"description": "Click \"Add Trigger\" to create an event trigger that automatically starts this workflow."
|
|
574
|
-
},
|
|
575
|
-
"dialog": {
|
|
576
|
-
"create": {
|
|
577
|
-
"title": "Create Event Trigger"
|
|
578
|
-
},
|
|
579
|
-
"edit": {
|
|
580
|
-
"title": "Edit Event Trigger"
|
|
581
|
-
},
|
|
582
|
-
"description": "Configure when this workflow should be automatically started based on system events."
|
|
583
|
-
},
|
|
584
|
-
"delete": {
|
|
585
|
-
"title": "Delete Event Trigger?",
|
|
586
|
-
"description": "This will remove the event trigger. The change will take effect when you save the workflow definition."
|
|
587
|
-
},
|
|
588
|
-
"fields": {
|
|
589
|
-
"name": "Name",
|
|
590
|
-
"description": "Description",
|
|
591
|
-
"eventPattern": "Event Pattern",
|
|
592
|
-
"enabled": "Enabled",
|
|
593
|
-
"priority": "Priority",
|
|
594
|
-
"filterConditions": "Filter Conditions",
|
|
595
|
-
"contextMapping": "Context Mapping",
|
|
596
|
-
"debounceMs": "Debounce (ms)",
|
|
597
|
-
"maxConcurrent": "Max Concurrent Instances"
|
|
598
|
-
},
|
|
599
|
-
"placeholders": {
|
|
600
|
-
"name": "Order Created Trigger",
|
|
601
|
-
"description": "Describe when this trigger should fire...",
|
|
602
|
-
"quickSelect": "Quick select...",
|
|
603
|
-
"unlimited": "Unlimited"
|
|
604
|
-
},
|
|
605
|
-
"hints": {
|
|
606
|
-
"priority": "Higher priority triggers execute first",
|
|
607
|
-
"eventPattern": "Use * as wildcard: \"sales.orders.*\" matches any order event",
|
|
608
|
-
"filterConditions": "Only trigger when the event payload matches these conditions (all must match)",
|
|
609
|
-
"contextMapping": "Map values from the event payload to the workflow's initial context",
|
|
610
|
-
"debounce": "Delay to prevent rapid re-triggers",
|
|
611
|
-
"maxConcurrent": "Limit simultaneous workflow instances"
|
|
612
|
-
},
|
|
613
|
-
"addCondition": "Add Condition",
|
|
614
|
-
"addMapping": "Add Mapping"
|
|
615
|
-
},
|
|
616
566
|
"common": {
|
|
617
567
|
"save": "Save",
|
|
618
568
|
"cancel": "Cancel",
|
|
@@ -679,27 +629,6 @@
|
|
|
679
629
|
"duplicateNotYetImplemented": "Duplicate functionality is not yet implemented"
|
|
680
630
|
}
|
|
681
631
|
},
|
|
682
|
-
"orderApproval": {
|
|
683
|
-
"groupLabel": "Order Approval",
|
|
684
|
-
"groupDescription": "Review and approve or reject this order",
|
|
685
|
-
"pendingTitle": "Pending Approval",
|
|
686
|
-
"pendingDescription": "This order requires approval before processing",
|
|
687
|
-
"decisionLabel": "Decision",
|
|
688
|
-
"approveButton": "Approve",
|
|
689
|
-
"rejectButton": "Reject",
|
|
690
|
-
"commentsLabel": "Comments",
|
|
691
|
-
"commentsPlaceholder": "Add optional comments...",
|
|
692
|
-
"approvedStatus": "Approved",
|
|
693
|
-
"rejectedStatus": "Rejected",
|
|
694
|
-
"requestApproval": "Request Approval",
|
|
695
|
-
"submitDecision": "Submit Decision",
|
|
696
|
-
"noWorkflowActive": "No approval workflow is active for this order.",
|
|
697
|
-
"processing": "Workflow is processing...",
|
|
698
|
-
"completed": "Approval workflow completed.",
|
|
699
|
-
"startError": "Failed to start approval workflow",
|
|
700
|
-
"completeError": "Failed to complete approval task",
|
|
701
|
-
"missingStatuses": "Missing order status entries. Please ensure pending_approval, approved, and rejected statuses exist in the sales.order_status dictionary."
|
|
702
|
-
},
|
|
703
632
|
"common": {
|
|
704
633
|
"all": "All",
|
|
705
634
|
"enabled": "Enabled",
|
|
@@ -448,30 +448,7 @@ export async function executeEmitEvent(
|
|
|
448
448
|
/**
|
|
449
449
|
* UPDATE_ENTITY activity handler
|
|
450
450
|
*
|
|
451
|
-
* Updates an entity via
|
|
452
|
-
*
|
|
453
|
-
* Config format:
|
|
454
|
-
* ```json
|
|
455
|
-
* {
|
|
456
|
-
* "commandId": "sales.documents.update",
|
|
457
|
-
* "input": {
|
|
458
|
-
* "id": "{{context.orderId}}",
|
|
459
|
-
* "statusEntryId": "{{context.approvedStatusId}}"
|
|
460
|
-
* }
|
|
461
|
-
* }
|
|
462
|
-
* ```
|
|
463
|
-
*
|
|
464
|
-
* Alternative format with statusValue (auto-resolves to statusEntryId):
|
|
465
|
-
* ```json
|
|
466
|
-
* {
|
|
467
|
-
* "commandId": "sales.orders.update",
|
|
468
|
-
* "statusDictionary": "sales.order_status",
|
|
469
|
-
* "input": {
|
|
470
|
-
* "id": "{{context.id}}",
|
|
471
|
-
* "statusValue": "pending_approval"
|
|
472
|
-
* }
|
|
473
|
-
* }
|
|
474
|
-
* ```
|
|
451
|
+
* Updates an entity via query engine
|
|
475
452
|
*/
|
|
476
453
|
export async function executeUpdateEntity(
|
|
477
454
|
em: EntityManager,
|
|
@@ -479,119 +456,29 @@ export async function executeUpdateEntity(
|
|
|
479
456
|
context: ActivityContext,
|
|
480
457
|
container: AwilixContainer
|
|
481
458
|
): Promise<any> {
|
|
482
|
-
const {
|
|
483
|
-
|
|
484
|
-
if (!commandId) {
|
|
485
|
-
throw new Error('UPDATE_ENTITY requires "commandId" field (e.g., "sales.documents.update")')
|
|
486
|
-
}
|
|
459
|
+
const { entityType, entityId, updates } = config
|
|
487
460
|
|
|
488
|
-
if (!
|
|
489
|
-
throw new Error('UPDATE_ENTITY requires "
|
|
461
|
+
if (!entityType || !entityId || !updates) {
|
|
462
|
+
throw new Error('UPDATE_ENTITY requires "entityType", "entityId", and "updates" fields')
|
|
490
463
|
}
|
|
491
464
|
|
|
492
|
-
//
|
|
493
|
-
const
|
|
494
|
-
|
|
495
|
-
if (!commandBus || typeof commandBus.execute !== 'function') {
|
|
496
|
-
throw new Error('CommandBus not available in container')
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
// Prepare final input, resolving statusValue if provided
|
|
500
|
-
let finalInput = { ...input }
|
|
501
|
-
|
|
502
|
-
// If statusValue is provided with a statusDictionary, resolve it to statusEntryId
|
|
503
|
-
if (finalInput.statusValue && statusDictionary) {
|
|
504
|
-
const statusEntryId = await resolveDictionaryEntryId(
|
|
505
|
-
em,
|
|
506
|
-
statusDictionary,
|
|
507
|
-
finalInput.statusValue,
|
|
508
|
-
context.workflowInstance.tenantId,
|
|
509
|
-
context.workflowInstance.organizationId
|
|
510
|
-
)
|
|
511
|
-
if (statusEntryId) {
|
|
512
|
-
finalInput.statusEntryId = statusEntryId
|
|
513
|
-
}
|
|
514
|
-
delete finalInput.statusValue
|
|
515
|
-
}
|
|
465
|
+
// Get query engine from container
|
|
466
|
+
const queryEngine = container.resolve('queryEngine')
|
|
516
467
|
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
const SYSTEM_USER_ID = '00000000-0000-0000-0000-000000000000'
|
|
520
|
-
const ctx = {
|
|
521
|
-
container,
|
|
522
|
-
auth: {
|
|
523
|
-
sub: context.userId || SYSTEM_USER_ID,
|
|
524
|
-
tenantId: context.workflowInstance.tenantId,
|
|
525
|
-
orgId: context.workflowInstance.organizationId,
|
|
526
|
-
isSuperAdmin: false,
|
|
527
|
-
},
|
|
528
|
-
organizationScope: null,
|
|
529
|
-
selectedOrganizationId: context.workflowInstance.organizationId,
|
|
530
|
-
organizationIds: context.workflowInstance.organizationId
|
|
531
|
-
? [context.workflowInstance.organizationId]
|
|
532
|
-
: null,
|
|
468
|
+
if (!queryEngine || typeof queryEngine.update !== 'function') {
|
|
469
|
+
throw new Error('Query engine not available in container')
|
|
533
470
|
}
|
|
534
471
|
|
|
535
|
-
// Execute
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
472
|
+
// Execute update with tenant scoping
|
|
473
|
+
await queryEngine.update({
|
|
474
|
+
entity: entityType,
|
|
475
|
+
where: { id: entityId },
|
|
476
|
+
data: updates,
|
|
477
|
+
tenantId: context.workflowInstance.tenantId,
|
|
478
|
+
organizationId: context.workflowInstance.organizationId,
|
|
539
479
|
})
|
|
540
480
|
|
|
541
|
-
return {
|
|
542
|
-
executed: true,
|
|
543
|
-
commandId,
|
|
544
|
-
result,
|
|
545
|
-
logEntryId: logEntry?.id,
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
/**
|
|
550
|
-
* Helper to resolve dictionary entry ID by value
|
|
551
|
-
*/
|
|
552
|
-
async function resolveDictionaryEntryId(
|
|
553
|
-
em: EntityManager,
|
|
554
|
-
dictionaryKey: string,
|
|
555
|
-
value: string,
|
|
556
|
-
tenantId: string,
|
|
557
|
-
organizationId: string
|
|
558
|
-
): Promise<string | null> {
|
|
559
|
-
try {
|
|
560
|
-
// Import here to avoid circular dependencies
|
|
561
|
-
const { Dictionary, DictionaryEntry } = await import('@open-mercato/core/modules/dictionaries/data/entities')
|
|
562
|
-
|
|
563
|
-
// Find the dictionary
|
|
564
|
-
const dictionary = await em.findOne(Dictionary, {
|
|
565
|
-
key: dictionaryKey,
|
|
566
|
-
tenantId,
|
|
567
|
-
organizationId,
|
|
568
|
-
deletedAt: null,
|
|
569
|
-
})
|
|
570
|
-
|
|
571
|
-
if (!dictionary) {
|
|
572
|
-
console.warn(`[UPDATE_ENTITY] Dictionary not found: ${dictionaryKey}`)
|
|
573
|
-
return null
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
// Find the entry by normalized value
|
|
577
|
-
const normalizedValue = value.toLowerCase().trim()
|
|
578
|
-
const entry = await em.findOne(DictionaryEntry, {
|
|
579
|
-
dictionary: dictionary.id,
|
|
580
|
-
tenantId,
|
|
581
|
-
organizationId,
|
|
582
|
-
normalizedValue,
|
|
583
|
-
})
|
|
584
|
-
|
|
585
|
-
if (!entry) {
|
|
586
|
-
console.warn(`[UPDATE_ENTITY] Dictionary entry not found: ${dictionaryKey}/${value}`)
|
|
587
|
-
return null
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
return entry.id
|
|
591
|
-
} catch (error) {
|
|
592
|
-
console.error(`[UPDATE_ENTITY] Error resolving dictionary entry:`, error)
|
|
593
|
-
return null
|
|
594
|
-
}
|
|
481
|
+
return { updated: true, entityType, entityId, updates }
|
|
595
482
|
}
|
|
596
483
|
|
|
597
484
|
/**
|