@open-mercato/core 0.5.1-develop.2691.d8a0934b37 → 0.5.1-develop.2699.f8b50c8046
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/modules/api_keys/data/entities.js +1 -1
- package/dist/modules/api_keys/data/entities.js.map +1 -1
- package/dist/modules/api_keys/services/apiKeyService.js +5 -5
- package/dist/modules/api_keys/services/apiKeyService.js.map +2 -2
- package/dist/modules/attachments/api/library/[id]/route.js +1 -1
- package/dist/modules/attachments/api/library/[id]/route.js.map +2 -2
- package/dist/modules/attachments/api/library/route.js +7 -9
- package/dist/modules/attachments/api/library/route.js.map +2 -2
- package/dist/modules/attachments/api/partitions/route.js +3 -3
- package/dist/modules/attachments/api/partitions/route.js.map +2 -2
- package/dist/modules/attachments/api/route.js +6 -5
- package/dist/modules/attachments/api/route.js.map +2 -2
- package/dist/modules/attachments/api/transfer/route.js +1 -1
- package/dist/modules/attachments/api/transfer/route.js.map +2 -2
- package/dist/modules/attachments/data/entities.js +2 -1
- package/dist/modules/attachments/data/entities.js.map +2 -2
- package/dist/modules/attachments/lib/ocrQueue.js +1 -1
- package/dist/modules/attachments/lib/ocrQueue.js.map +2 -2
- package/dist/modules/audit_logs/api/audit-logs/actions/export/route.js.map +2 -2
- package/dist/modules/audit_logs/api/audit-logs/actions/route.js.map +2 -2
- package/dist/modules/audit_logs/data/entities.js +1 -1
- package/dist/modules/audit_logs/data/entities.js.map +1 -1
- package/dist/modules/audit_logs/services/actionLogService.js +77 -70
- package/dist/modules/audit_logs/services/actionLogService.js.map +2 -2
- package/dist/modules/auth/api/roles/acl/route.js +1 -1
- package/dist/modules/auth/api/roles/acl/route.js.map +2 -2
- package/dist/modules/auth/api/users/acl/route.js +2 -2
- package/dist/modules/auth/api/users/acl/route.js.map +2 -2
- package/dist/modules/auth/api/users/resend-invite/route.js +1 -1
- package/dist/modules/auth/api/users/resend-invite/route.js.map +2 -2
- package/dist/modules/auth/cli.js +12 -6
- package/dist/modules/auth/cli.js.map +2 -2
- package/dist/modules/auth/commands/users.js +1 -1
- package/dist/modules/auth/commands/users.js.map +2 -2
- package/dist/modules/auth/data/entities.js +1 -1
- package/dist/modules/auth/data/entities.js.map +2 -2
- package/dist/modules/auth/lib/setup-app.js +3 -3
- package/dist/modules/auth/lib/setup-app.js.map +2 -2
- package/dist/modules/auth/services/authService.js +2 -2
- package/dist/modules/auth/services/authService.js.map +2 -2
- package/dist/modules/business_rules/api/rules/route.js +3 -3
- package/dist/modules/business_rules/api/rules/route.js.map +2 -2
- package/dist/modules/business_rules/api/sets/[id]/members/route.js +7 -4
- package/dist/modules/business_rules/api/sets/[id]/members/route.js.map +2 -2
- package/dist/modules/business_rules/api/sets/route.js +3 -3
- package/dist/modules/business_rules/api/sets/route.js.map +2 -2
- package/dist/modules/business_rules/cli.js +1 -1
- package/dist/modules/business_rules/cli.js.map +2 -2
- package/dist/modules/business_rules/data/entities.js +2 -9
- package/dist/modules/business_rules/data/entities.js.map +2 -2
- package/dist/modules/business_rules/lib/rule-engine.js +1 -1
- package/dist/modules/business_rules/lib/rule-engine.js.map +2 -2
- package/dist/modules/catalog/api/option-schemas/route.js +0 -1
- package/dist/modules/catalog/api/option-schemas/route.js.map +2 -2
- package/dist/modules/catalog/data/entities.js +2 -11
- package/dist/modules/catalog/data/entities.js.map +2 -2
- package/dist/modules/configs/data/entities.js +2 -1
- package/dist/modules/configs/data/entities.js.map +2 -2
- package/dist/modules/currencies/commands/fetch-configs.js +3 -3
- package/dist/modules/currencies/commands/fetch-configs.js.map +2 -2
- package/dist/modules/currencies/data/entities.js +1 -1
- package/dist/modules/currencies/data/entities.js.map +2 -2
- package/dist/modules/customer_accounts/api/signup.js +1 -1
- package/dist/modules/customer_accounts/api/signup.js.map +2 -2
- package/dist/modules/customer_accounts/data/entities.js +1 -1
- package/dist/modules/customer_accounts/data/entities.js.map +2 -2
- package/dist/modules/customer_accounts/services/customerInvitationService.js +1 -1
- package/dist/modules/customer_accounts/services/customerInvitationService.js.map +2 -2
- package/dist/modules/customer_accounts/services/customerSessionService.js +1 -1
- package/dist/modules/customer_accounts/services/customerSessionService.js.map +2 -2
- package/dist/modules/customer_accounts/services/customerTokenService.js +12 -7
- package/dist/modules/customer_accounts/services/customerTokenService.js.map +2 -2
- package/dist/modules/customers/api/interactions/conflicts/route.js +19 -17
- package/dist/modules/customers/api/interactions/conflicts/route.js.map +2 -2
- package/dist/modules/customers/api/interactions/counts/route.js +7 -6
- package/dist/modules/customers/api/interactions/counts/route.js.map +2 -2
- package/dist/modules/customers/api/interactions/route.js +28 -42
- package/dist/modules/customers/api/interactions/route.js.map +2 -2
- package/dist/modules/customers/api/utils.js +29 -24
- package/dist/modules/customers/api/utils.js.map +2 -2
- package/dist/modules/customers/cli.js +45 -40
- package/dist/modules/customers/cli.js.map +2 -2
- package/dist/modules/customers/commands/dictionaries.js +1 -1
- package/dist/modules/customers/commands/dictionaries.js.map +2 -2
- package/dist/modules/customers/commands/tags.js +1 -1
- package/dist/modules/customers/commands/tags.js.map +2 -2
- package/dist/modules/customers/data/entities.js +2 -12
- package/dist/modules/customers/data/entities.js.map +2 -2
- package/dist/modules/customers/lib/interactionProjection.js +18 -15
- package/dist/modules/customers/lib/interactionProjection.js.map +2 -2
- package/dist/modules/customers/lib/personCompanyLinkTable.js +6 -8
- package/dist/modules/customers/lib/personCompanyLinkTable.js.map +2 -2
- package/dist/modules/dashboards/api/roles/widgets/route.js +1 -1
- package/dist/modules/dashboards/api/roles/widgets/route.js.map +2 -2
- package/dist/modules/dashboards/api/users/widgets/route.js +1 -1
- package/dist/modules/dashboards/api/users/widgets/route.js.map +2 -2
- package/dist/modules/dashboards/data/entities.js +1 -1
- package/dist/modules/dashboards/data/entities.js.map +1 -1
- package/dist/modules/data_sync/api/mappings/route.js +1 -1
- package/dist/modules/data_sync/api/mappings/route.js.map +2 -2
- package/dist/modules/data_sync/data/entities.js +2 -1
- package/dist/modules/data_sync/data/entities.js.map +2 -2
- package/dist/modules/data_sync/lib/id-mapping.js +1 -1
- package/dist/modules/data_sync/lib/id-mapping.js.map +2 -2
- package/dist/modules/data_sync/lib/sync-run-service.js +1 -1
- package/dist/modules/data_sync/lib/sync-run-service.js.map +2 -2
- package/dist/modules/dictionaries/commands/factory.js +1 -1
- package/dist/modules/dictionaries/commands/factory.js.map +2 -2
- package/dist/modules/dictionaries/data/entities.js +2 -9
- package/dist/modules/dictionaries/data/entities.js.map +2 -2
- package/dist/modules/directory/commands/organizations.js +4 -4
- package/dist/modules/directory/commands/organizations.js.map +2 -2
- package/dist/modules/directory/data/entities.js +2 -1
- package/dist/modules/directory/data/entities.js.map +2 -2
- package/dist/modules/entities/api/definitions.js +2 -2
- package/dist/modules/entities/api/definitions.js.map +2 -2
- package/dist/modules/entities/api/encryption.js +2 -2
- package/dist/modules/entities/api/encryption.js.map +2 -2
- package/dist/modules/entities/api/relations/options.js +2 -2
- package/dist/modules/entities/api/relations/options.js.map +2 -2
- package/dist/modules/entities/cli.js +4 -4
- package/dist/modules/entities/cli.js.map +2 -2
- package/dist/modules/entities/data/entities.js +1 -1
- package/dist/modules/entities/data/entities.js.map +2 -2
- package/dist/modules/entities/lib/field-definitions.js +2 -2
- package/dist/modules/entities/lib/field-definitions.js.map +2 -2
- package/dist/modules/entities/lib/register.js +1 -1
- package/dist/modules/entities/lib/register.js.map +2 -2
- package/dist/modules/feature_toggles/data/entities.js +2 -9
- package/dist/modules/feature_toggles/data/entities.js.map +2 -2
- package/dist/modules/inbox_ops/api/proposals/counts/route.js +3 -6
- package/dist/modules/inbox_ops/api/proposals/counts/route.js.map +2 -2
- package/dist/modules/inbox_ops/data/entities.js +2 -8
- package/dist/modules/inbox_ops/data/entities.js.map +2 -2
- package/dist/modules/inbox_ops/lib/messagesIntegration.js +6 -6
- package/dist/modules/inbox_ops/lib/messagesIntegration.js.map +2 -2
- package/dist/modules/integrations/data/entities.js +2 -1
- package/dist/modules/integrations/data/entities.js.map +2 -2
- package/dist/modules/integrations/lib/credentials-service.js +1 -1
- package/dist/modules/integrations/lib/credentials-service.js.map +2 -2
- package/dist/modules/integrations/lib/log-service.js +1 -1
- package/dist/modules/integrations/lib/log-service.js.map +2 -2
- package/dist/modules/integrations/lib/state-service.js +1 -1
- package/dist/modules/integrations/lib/state-service.js.map +2 -2
- package/dist/modules/messages/api/route.js +90 -93
- package/dist/modules/messages/api/route.js.map +2 -2
- package/dist/modules/messages/api/unread-count/route.js +8 -7
- package/dist/modules/messages/api/unread-count/route.js.map +2 -2
- package/dist/modules/messages/commands/confirmations.js +1 -1
- package/dist/modules/messages/commands/confirmations.js.map +2 -2
- package/dist/modules/messages/commands/messages.js +3 -3
- package/dist/modules/messages/commands/messages.js.map +2 -2
- package/dist/modules/messages/data/entities.js +2 -1
- package/dist/modules/messages/data/entities.js.map +2 -2
- package/dist/modules/messages/lib/email-sender.js +1 -1
- package/dist/modules/messages/lib/email-sender.js.map +2 -2
- package/dist/modules/messages/lib/searchLookup.js +8 -8
- package/dist/modules/messages/lib/searchLookup.js.map +2 -2
- package/dist/modules/messages/lib/tokenConsumption.js +9 -4
- package/dist/modules/messages/lib/tokenConsumption.js.map +2 -2
- package/dist/modules/notifications/data/entities.js +2 -1
- package/dist/modules/notifications/data/entities.js.map +2 -2
- package/dist/modules/notifications/lib/notificationRecipients.js +15 -5
- package/dist/modules/notifications/lib/notificationRecipients.js.map +2 -2
- package/dist/modules/notifications/lib/notificationService.js +39 -34
- package/dist/modules/notifications/lib/notificationService.js.map +2 -2
- package/dist/modules/notifications/workers/create-notification.worker.js +14 -13
- package/dist/modules/notifications/workers/create-notification.worker.js.map +2 -2
- package/dist/modules/payment_gateways/api/transactions/route.js +2 -2
- package/dist/modules/payment_gateways/api/transactions/route.js.map +2 -2
- package/dist/modules/payment_gateways/data/entities.js +2 -1
- package/dist/modules/payment_gateways/data/entities.js.map +2 -2
- package/dist/modules/payment_gateways/lib/gateway-service.js +1 -1
- package/dist/modules/payment_gateways/lib/gateway-service.js.map +2 -2
- package/dist/modules/payment_gateways/lib/webhook-utils.js +2 -2
- package/dist/modules/payment_gateways/lib/webhook-utils.js.map +2 -2
- package/dist/modules/perspectives/data/entities.js +1 -1
- package/dist/modules/perspectives/data/entities.js.map +2 -2
- package/dist/modules/planner/data/entities.js +1 -1
- package/dist/modules/planner/data/entities.js.map +2 -2
- package/dist/modules/progress/data/entities.js +2 -1
- package/dist/modules/progress/data/entities.js.map +2 -2
- package/dist/modules/progress/lib/progressServiceImpl.js +1 -1
- package/dist/modules/progress/lib/progressServiceImpl.js.map +2 -2
- package/dist/modules/query_index/api/status.js +66 -57
- package/dist/modules/query_index/api/status.js.map +2 -2
- package/dist/modules/query_index/cli.js +39 -24
- package/dist/modules/query_index/cli.js.map +2 -2
- package/dist/modules/query_index/data/entities.js +1 -1
- package/dist/modules/query_index/data/entities.js.map +2 -2
- package/dist/modules/query_index/di.js +25 -13
- package/dist/modules/query_index/di.js.map +2 -2
- package/dist/modules/query_index/lib/batch.js +31 -33
- package/dist/modules/query_index/lib/batch.js.map +2 -2
- package/dist/modules/query_index/lib/coverage.js +63 -50
- package/dist/modules/query_index/lib/coverage.js.map +2 -2
- package/dist/modules/query_index/lib/engine.js +592 -588
- package/dist/modules/query_index/lib/engine.js.map +2 -2
- package/dist/modules/query_index/lib/indexer.js +74 -47
- package/dist/modules/query_index/lib/indexer.js.map +2 -2
- package/dist/modules/query_index/lib/jobs.js +37 -24
- package/dist/modules/query_index/lib/jobs.js.map +2 -2
- package/dist/modules/query_index/lib/purge.js +19 -11
- package/dist/modules/query_index/lib/purge.js.map +2 -2
- package/dist/modules/query_index/lib/reindexer.js +47 -44
- package/dist/modules/query_index/lib/reindexer.js.map +2 -2
- package/dist/modules/query_index/lib/search-tokens.js +47 -25
- package/dist/modules/query_index/lib/search-tokens.js.map +2 -2
- package/dist/modules/query_index/lib/stale.js +14 -12
- package/dist/modules/query_index/lib/stale.js.map +2 -2
- package/dist/modules/query_index/lib/subscriber-scope.js +2 -2
- package/dist/modules/query_index/lib/subscriber-scope.js.map +2 -2
- package/dist/modules/query_index/subscribers/delete_one.js +3 -2
- package/dist/modules/query_index/subscribers/delete_one.js.map +2 -2
- package/dist/modules/resources/commands/tag-assignments.js +1 -1
- package/dist/modules/resources/commands/tag-assignments.js.map +2 -2
- package/dist/modules/resources/commands/tags.js +1 -1
- package/dist/modules/resources/commands/tags.js.map +2 -2
- package/dist/modules/resources/data/entities.js +2 -1
- package/dist/modules/resources/data/entities.js.map +2 -2
- package/dist/modules/sales/commands/documentAddresses.js +2 -2
- package/dist/modules/sales/commands/documentAddresses.js.map +2 -2
- package/dist/modules/sales/commands/notes.js.map +2 -2
- package/dist/modules/sales/commands/tags.js +1 -1
- package/dist/modules/sales/commands/tags.js.map +2 -2
- package/dist/modules/sales/data/enrichers.js +9 -8
- package/dist/modules/sales/data/enrichers.js.map +2 -2
- package/dist/modules/sales/data/entities.js +2 -11
- package/dist/modules/sales/data/entities.js.map +2 -2
- package/dist/modules/shipping_carriers/data/entities.js +2 -1
- package/dist/modules/shipping_carriers/data/entities.js.map +2 -2
- package/dist/modules/shipping_carriers/lib/shipping-service.js +1 -1
- package/dist/modules/shipping_carriers/lib/shipping-service.js.map +2 -2
- package/dist/modules/shipping_carriers/lib/webhook-utils.js +2 -2
- package/dist/modules/shipping_carriers/lib/webhook-utils.js.map +2 -2
- package/dist/modules/staff/data/entities.js +1 -1
- package/dist/modules/staff/data/entities.js.map +2 -2
- package/dist/modules/translations/api/[entityType]/[entityId]/route.js +3 -5
- package/dist/modules/translations/api/[entityType]/[entityId]/route.js.map +2 -2
- package/dist/modules/translations/api/context.js +2 -2
- package/dist/modules/translations/api/context.js.map +2 -2
- package/dist/modules/translations/commands/translations.js +46 -39
- package/dist/modules/translations/commands/translations.js.map +2 -2
- package/dist/modules/translations/components/TranslationManager.js +19 -10
- package/dist/modules/translations/components/TranslationManager.js.map +2 -2
- package/dist/modules/translations/data/entities.js +1 -1
- package/dist/modules/translations/data/entities.js.map +2 -2
- package/dist/modules/translations/lib/apply.js +4 -4
- package/dist/modules/translations/lib/apply.js.map +2 -2
- package/dist/modules/translations/lib/batch.js +3 -2
- package/dist/modules/translations/lib/batch.js.map +2 -2
- package/dist/modules/translations/subscribers/cleanup.js +3 -5
- package/dist/modules/translations/subscribers/cleanup.js.map +2 -2
- package/dist/modules/workflows/api/definitions/route.js +1 -1
- package/dist/modules/workflows/api/definitions/route.js.map +2 -2
- package/dist/modules/workflows/cli.js +5 -5
- package/dist/modules/workflows/cli.js.map +2 -2
- package/dist/modules/workflows/data/entities.js +2 -1
- package/dist/modules/workflows/data/entities.js.map +2 -2
- package/dist/modules/workflows/lib/event-logger.js +2 -2
- package/dist/modules/workflows/lib/event-logger.js.map +2 -2
- package/dist/modules/workflows/lib/seeds.js +16 -1
- package/dist/modules/workflows/lib/seeds.js.map +2 -2
- package/dist/modules/workflows/lib/step-handler.js +3 -3
- package/dist/modules/workflows/lib/step-handler.js.map +2 -2
- package/dist/modules/workflows/lib/task-handler.js +1 -1
- package/dist/modules/workflows/lib/task-handler.js.map +2 -2
- package/dist/modules/workflows/lib/transition-handler.js +1 -1
- package/dist/modules/workflows/lib/transition-handler.js.map +2 -2
- package/dist/modules/workflows/lib/workflow-executor.js +2 -2
- package/dist/modules/workflows/lib/workflow-executor.js.map +2 -2
- package/jest.config.cjs +4 -2
- package/package.json +3 -3
- package/src/modules/api_keys/data/entities.ts +1 -1
- package/src/modules/api_keys/services/apiKeyService.ts +5 -5
- package/src/modules/attachments/api/library/[id]/route.ts +1 -1
- package/src/modules/attachments/api/library/route.ts +10 -12
- package/src/modules/attachments/api/partitions/route.ts +3 -3
- package/src/modules/attachments/api/route.ts +10 -8
- package/src/modules/attachments/api/transfer/route.ts +1 -1
- package/src/modules/attachments/data/entities.ts +2 -1
- package/src/modules/attachments/lib/ocrQueue.ts +1 -1
- package/src/modules/audit_logs/api/audit-logs/actions/export/route.ts +4 -4
- package/src/modules/audit_logs/api/audit-logs/actions/route.ts +4 -4
- package/src/modules/audit_logs/data/entities.ts +1 -1
- package/src/modules/audit_logs/services/actionLogService.ts +96 -87
- package/src/modules/auth/api/roles/acl/route.ts +1 -1
- package/src/modules/auth/api/users/acl/route.ts +2 -2
- package/src/modules/auth/api/users/resend-invite/route.ts +1 -1
- package/src/modules/auth/cli.ts +46 -40
- package/src/modules/auth/commands/users.ts +1 -1
- package/src/modules/auth/data/entities.ts +1 -1
- package/src/modules/auth/lib/setup-app.ts +3 -3
- package/src/modules/auth/services/authService.ts +2 -2
- package/src/modules/business_rules/api/rules/route.ts +3 -3
- package/src/modules/business_rules/api/sets/[id]/members/route.ts +7 -4
- package/src/modules/business_rules/api/sets/route.ts +3 -3
- package/src/modules/business_rules/cli.ts +1 -1
- package/src/modules/business_rules/data/entities.ts +2 -9
- package/src/modules/business_rules/lib/rule-engine.ts +1 -1
- package/src/modules/catalog/api/option-schemas/route.ts +0 -1
- package/src/modules/catalog/data/entities.ts +2 -11
- package/src/modules/configs/data/entities.ts +2 -1
- package/src/modules/currencies/commands/fetch-configs.ts +3 -3
- package/src/modules/currencies/data/entities.ts +1 -1
- package/src/modules/customer_accounts/api/signup.ts +1 -1
- package/src/modules/customer_accounts/data/entities.ts +1 -1
- package/src/modules/customer_accounts/services/customerInvitationService.ts +1 -1
- package/src/modules/customer_accounts/services/customerSessionService.ts +1 -1
- package/src/modules/customer_accounts/services/customerTokenService.ts +26 -15
- package/src/modules/customers/api/interactions/conflicts/route.ts +26 -23
- package/src/modules/customers/api/interactions/counts/route.ts +13 -11
- package/src/modules/customers/api/interactions/route.ts +32 -44
- package/src/modules/customers/api/utils.ts +45 -37
- package/src/modules/customers/cli.ts +88 -67
- package/src/modules/customers/commands/dictionaries.ts +1 -1
- package/src/modules/customers/commands/tags.ts +1 -1
- package/src/modules/customers/data/entities.ts +2 -12
- package/src/modules/customers/lib/interactionProjection.ts +36 -25
- package/src/modules/customers/lib/personCompanyLinkTable.ts +13 -18
- package/src/modules/dashboards/api/roles/widgets/route.ts +1 -1
- package/src/modules/dashboards/api/users/widgets/route.ts +1 -1
- package/src/modules/dashboards/data/entities.ts +1 -1
- package/src/modules/data_sync/api/mappings/route.ts +1 -1
- package/src/modules/data_sync/data/entities.ts +2 -1
- package/src/modules/data_sync/lib/id-mapping.ts +1 -1
- package/src/modules/data_sync/lib/sync-run-service.ts +1 -1
- package/src/modules/dictionaries/commands/factory.ts +1 -1
- package/src/modules/dictionaries/data/entities.ts +2 -9
- package/src/modules/directory/commands/organizations.ts +4 -4
- package/src/modules/directory/data/entities.ts +2 -1
- package/src/modules/entities/api/definitions.ts +2 -2
- package/src/modules/entities/api/encryption.ts +2 -2
- package/src/modules/entities/api/relations/options.ts +8 -3
- package/src/modules/entities/cli.ts +4 -4
- package/src/modules/entities/data/entities.ts +1 -1
- package/src/modules/entities/lib/field-definitions.ts +2 -2
- package/src/modules/entities/lib/register.ts +1 -1
- package/src/modules/feature_toggles/data/entities.ts +2 -9
- package/src/modules/inbox_ops/api/proposals/counts/route.ts +10 -10
- package/src/modules/inbox_ops/data/entities.ts +2 -8
- package/src/modules/inbox_ops/lib/messagesIntegration.ts +12 -11
- package/src/modules/integrations/data/entities.ts +2 -1
- package/src/modules/integrations/lib/credentials-service.ts +1 -1
- package/src/modules/integrations/lib/log-service.ts +1 -1
- package/src/modules/integrations/lib/state-service.ts +1 -1
- package/src/modules/messages/api/route.ts +134 -123
- package/src/modules/messages/api/unread-count/route.ts +19 -16
- package/src/modules/messages/commands/confirmations.ts +1 -1
- package/src/modules/messages/commands/messages.ts +3 -3
- package/src/modules/messages/data/entities.ts +2 -1
- package/src/modules/messages/lib/email-sender.ts +1 -1
- package/src/modules/messages/lib/searchLookup.ts +16 -13
- package/src/modules/messages/lib/tokenConsumption.ts +16 -8
- package/src/modules/notifications/data/entities.ts +2 -1
- package/src/modules/notifications/lib/notificationRecipients.ts +42 -26
- package/src/modules/notifications/lib/notificationService.ts +53 -42
- package/src/modules/notifications/workers/create-notification.worker.ts +20 -17
- package/src/modules/payment_gateways/api/transactions/route.ts +2 -2
- package/src/modules/payment_gateways/data/entities.ts +2 -1
- package/src/modules/payment_gateways/lib/gateway-service.ts +1 -1
- package/src/modules/payment_gateways/lib/webhook-utils.ts +2 -2
- package/src/modules/perspectives/data/entities.ts +1 -1
- package/src/modules/planner/data/entities.ts +1 -1
- package/src/modules/progress/data/entities.ts +2 -1
- package/src/modules/progress/lib/progressServiceImpl.ts +1 -1
- package/src/modules/query_index/api/status.ts +85 -71
- package/src/modules/query_index/cli.ts +51 -31
- package/src/modules/query_index/data/entities.ts +1 -1
- package/src/modules/query_index/di.ts +41 -16
- package/src/modules/query_index/lib/batch.ts +68 -55
- package/src/modules/query_index/lib/coverage.ts +115 -88
- package/src/modules/query_index/lib/engine.ts +1036 -1096
- package/src/modules/query_index/lib/indexer.ts +115 -79
- package/src/modules/query_index/lib/jobs.ts +51 -31
- package/src/modules/query_index/lib/purge.ts +25 -19
- package/src/modules/query_index/lib/reindexer.ts +97 -84
- package/src/modules/query_index/lib/search-tokens.ts +67 -36
- package/src/modules/query_index/lib/stale.ts +14 -17
- package/src/modules/query_index/lib/subscriber-scope.ts +6 -5
- package/src/modules/query_index/subscribers/delete_one.ts +9 -6
- package/src/modules/resources/commands/tag-assignments.ts +1 -1
- package/src/modules/resources/commands/tags.ts +1 -1
- package/src/modules/resources/data/entities.ts +2 -1
- package/src/modules/sales/commands/documentAddresses.ts +2 -2
- package/src/modules/sales/commands/notes.ts +1 -1
- package/src/modules/sales/commands/tags.ts +1 -1
- package/src/modules/sales/data/enrichers.ts +17 -13
- package/src/modules/sales/data/entities.ts +2 -11
- package/src/modules/shipping_carriers/data/entities.ts +2 -1
- package/src/modules/shipping_carriers/lib/shipping-service.ts +1 -1
- package/src/modules/shipping_carriers/lib/webhook-utils.ts +2 -2
- package/src/modules/staff/data/entities.ts +1 -1
- package/src/modules/translations/api/[entityType]/[entityId]/route.ts +14 -11
- package/src/modules/translations/api/context.ts +4 -4
- package/src/modules/translations/commands/translations.ts +116 -81
- package/src/modules/translations/components/TranslationManager.tsx +23 -14
- package/src/modules/translations/data/entities.ts +1 -1
- package/src/modules/translations/i18n/de.json +1 -0
- package/src/modules/translations/i18n/en.json +1 -0
- package/src/modules/translations/i18n/es.json +1 -0
- package/src/modules/translations/i18n/pl.json +1 -0
- package/src/modules/translations/lib/apply.ts +6 -6
- package/src/modules/translations/lib/batch.ts +9 -7
- package/src/modules/translations/subscribers/cleanup.ts +10 -11
- package/src/modules/workflows/api/definitions/route.ts +1 -1
- package/src/modules/workflows/cli.ts +5 -5
- package/src/modules/workflows/data/entities.ts +2 -1
- package/src/modules/workflows/lib/event-logger.ts +2 -2
- package/src/modules/workflows/lib/seeds.ts +16 -1
- package/src/modules/workflows/lib/step-handler.ts +3 -3
- package/src/modules/workflows/lib/task-handler.ts +1 -1
- package/src/modules/workflows/lib/transition-handler.ts +1 -1
- package/src/modules/workflows/lib/workflow-executor.ts +2 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/workflows/lib/event-logger.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Workflows Module - Event Logger Service\n *\n * Consolidates workflow event logging for audit trail and replay:\n * - Log workflow lifecycle events\n * - Log step execution events\n * - Log transition events\n * - Query event history\n *\n * Functional API (no classes) following Open Mercato conventions.\n */\n\nimport { EntityManager } from '@mikro-orm/core'\nimport { WorkflowEvent } from '../data/entities'\n\n// ============================================================================\n// Event Type Constants\n// ============================================================================\n\nexport const WorkflowEventTypes = {\n // Workflow lifecycle\n WORKFLOW_STARTED: 'WORKFLOW_STARTED',\n WORKFLOW_COMPLETED: 'WORKFLOW_COMPLETED',\n WORKFLOW_FAILED: 'WORKFLOW_FAILED',\n WORKFLOW_CANCELLED: 'WORKFLOW_CANCELLED',\n WORKFLOW_PAUSED: 'WORKFLOW_PAUSED',\n WORKFLOW_RESUMED: 'WORKFLOW_RESUMED',\n\n // Step lifecycle\n STEP_ENTERED: 'STEP_ENTERED',\n STEP_EXITED: 'STEP_EXITED',\n STEP_FAILED: 'STEP_FAILED',\n STEP_SKIPPED: 'STEP_SKIPPED',\n\n // Transition events\n TRANSITION_EXECUTED: 'TRANSITION_EXECUTED',\n TRANSITION_REJECTED: 'TRANSITION_REJECTED',\n TRANSITION_POST_CONDITION_FAILED: 'TRANSITION_POST_CONDITION_FAILED',\n TRANSITION_FAILED: 'TRANSITION_FAILED',\n\n // Activity events\n ACTIVITY_SCHEDULED: 'ACTIVITY_SCHEDULED',\n ACTIVITY_STARTED: 'ACTIVITY_STARTED',\n ACTIVITY_COMPLETED: 'ACTIVITY_COMPLETED',\n ACTIVITY_FAILED: 'ACTIVITY_FAILED',\n ACTIVITY_RETRY: 'ACTIVITY_RETRY',\n\n // User task events\n USER_TASK_CREATED: 'USER_TASK_CREATED',\n USER_TASK_ASSIGNED: 'USER_TASK_ASSIGNED',\n USER_TASK_STARTED: 'USER_TASK_STARTED',\n USER_TASK_COMPLETED: 'USER_TASK_COMPLETED',\n USER_TASK_CANCELLED: 'USER_TASK_CANCELLED',\n USER_TASK_ESCALATED: 'USER_TASK_ESCALATED',\n\n // Sub-workflow events (Phase 8)\n SUB_WORKFLOW_STARTED: 'SUB_WORKFLOW_STARTED',\n SUB_WORKFLOW_COMPLETED: 'SUB_WORKFLOW_COMPLETED',\n SUB_WORKFLOW_FAILED: 'SUB_WORKFLOW_FAILED',\n\n // Compensation events (Phase 8)\n COMPENSATION_STARTED: 'COMPENSATION_STARTED',\n COMPENSATION_COMPLETED: 'COMPENSATION_COMPLETED',\n COMPENSATION_PARTIAL: 'COMPENSATION_PARTIAL',\n COMPENSATION_FAILED: 'COMPENSATION_FAILED',\n COMPENSATION_ACTIVITY_STARTED: 'COMPENSATION_ACTIVITY_STARTED',\n COMPENSATION_ACTIVITY_COMPLETED: 'COMPENSATION_ACTIVITY_COMPLETED',\n COMPENSATION_ACTIVITY_FAILED: 'COMPENSATION_ACTIVITY_FAILED',\n\n // Signal events (Phase 9)\n SIGNAL_AWAITING: 'SIGNAL_AWAITING',\n SIGNAL_RECEIVED: 'SIGNAL_RECEIVED',\n SIGNAL_TIMEOUT: 'SIGNAL_TIMEOUT',\n\n // Timer events (Phase 9)\n TIMER_FIRED: 'TIMER_FIRED',\n TIMER_CANCELLED: 'TIMER_CANCELLED',\n} as const\n\nexport type WorkflowEventType = typeof WorkflowEventTypes[keyof typeof WorkflowEventTypes]\n\n// ============================================================================\n// Types and Interfaces\n// ============================================================================\n\nexport interface WorkflowEventInput {\n workflowInstanceId: string\n stepInstanceId?: string\n eventType: WorkflowEventType | string\n eventData: any\n userId?: string\n tenantId: string\n organizationId: string\n}\n\nexport interface QueryOptions {\n eventTypes?: Array<WorkflowEventType | string>\n stepInstanceId?: string\n fromDate?: Date\n toDate?: Date\n limit?: number\n offset?: number\n}\n\nexport interface EventStatistics {\n totalEvents: number\n eventsByType: Record<string, number>\n firstEvent?: Date\n lastEvent?: Date\n}\n\n// ============================================================================\n// Main Event Logging Functions\n// ============================================================================\n\n/**\n * Log a workflow event to the event sourcing table\n *\n * @param em - Entity manager\n * @param event - Event input data\n * @returns Created event entity\n */\nexport async function logWorkflowEvent(\n em: EntityManager,\n event: WorkflowEventInput\n): Promise<WorkflowEvent> {\n const workflowEvent = em.create(WorkflowEvent, {\n workflowInstanceId: event.workflowInstanceId,\n stepInstanceId: event.stepInstanceId || null,\n eventType: event.eventType,\n eventData: event.eventData || {},\n userId: event.userId || null,\n tenantId: event.tenantId,\n organizationId: event.organizationId,\n occurredAt: new Date(),\n })\n\n await em.persistAndFlush(workflowEvent)\n\n return workflowEvent\n}\n\n/**\n * Log multiple workflow events in batch\n *\n * @param em - Entity manager\n * @param events - Array of event input data\n * @returns Array of created event entities\n */\nexport async function logWorkflowEvents(\n em: EntityManager,\n events: WorkflowEventInput[]\n): Promise<WorkflowEvent[]> {\n const workflowEvents = events.map(event =>\n em.create(WorkflowEvent, {\n workflowInstanceId: event.workflowInstanceId,\n stepInstanceId: event.stepInstanceId || null,\n eventType: event.eventType,\n eventData: event.eventData || {},\n userId: event.userId || null,\n tenantId: event.tenantId,\n organizationId: event.organizationId,\n occurredAt: new Date(),\n })\n )\n\n await em.persistAndFlush(workflowEvents)\n\n return workflowEvents\n}\n\n// ============================================================================\n// Event Query Functions\n// ============================================================================\n\n/**\n * Get all events for a workflow instance\n *\n * @param em - Entity manager\n * @param instanceId - Workflow instance ID\n * @param options - Query options (filters, pagination)\n * @returns Array of workflow events\n */\nexport async function getWorkflowEvents(\n em: EntityManager,\n instanceId: string,\n options?: QueryOptions\n): Promise<WorkflowEvent[]> {\n const where: any = {\n workflowInstanceId: instanceId,\n }\n\n // Filter by event types\n if (options?.eventTypes && options.eventTypes.length > 0) {\n where.eventType = { $in: options.eventTypes }\n }\n\n // Filter by step instance\n if (options?.stepInstanceId) {\n where.stepInstanceId = options.stepInstanceId\n }\n\n // Filter by date range\n if (options?.fromDate || options?.toDate) {\n where.occurredAt = {}\n if (options.fromDate) {\n where.occurredAt.$gte = options.fromDate\n }\n if (options.toDate) {\n where.occurredAt.$lte = options.toDate\n }\n }\n\n const events = await em.find(\n WorkflowEvent,\n where,\n {\n orderBy: { occurredAt: 'ASC' },\n limit: options?.limit,\n offset: options?.offset,\n }\n )\n\n return events\n}\n\n/**\n * Get events for a specific step instance\n *\n * @param em - Entity manager\n * @param stepInstanceId - Step instance ID\n * @returns Array of workflow events\n */\nexport async function getStepEvents(\n em: EntityManager,\n stepInstanceId: string\n): Promise<WorkflowEvent[]> {\n const events = await em.find(\n WorkflowEvent,\n { stepInstanceId },\n { orderBy: { occurredAt: 'ASC' } }\n )\n\n return events\n}\n\n/**\n * Get the latest event for a workflow instance\n *\n * @param em - Entity manager\n * @param instanceId - Workflow instance ID\n * @param eventType - Optional event type filter\n * @returns Latest workflow event or null\n */\nexport async function getLatestEvent(\n em: EntityManager,\n instanceId: string,\n eventType?: WorkflowEventType | string\n): Promise<WorkflowEvent | null> {\n const where: any = {\n workflowInstanceId: instanceId,\n }\n\n if (eventType) {\n where.eventType = eventType\n }\n\n const event = await em.findOne(\n WorkflowEvent,\n where,\n { orderBy: { occurredAt: 'DESC' } }\n )\n\n return event\n}\n\n/**\n * Count events for a workflow instance\n *\n * @param em - Entity manager\n * @param instanceId - Workflow instance ID\n * @param eventType - Optional event type filter\n * @returns Count of events\n */\nexport async function countEvents(\n em: EntityManager,\n instanceId: string,\n eventType?: WorkflowEventType | string\n): Promise<number> {\n const where: any = {\n workflowInstanceId: instanceId,\n }\n\n if (eventType) {\n where.eventType = eventType\n }\n\n return await em.count(WorkflowEvent, where)\n}\n\n/**\n * Get event statistics for a workflow instance\n *\n * @param em - Entity manager\n * @param instanceId - Workflow instance ID\n * @returns Event statistics\n */\nexport async function getEventStatistics(\n em: EntityManager,\n instanceId: string\n): Promise<EventStatistics> {\n const events = await em.find(\n WorkflowEvent,\n { workflowInstanceId: instanceId },\n { orderBy: { occurredAt: 'ASC' } }\n )\n\n const eventsByType: Record<string, number> = {}\n\n for (const event of events) {\n eventsByType[event.eventType] = (eventsByType[event.eventType] || 0) + 1\n }\n\n return {\n totalEvents: events.length,\n eventsByType,\n firstEvent: events.length > 0 ? events[0].occurredAt : undefined,\n lastEvent: events.length > 0 ? events[events.length - 1].occurredAt : undefined,\n }\n}\n\n/**\n * Check if a specific event type has occurred for a workflow instance\n *\n * @param em - Entity manager\n * @param instanceId - Workflow instance ID\n * @param eventType - Event type to check\n * @returns True if event has occurred\n */\nexport async function hasEventOccurred(\n em: EntityManager,\n instanceId: string,\n eventType: WorkflowEventType | string\n): Promise<boolean> {\n const count = await em.count(WorkflowEvent, {\n workflowInstanceId: instanceId,\n eventType,\n })\n\n return count > 0\n}\n\n/**\n * Get event timeline for a workflow instance (simplified view)\n *\n * @param em - Entity manager\n * @param instanceId - Workflow instance ID\n * @returns Array of simplified event objects\n */\nexport async function getEventTimeline(\n em: EntityManager,\n instanceId: string\n): Promise<Array<{\n eventType: string\n occurredAt: Date\n stepInstanceId?: string\n userId?: string\n summary: string\n}>> {\n const events = await em.find(\n WorkflowEvent,\n { workflowInstanceId: instanceId },\n { orderBy: { occurredAt: 'ASC' } }\n )\n\n return events.map(event => ({\n eventType: event.eventType,\n occurredAt: event.occurredAt,\n stepInstanceId: event.stepInstanceId || undefined,\n userId: event.userId || undefined,\n summary: generateEventSummary(event),\n }))\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Generate human-readable summary for an event\n */\nfunction generateEventSummary(event: WorkflowEvent): string {\n const data = event.eventData || {}\n\n switch (event.eventType) {\n case WorkflowEventTypes.WORKFLOW_STARTED:\n return `Workflow started${data.workflowId ? ` (${data.workflowId})` : ''}`\n\n case WorkflowEventTypes.WORKFLOW_COMPLETED:\n return `Workflow completed${data.result ? ` with result` : ''}`\n\n case WorkflowEventTypes.WORKFLOW_FAILED:\n return `Workflow failed${data.error ? `: ${data.error}` : ''}`\n\n case WorkflowEventTypes.STEP_ENTERED:\n return `Entered step: ${data.stepName || data.stepId || 'unknown'}`\n\n case WorkflowEventTypes.STEP_EXITED:\n return `Exited step: ${data.stepName || data.stepId || 'unknown'}${\n data.executionTimeMs ? ` (${data.executionTimeMs}ms)` : ''\n }`\n\n case WorkflowEventTypes.STEP_FAILED:\n return `Step failed: ${data.stepName || data.stepId || 'unknown'}${\n data.error ? ` - ${data.error}` : ''\n }`\n\n case WorkflowEventTypes.TRANSITION_EXECUTED:\n return `Transition: ${data.fromStepId} \u2192 ${data.toStepId}`\n\n case WorkflowEventTypes.TRANSITION_REJECTED:\n return `Transition blocked: ${data.fromStepId} \u2192 ${data.toStepId}${\n data.reason ? ` (${data.reason})` : ''\n }`\n\n case WorkflowEventTypes.USER_TASK_CREATED:\n return `User task created: ${data.taskName || 'unnamed'}${\n data.assignedTo ? ` (assigned to ${data.assignedTo})` : ''\n }`\n\n case WorkflowEventTypes.USER_TASK_COMPLETED:\n return `User task completed: ${data.taskName || 'unnamed'}`\n\n case WorkflowEventTypes.ACTIVITY_COMPLETED:\n return `Activity completed: ${data.activityName || data.activityId || 'unknown'}`\n\n case WorkflowEventTypes.ACTIVITY_FAILED:\n return `Activity failed: ${data.activityName || data.activityId || 'unknown'}${\n data.error ? ` - ${data.error}` : ''\n }`\n\n case WorkflowEventTypes.COMPENSATION_STARTED:\n return `Compensation started${data.reason ? `: ${data.reason}` : ''}`\n\n case WorkflowEventTypes.COMPENSATION_COMPLETED:\n return `Compensation completed: ${data.compensatedActivities || 0}/${data.totalActivities || 0} activities`\n\n case WorkflowEventTypes.COMPENSATION_PARTIAL:\n return `Partial compensation: ${data.compensatedActivities || 0}/${data.totalActivities || 0} succeeded`\n\n case WorkflowEventTypes.COMPENSATION_FAILED:\n return `Compensation failed: ${data.failedCompensations?.length || 0} activities failed`\n\n case WorkflowEventTypes.COMPENSATION_ACTIVITY_STARTED:\n return `Compensating: ${data.compensationActivityName || data.compensationActivityId || 'unknown'}`\n\n case WorkflowEventTypes.COMPENSATION_ACTIVITY_COMPLETED:\n return `Compensated: ${data.compensationActivityName || data.compensationActivityId || 'unknown'}`\n\n case WorkflowEventTypes.COMPENSATION_ACTIVITY_FAILED:\n return `Compensation failed: ${data.compensationActivityName || data.compensationActivityId || 'unknown'}${\n data.error ? ` - ${data.error}` : ''\n }`\n\n default:\n return event.eventType\n }\n}\n\n/**\n * Validate event type is a known type\n */\nexport function isValidEventType(eventType: string): eventType is WorkflowEventType {\n return Object.values(WorkflowEventTypes).includes(eventType as WorkflowEventType)\n}\n\n/**\n * Get all known event types\n */\nexport function getAllEventTypes(): WorkflowEventType[] {\n return Object.values(WorkflowEventTypes)\n}\n"],
|
|
5
|
-
"mappings": "AAaA,SAAS,qBAAqB;AAMvB,MAAM,qBAAqB;AAAA;AAAA,EAEhC,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,iBAAiB;AAAA,EACjB,oBAAoB;AAAA,EACpB,iBAAiB;AAAA,EACjB,kBAAkB;AAAA;AAAA,EAGlB,cAAc;AAAA,EACd,aAAa;AAAA,EACb,aAAa;AAAA,EACb,cAAc;AAAA;AAAA,EAGd,qBAAqB;AAAA,EACrB,qBAAqB;AAAA,EACrB,kCAAkC;AAAA,EAClC,mBAAmB;AAAA;AAAA,EAGnB,oBAAoB;AAAA,EACpB,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,iBAAiB;AAAA,EACjB,gBAAgB;AAAA;AAAA,EAGhB,mBAAmB;AAAA,EACnB,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB,qBAAqB;AAAA,EACrB,qBAAqB;AAAA,EACrB,qBAAqB;AAAA;AAAA,EAGrB,sBAAsB;AAAA,EACtB,wBAAwB;AAAA,EACxB,qBAAqB;AAAA;AAAA,EAGrB,sBAAsB;AAAA,EACtB,wBAAwB;AAAA,EACxB,sBAAsB;AAAA,EACtB,qBAAqB;AAAA,EACrB,+BAA+B;AAAA,EAC/B,iCAAiC;AAAA,EACjC,8BAA8B;AAAA;AAAA,EAG9B,iBAAiB;AAAA,EACjB,iBAAiB;AAAA,EACjB,gBAAgB;AAAA;AAAA,EAGhB,aAAa;AAAA,EACb,iBAAiB;AACnB;AA6CA,eAAsB,iBACpB,IACA,OACwB;AACxB,QAAM,gBAAgB,GAAG,OAAO,eAAe;AAAA,IAC7C,oBAAoB,MAAM;AAAA,IAC1B,gBAAgB,MAAM,kBAAkB;AAAA,IACxC,WAAW,MAAM;AAAA,IACjB,WAAW,MAAM,aAAa,CAAC;AAAA,IAC/B,QAAQ,MAAM,UAAU;AAAA,IACxB,UAAU,MAAM;AAAA,IAChB,gBAAgB,MAAM;AAAA,IACtB,YAAY,oBAAI,KAAK;AAAA,EACvB,CAAC;AAED,QAAM,GAAG,
|
|
4
|
+
"sourcesContent": ["/**\n * Workflows Module - Event Logger Service\n *\n * Consolidates workflow event logging for audit trail and replay:\n * - Log workflow lifecycle events\n * - Log step execution events\n * - Log transition events\n * - Query event history\n *\n * Functional API (no classes) following Open Mercato conventions.\n */\n\nimport { EntityManager } from '@mikro-orm/core'\nimport { WorkflowEvent } from '../data/entities'\n\n// ============================================================================\n// Event Type Constants\n// ============================================================================\n\nexport const WorkflowEventTypes = {\n // Workflow lifecycle\n WORKFLOW_STARTED: 'WORKFLOW_STARTED',\n WORKFLOW_COMPLETED: 'WORKFLOW_COMPLETED',\n WORKFLOW_FAILED: 'WORKFLOW_FAILED',\n WORKFLOW_CANCELLED: 'WORKFLOW_CANCELLED',\n WORKFLOW_PAUSED: 'WORKFLOW_PAUSED',\n WORKFLOW_RESUMED: 'WORKFLOW_RESUMED',\n\n // Step lifecycle\n STEP_ENTERED: 'STEP_ENTERED',\n STEP_EXITED: 'STEP_EXITED',\n STEP_FAILED: 'STEP_FAILED',\n STEP_SKIPPED: 'STEP_SKIPPED',\n\n // Transition events\n TRANSITION_EXECUTED: 'TRANSITION_EXECUTED',\n TRANSITION_REJECTED: 'TRANSITION_REJECTED',\n TRANSITION_POST_CONDITION_FAILED: 'TRANSITION_POST_CONDITION_FAILED',\n TRANSITION_FAILED: 'TRANSITION_FAILED',\n\n // Activity events\n ACTIVITY_SCHEDULED: 'ACTIVITY_SCHEDULED',\n ACTIVITY_STARTED: 'ACTIVITY_STARTED',\n ACTIVITY_COMPLETED: 'ACTIVITY_COMPLETED',\n ACTIVITY_FAILED: 'ACTIVITY_FAILED',\n ACTIVITY_RETRY: 'ACTIVITY_RETRY',\n\n // User task events\n USER_TASK_CREATED: 'USER_TASK_CREATED',\n USER_TASK_ASSIGNED: 'USER_TASK_ASSIGNED',\n USER_TASK_STARTED: 'USER_TASK_STARTED',\n USER_TASK_COMPLETED: 'USER_TASK_COMPLETED',\n USER_TASK_CANCELLED: 'USER_TASK_CANCELLED',\n USER_TASK_ESCALATED: 'USER_TASK_ESCALATED',\n\n // Sub-workflow events (Phase 8)\n SUB_WORKFLOW_STARTED: 'SUB_WORKFLOW_STARTED',\n SUB_WORKFLOW_COMPLETED: 'SUB_WORKFLOW_COMPLETED',\n SUB_WORKFLOW_FAILED: 'SUB_WORKFLOW_FAILED',\n\n // Compensation events (Phase 8)\n COMPENSATION_STARTED: 'COMPENSATION_STARTED',\n COMPENSATION_COMPLETED: 'COMPENSATION_COMPLETED',\n COMPENSATION_PARTIAL: 'COMPENSATION_PARTIAL',\n COMPENSATION_FAILED: 'COMPENSATION_FAILED',\n COMPENSATION_ACTIVITY_STARTED: 'COMPENSATION_ACTIVITY_STARTED',\n COMPENSATION_ACTIVITY_COMPLETED: 'COMPENSATION_ACTIVITY_COMPLETED',\n COMPENSATION_ACTIVITY_FAILED: 'COMPENSATION_ACTIVITY_FAILED',\n\n // Signal events (Phase 9)\n SIGNAL_AWAITING: 'SIGNAL_AWAITING',\n SIGNAL_RECEIVED: 'SIGNAL_RECEIVED',\n SIGNAL_TIMEOUT: 'SIGNAL_TIMEOUT',\n\n // Timer events (Phase 9)\n TIMER_FIRED: 'TIMER_FIRED',\n TIMER_CANCELLED: 'TIMER_CANCELLED',\n} as const\n\nexport type WorkflowEventType = typeof WorkflowEventTypes[keyof typeof WorkflowEventTypes]\n\n// ============================================================================\n// Types and Interfaces\n// ============================================================================\n\nexport interface WorkflowEventInput {\n workflowInstanceId: string\n stepInstanceId?: string\n eventType: WorkflowEventType | string\n eventData: any\n userId?: string\n tenantId: string\n organizationId: string\n}\n\nexport interface QueryOptions {\n eventTypes?: Array<WorkflowEventType | string>\n stepInstanceId?: string\n fromDate?: Date\n toDate?: Date\n limit?: number\n offset?: number\n}\n\nexport interface EventStatistics {\n totalEvents: number\n eventsByType: Record<string, number>\n firstEvent?: Date\n lastEvent?: Date\n}\n\n// ============================================================================\n// Main Event Logging Functions\n// ============================================================================\n\n/**\n * Log a workflow event to the event sourcing table\n *\n * @param em - Entity manager\n * @param event - Event input data\n * @returns Created event entity\n */\nexport async function logWorkflowEvent(\n em: EntityManager,\n event: WorkflowEventInput\n): Promise<WorkflowEvent> {\n const workflowEvent = em.create(WorkflowEvent, {\n workflowInstanceId: event.workflowInstanceId,\n stepInstanceId: event.stepInstanceId || null,\n eventType: event.eventType,\n eventData: event.eventData || {},\n userId: event.userId || null,\n tenantId: event.tenantId,\n organizationId: event.organizationId,\n occurredAt: new Date(),\n })\n\n await em.persist(workflowEvent).flush()\n\n return workflowEvent\n}\n\n/**\n * Log multiple workflow events in batch\n *\n * @param em - Entity manager\n * @param events - Array of event input data\n * @returns Array of created event entities\n */\nexport async function logWorkflowEvents(\n em: EntityManager,\n events: WorkflowEventInput[]\n): Promise<WorkflowEvent[]> {\n const workflowEvents = events.map(event =>\n em.create(WorkflowEvent, {\n workflowInstanceId: event.workflowInstanceId,\n stepInstanceId: event.stepInstanceId || null,\n eventType: event.eventType,\n eventData: event.eventData || {},\n userId: event.userId || null,\n tenantId: event.tenantId,\n organizationId: event.organizationId,\n occurredAt: new Date(),\n })\n )\n\n await em.persist(workflowEvents).flush()\n\n return workflowEvents\n}\n\n// ============================================================================\n// Event Query Functions\n// ============================================================================\n\n/**\n * Get all events for a workflow instance\n *\n * @param em - Entity manager\n * @param instanceId - Workflow instance ID\n * @param options - Query options (filters, pagination)\n * @returns Array of workflow events\n */\nexport async function getWorkflowEvents(\n em: EntityManager,\n instanceId: string,\n options?: QueryOptions\n): Promise<WorkflowEvent[]> {\n const where: any = {\n workflowInstanceId: instanceId,\n }\n\n // Filter by event types\n if (options?.eventTypes && options.eventTypes.length > 0) {\n where.eventType = { $in: options.eventTypes }\n }\n\n // Filter by step instance\n if (options?.stepInstanceId) {\n where.stepInstanceId = options.stepInstanceId\n }\n\n // Filter by date range\n if (options?.fromDate || options?.toDate) {\n where.occurredAt = {}\n if (options.fromDate) {\n where.occurredAt.$gte = options.fromDate\n }\n if (options.toDate) {\n where.occurredAt.$lte = options.toDate\n }\n }\n\n const events = await em.find(\n WorkflowEvent,\n where,\n {\n orderBy: { occurredAt: 'ASC' },\n limit: options?.limit,\n offset: options?.offset,\n }\n )\n\n return events\n}\n\n/**\n * Get events for a specific step instance\n *\n * @param em - Entity manager\n * @param stepInstanceId - Step instance ID\n * @returns Array of workflow events\n */\nexport async function getStepEvents(\n em: EntityManager,\n stepInstanceId: string\n): Promise<WorkflowEvent[]> {\n const events = await em.find(\n WorkflowEvent,\n { stepInstanceId },\n { orderBy: { occurredAt: 'ASC' } }\n )\n\n return events\n}\n\n/**\n * Get the latest event for a workflow instance\n *\n * @param em - Entity manager\n * @param instanceId - Workflow instance ID\n * @param eventType - Optional event type filter\n * @returns Latest workflow event or null\n */\nexport async function getLatestEvent(\n em: EntityManager,\n instanceId: string,\n eventType?: WorkflowEventType | string\n): Promise<WorkflowEvent | null> {\n const where: any = {\n workflowInstanceId: instanceId,\n }\n\n if (eventType) {\n where.eventType = eventType\n }\n\n const event = await em.findOne(\n WorkflowEvent,\n where,\n { orderBy: { occurredAt: 'DESC' } }\n )\n\n return event\n}\n\n/**\n * Count events for a workflow instance\n *\n * @param em - Entity manager\n * @param instanceId - Workflow instance ID\n * @param eventType - Optional event type filter\n * @returns Count of events\n */\nexport async function countEvents(\n em: EntityManager,\n instanceId: string,\n eventType?: WorkflowEventType | string\n): Promise<number> {\n const where: any = {\n workflowInstanceId: instanceId,\n }\n\n if (eventType) {\n where.eventType = eventType\n }\n\n return await em.count(WorkflowEvent, where)\n}\n\n/**\n * Get event statistics for a workflow instance\n *\n * @param em - Entity manager\n * @param instanceId - Workflow instance ID\n * @returns Event statistics\n */\nexport async function getEventStatistics(\n em: EntityManager,\n instanceId: string\n): Promise<EventStatistics> {\n const events = await em.find(\n WorkflowEvent,\n { workflowInstanceId: instanceId },\n { orderBy: { occurredAt: 'ASC' } }\n )\n\n const eventsByType: Record<string, number> = {}\n\n for (const event of events) {\n eventsByType[event.eventType] = (eventsByType[event.eventType] || 0) + 1\n }\n\n return {\n totalEvents: events.length,\n eventsByType,\n firstEvent: events.length > 0 ? events[0].occurredAt : undefined,\n lastEvent: events.length > 0 ? events[events.length - 1].occurredAt : undefined,\n }\n}\n\n/**\n * Check if a specific event type has occurred for a workflow instance\n *\n * @param em - Entity manager\n * @param instanceId - Workflow instance ID\n * @param eventType - Event type to check\n * @returns True if event has occurred\n */\nexport async function hasEventOccurred(\n em: EntityManager,\n instanceId: string,\n eventType: WorkflowEventType | string\n): Promise<boolean> {\n const count = await em.count(WorkflowEvent, {\n workflowInstanceId: instanceId,\n eventType,\n })\n\n return count > 0\n}\n\n/**\n * Get event timeline for a workflow instance (simplified view)\n *\n * @param em - Entity manager\n * @param instanceId - Workflow instance ID\n * @returns Array of simplified event objects\n */\nexport async function getEventTimeline(\n em: EntityManager,\n instanceId: string\n): Promise<Array<{\n eventType: string\n occurredAt: Date\n stepInstanceId?: string\n userId?: string\n summary: string\n}>> {\n const events = await em.find(\n WorkflowEvent,\n { workflowInstanceId: instanceId },\n { orderBy: { occurredAt: 'ASC' } }\n )\n\n return events.map(event => ({\n eventType: event.eventType,\n occurredAt: event.occurredAt,\n stepInstanceId: event.stepInstanceId || undefined,\n userId: event.userId || undefined,\n summary: generateEventSummary(event),\n }))\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Generate human-readable summary for an event\n */\nfunction generateEventSummary(event: WorkflowEvent): string {\n const data = event.eventData || {}\n\n switch (event.eventType) {\n case WorkflowEventTypes.WORKFLOW_STARTED:\n return `Workflow started${data.workflowId ? ` (${data.workflowId})` : ''}`\n\n case WorkflowEventTypes.WORKFLOW_COMPLETED:\n return `Workflow completed${data.result ? ` with result` : ''}`\n\n case WorkflowEventTypes.WORKFLOW_FAILED:\n return `Workflow failed${data.error ? `: ${data.error}` : ''}`\n\n case WorkflowEventTypes.STEP_ENTERED:\n return `Entered step: ${data.stepName || data.stepId || 'unknown'}`\n\n case WorkflowEventTypes.STEP_EXITED:\n return `Exited step: ${data.stepName || data.stepId || 'unknown'}${\n data.executionTimeMs ? ` (${data.executionTimeMs}ms)` : ''\n }`\n\n case WorkflowEventTypes.STEP_FAILED:\n return `Step failed: ${data.stepName || data.stepId || 'unknown'}${\n data.error ? ` - ${data.error}` : ''\n }`\n\n case WorkflowEventTypes.TRANSITION_EXECUTED:\n return `Transition: ${data.fromStepId} \u2192 ${data.toStepId}`\n\n case WorkflowEventTypes.TRANSITION_REJECTED:\n return `Transition blocked: ${data.fromStepId} \u2192 ${data.toStepId}${\n data.reason ? ` (${data.reason})` : ''\n }`\n\n case WorkflowEventTypes.USER_TASK_CREATED:\n return `User task created: ${data.taskName || 'unnamed'}${\n data.assignedTo ? ` (assigned to ${data.assignedTo})` : ''\n }`\n\n case WorkflowEventTypes.USER_TASK_COMPLETED:\n return `User task completed: ${data.taskName || 'unnamed'}`\n\n case WorkflowEventTypes.ACTIVITY_COMPLETED:\n return `Activity completed: ${data.activityName || data.activityId || 'unknown'}`\n\n case WorkflowEventTypes.ACTIVITY_FAILED:\n return `Activity failed: ${data.activityName || data.activityId || 'unknown'}${\n data.error ? ` - ${data.error}` : ''\n }`\n\n case WorkflowEventTypes.COMPENSATION_STARTED:\n return `Compensation started${data.reason ? `: ${data.reason}` : ''}`\n\n case WorkflowEventTypes.COMPENSATION_COMPLETED:\n return `Compensation completed: ${data.compensatedActivities || 0}/${data.totalActivities || 0} activities`\n\n case WorkflowEventTypes.COMPENSATION_PARTIAL:\n return `Partial compensation: ${data.compensatedActivities || 0}/${data.totalActivities || 0} succeeded`\n\n case WorkflowEventTypes.COMPENSATION_FAILED:\n return `Compensation failed: ${data.failedCompensations?.length || 0} activities failed`\n\n case WorkflowEventTypes.COMPENSATION_ACTIVITY_STARTED:\n return `Compensating: ${data.compensationActivityName || data.compensationActivityId || 'unknown'}`\n\n case WorkflowEventTypes.COMPENSATION_ACTIVITY_COMPLETED:\n return `Compensated: ${data.compensationActivityName || data.compensationActivityId || 'unknown'}`\n\n case WorkflowEventTypes.COMPENSATION_ACTIVITY_FAILED:\n return `Compensation failed: ${data.compensationActivityName || data.compensationActivityId || 'unknown'}${\n data.error ? ` - ${data.error}` : ''\n }`\n\n default:\n return event.eventType\n }\n}\n\n/**\n * Validate event type is a known type\n */\nexport function isValidEventType(eventType: string): eventType is WorkflowEventType {\n return Object.values(WorkflowEventTypes).includes(eventType as WorkflowEventType)\n}\n\n/**\n * Get all known event types\n */\nexport function getAllEventTypes(): WorkflowEventType[] {\n return Object.values(WorkflowEventTypes)\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -90,8 +90,23 @@ async function seedGuardRules(em, scope, fileName) {
|
|
|
90
90
|
continue;
|
|
91
91
|
}
|
|
92
92
|
const entry = em.create(BusinessRule, {
|
|
93
|
-
...rule,
|
|
94
93
|
ruleId,
|
|
94
|
+
ruleName: rule.ruleName,
|
|
95
|
+
ruleType: rule.ruleType,
|
|
96
|
+
entityType: rule.entityType,
|
|
97
|
+
conditionExpression: rule.conditionExpression,
|
|
98
|
+
eventType: rule.eventType,
|
|
99
|
+
ruleCategory: rule.ruleCategory,
|
|
100
|
+
description: rule.description,
|
|
101
|
+
successActions: rule.successActions,
|
|
102
|
+
failureActions: rule.failureActions,
|
|
103
|
+
enabled: rule.enabled,
|
|
104
|
+
priority: rule.priority,
|
|
105
|
+
version: rule.version,
|
|
106
|
+
effectiveFrom: rule.effectiveFrom,
|
|
107
|
+
effectiveTo: rule.effectiveTo,
|
|
108
|
+
createdBy: rule.createdBy,
|
|
109
|
+
updatedBy: rule.updatedBy,
|
|
95
110
|
tenantId: scope.tenantId,
|
|
96
111
|
organizationId: scope.organizationId
|
|
97
112
|
});
|
|
@@ -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
|
|
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 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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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -46,7 +46,7 @@ async function enterStep(em, instance, stepId, context) {
|
|
|
46
46
|
createdAt: now,
|
|
47
47
|
updatedAt: now
|
|
48
48
|
});
|
|
49
|
-
await em.
|
|
49
|
+
await em.persist(stepInstance).flush();
|
|
50
50
|
await logStepEvent(em, {
|
|
51
51
|
workflowInstanceId: instance.id,
|
|
52
52
|
stepInstanceId: stepInstance.id,
|
|
@@ -315,7 +315,7 @@ async function handleUserTaskStep(em, instance, stepInstance, stepDef, context)
|
|
|
315
315
|
createdAt: now,
|
|
316
316
|
updatedAt: now
|
|
317
317
|
});
|
|
318
|
-
await em.
|
|
318
|
+
await em.persist(userTask).flush();
|
|
319
319
|
await logStepEvent(em, {
|
|
320
320
|
workflowInstanceId: instance.id,
|
|
321
321
|
stepInstanceId: stepInstance.id,
|
|
@@ -514,7 +514,7 @@ async function logStepEvent(em, event) {
|
|
|
514
514
|
...event,
|
|
515
515
|
occurredAt: /* @__PURE__ */ new Date()
|
|
516
516
|
});
|
|
517
|
-
await em.
|
|
517
|
+
await em.persist(workflowEvent).flush();
|
|
518
518
|
return workflowEvent;
|
|
519
519
|
}
|
|
520
520
|
function calculateDueDate(duration) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/workflows/lib/step-handler.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Workflows Module - Step Handler Service\n *\n * Handles individual workflow step execution:\n * - Creating step instances when entering a step\n * - Executing step logic based on step type (START, END, AUTOMATED, USER_TASK)\n * - Completing step instances when exiting\n *\n * Functional API (no classes) following Open Mercato conventions.\n */\n\nimport { EntityManager } from '@mikro-orm/core'\nimport {\n WorkflowInstance,\n WorkflowDefinition,\n StepInstance,\n UserTask,\n WorkflowEvent,\n type StepInstanceStatus,\n type WorkflowStepType,\n} from '../data/entities'\n\n// ============================================================================\n// Types and Interfaces\n// ============================================================================\n\nexport interface StepExecutionContext {\n workflowContext: Record<string, any>\n userId?: string\n triggerData?: any\n}\n\nexport interface StepExecutionResult {\n status: 'COMPLETED' | 'WAITING' | 'FAILED'\n outputData?: any\n nextSteps?: string[] // For parallel forks (Phase 7)\n waitReason?: 'USER_TASK' | 'SIGNAL' | 'TIMER'\n error?: string\n}\n\nexport class StepExecutionError extends Error {\n constructor(\n message: string,\n public code: string,\n public details?: any\n ) {\n super(message)\n this.name = 'StepExecutionError'\n }\n}\n\n// ============================================================================\n// Main Step Execution Functions\n// ============================================================================\n\n/**\n * Enter a workflow step - create step instance and mark as ACTIVE\n *\n * @param em - Entity manager\n * @param instance - Workflow instance\n * @param stepId - Step ID to enter\n * @param context - Execution context\n * @returns Created step instance\n */\nexport async function enterStep(\n em: EntityManager,\n instance: WorkflowInstance,\n stepId: string,\n context: StepExecutionContext\n): Promise<StepInstance> {\n // Load workflow definition to get step details\n const definition = await em.findOne(WorkflowDefinition, {\n id: instance.definitionId,\n })\n\n if (!definition) {\n throw new StepExecutionError(\n `Workflow definition not found: ${instance.definitionId}`,\n 'DEFINITION_NOT_FOUND',\n { definitionId: instance.definitionId }\n )\n }\n\n // Find step in definition\n const stepDef = definition.definition.steps.find((s: any) => s.stepId === stepId)\n if (!stepDef) {\n throw new StepExecutionError(\n `Step not found in workflow definition: ${stepId}`,\n 'STEP_NOT_FOUND',\n { workflowId: definition.workflowId, stepId }\n )\n }\n\n const now = new Date()\n\n // Create step instance\n const stepInstance = em.create(StepInstance, {\n workflowInstanceId: instance.id,\n stepId: stepDef.stepId,\n stepName: stepDef.stepName,\n stepType: stepDef.stepType,\n status: 'ACTIVE',\n inputData: context.triggerData || null,\n enteredAt: now,\n retryCount: 0,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n createdAt: now,\n updatedAt: now,\n })\n\n await em.persistAndFlush(stepInstance)\n\n // Log STEP_ENTERED event\n await logStepEvent(em, {\n workflowInstanceId: instance.id,\n stepInstanceId: stepInstance.id,\n eventType: 'STEP_ENTERED',\n eventData: {\n stepId: stepDef.stepId,\n stepName: stepDef.stepName,\n stepType: stepDef.stepType,\n },\n userId: context.userId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n return stepInstance\n}\n\n/**\n * Exit a workflow step - mark as completed and record timing\n *\n * @param em - Entity manager\n * @param stepInstance - Step instance to exit\n * @param outputData - Optional output data from step execution\n */\nexport async function exitStep(\n em: EntityManager,\n stepInstance: StepInstance,\n outputData?: any\n): Promise<void> {\n const now = new Date()\n\n // Calculate execution time if we have enteredAt\n let executionTimeMs: number | null = null\n if (stepInstance.enteredAt) {\n executionTimeMs = now.getTime() - stepInstance.enteredAt.getTime()\n }\n\n // Update step instance\n stepInstance.status = 'COMPLETED'\n stepInstance.outputData = outputData || null\n stepInstance.exitedAt = now\n stepInstance.executionTimeMs = executionTimeMs\n stepInstance.updatedAt = now\n\n await em.flush()\n\n // Log STEP_EXITED event\n await logStepEvent(em, {\n workflowInstanceId: stepInstance.workflowInstanceId,\n stepInstanceId: stepInstance.id,\n eventType: 'STEP_EXITED',\n eventData: {\n stepId: stepInstance.stepId,\n status: 'COMPLETED',\n executionTimeMs,\n hasOutput: !!outputData,\n },\n tenantId: stepInstance.tenantId,\n organizationId: stepInstance.organizationId,\n })\n}\n\n/**\n * Execute a workflow step based on its type\n *\n * Main entry point for step execution. Handles:\n * - START: Immediate completion\n * - END: Workflow completion\n * - AUTOMATED: Activity execution (MVP: immediate completion)\n * - USER_TASK: Create user task and wait\n * - SUB_WORKFLOW: Invoke child workflow\n *\n * @param em - Entity manager\n * @param instance - Workflow instance\n * @param stepId - Step ID to execute\n * @param context - Execution context\n * @param container - DI container (required for SUB_WORKFLOW steps)\n * @returns Execution result with status and output\n */\nexport async function executeStep(\n em: EntityManager,\n instance: WorkflowInstance,\n stepId: string,\n context: StepExecutionContext,\n container?: any\n): Promise<StepExecutionResult> {\n try {\n // Enter the step (create step instance)\n const stepInstance = await enterStep(em, instance, stepId, context)\n\n // Load workflow definition to get step configuration\n const definition = await em.findOne(WorkflowDefinition, {\n id: instance.definitionId,\n })\n\n if (!definition) {\n throw new StepExecutionError(\n `Workflow definition not found: ${instance.definitionId}`,\n 'DEFINITION_NOT_FOUND',\n { definitionId: instance.definitionId }\n )\n }\n\n const stepDef = definition.definition.steps.find((s: any) => s.stepId === stepId)\n if (!stepDef) {\n throw new StepExecutionError(\n `Step not found: ${stepId}`,\n 'STEP_NOT_FOUND',\n { stepId }\n )\n }\n\n // Execute based on step type\n const result = await executeStepByType(\n em,\n instance,\n stepInstance,\n stepDef,\n context,\n container\n )\n\n // If step completed, exit it\n if (result.status === 'COMPLETED') {\n await exitStep(em, stepInstance, result.outputData)\n }\n\n return result\n } catch (error) {\n // Handle step execution errors\n const errorMessage = error instanceof Error ? error.message : String(error)\n\n // Try to mark step as failed if we have a step instance\n try {\n const failedStepInstance = await em.findOne(StepInstance, {\n workflowInstanceId: instance.id,\n stepId,\n status: 'ACTIVE',\n })\n\n if (failedStepInstance) {\n failedStepInstance.status = 'FAILED'\n failedStepInstance.errorData = {\n error: errorMessage,\n details: error instanceof StepExecutionError ? error.details : undefined,\n }\n failedStepInstance.exitedAt = new Date()\n failedStepInstance.updatedAt = new Date()\n await em.flush()\n\n await logStepEvent(em, {\n workflowInstanceId: instance.id,\n stepInstanceId: failedStepInstance.id,\n eventType: 'STEP_FAILED',\n eventData: { error: errorMessage },\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n }\n } catch (updateError) {\n // Swallow update errors to preserve original error\n console.error('Failed to update step instance with error:', updateError)\n }\n\n return {\n status: 'FAILED',\n error: errorMessage,\n }\n }\n}\n\n// ============================================================================\n// Step Type Handlers\n// ============================================================================\n\n/**\n * Execute step based on its type\n *\n * @param em - Entity manager\n * @param instance - Workflow instance\n * @param stepInstance - Step instance\n * @param stepDef - Step definition from workflow\n * @param context - Execution context\n * @returns Execution result\n */\nasync function executeStepByType(\n em: EntityManager,\n instance: WorkflowInstance,\n stepInstance: StepInstance,\n stepDef: any,\n context: StepExecutionContext,\n container?: any\n): Promise<StepExecutionResult> {\n const stepType: WorkflowStepType = stepDef.stepType\n\n switch (stepType) {\n case 'START':\n return handleStartStep(stepDef, context)\n\n case 'END':\n return handleEndStep(stepDef, context)\n\n case 'AUTOMATED':\n return await handleAutomatedStep(em, instance, stepInstance, stepDef, context, container)\n\n case 'USER_TASK':\n return await handleUserTaskStep(em, instance, stepInstance, stepDef, context)\n\n case 'SUB_WORKFLOW':\n if (!container) {\n throw new StepExecutionError(\n 'Container required for SUB_WORKFLOW execution',\n 'CONTAINER_REQUIRED',\n { stepType }\n )\n }\n return await handleSubWorkflowStep(em, container, instance, stepInstance, stepDef, context)\n\n case 'WAIT_FOR_SIGNAL':\n return await handleWaitForSignalStep(em, instance, stepInstance, stepDef, context)\n\n case 'PARALLEL_FORK':\n case 'PARALLEL_JOIN':\n case 'WAIT_FOR_TIMER':\n // These will be implemented in later phases\n throw new StepExecutionError(\n `Step type not yet implemented: ${stepType}`,\n 'STEP_TYPE_NOT_IMPLEMENTED',\n { stepType }\n )\n\n default:\n throw new StepExecutionError(\n `Unknown step type: ${stepType}`,\n 'UNKNOWN_STEP_TYPE',\n { stepType }\n )\n }\n}\n\n/**\n * Handle START step - no-op, immediately complete\n */\nfunction handleStartStep(\n stepDef: any,\n context: StepExecutionContext\n): StepExecutionResult {\n return {\n status: 'COMPLETED',\n outputData: {\n stepType: 'START',\n timestamp: new Date().toISOString(),\n },\n }\n}\n\n/**\n * Handle END step - mark as complete\n */\nfunction handleEndStep(\n stepDef: any,\n context: StepExecutionContext\n): StepExecutionResult {\n return {\n status: 'COMPLETED',\n outputData: {\n stepType: 'END',\n timestamp: new Date().toISOString(),\n finalContext: context.workflowContext,\n },\n }\n}\n\n/**\n * Handle AUTOMATED step - execute activities\n *\n * Executes activities defined in step configuration.\n * Supports both sync and async activities.\n */\nasync function handleAutomatedStep(\n em: EntityManager,\n instance: WorkflowInstance,\n stepInstance: StepInstance,\n stepDef: any,\n context: StepExecutionContext,\n container?: any\n): Promise<StepExecutionResult> {\n // Extract activities from step definition\n const activities = stepDef.activities || []\n\n if (activities.length === 0) {\n // No activities defined - immediate completion (legacy behavior)\n return {\n status: 'COMPLETED',\n outputData: {\n stepType: 'AUTOMATED',\n timestamp: new Date().toISOString(),\n },\n }\n }\n\n // Import activity executor\n const { executeActivities } = await import('./activity-executor')\n\n try {\n // Execute activities with proper context\n const results = await executeActivities(em, container, activities, {\n workflowInstance: instance,\n workflowContext: context.workflowContext,\n stepContext: { stepId: stepDef.stepId, stepName: stepDef.stepName },\n stepInstanceId: stepInstance.id,\n userId: context.userId,\n })\n\n // Check if there are pending async activities\n const pendingActivities = results.filter(r => r.async && !r.success)\n if (pendingActivities.length > 0) {\n // Workflow should pause and wait for async activities\n instance.status = 'WAITING_FOR_ACTIVITIES'\n instance.pausedAt = new Date()\n instance.updatedAt = new Date()\n await em.flush()\n\n return {\n status: 'WAITING',\n waitReason: 'SIGNAL', // Reuse SIGNAL wait reason (will be resumed by activity completion)\n outputData: {\n pendingActivities: pendingActivities.map(r => ({\n activityId: r.activityId,\n activityName: r.activityName,\n jobId: r.jobId,\n })),\n },\n }\n }\n\n // Check for failures in sync activities\n const failures = results.filter(r => !r.success && !r.async)\n if (failures.length > 0) {\n const errorMessages = failures.map(f => `${f.activityName || f.activityId}: ${f.error}`).join('; ')\n return {\n status: 'FAILED',\n error: `${failures.length} activity(ies) failed: ${errorMessages}`,\n outputData: {\n failures: failures.map(f => ({\n activityId: f.activityId,\n activityName: f.activityName,\n error: f.error,\n retryCount: f.retryCount,\n })),\n },\n }\n }\n\n // All activities completed successfully\n const activityOutputs = results.reduce((acc, r) => {\n if (r.output) {\n acc[r.activityId] = r.output\n }\n return acc\n }, {} as Record<string, any>)\n\n return {\n status: 'COMPLETED',\n outputData: {\n stepType: 'AUTOMATED',\n timestamp: new Date().toISOString(),\n activityResults: activityOutputs,\n activityCount: results.length,\n },\n }\n } catch (error: any) {\n return {\n status: 'FAILED',\n error: `Activity execution failed: ${error.message}`,\n }\n }\n}\n\n/**\n * Handle USER_TASK step - create user task and enter waiting state\n *\n * Creates a UserTask entity and returns WAITING status.\n * The workflow will pause until the task is completed by a user.\n */\nasync function handleUserTaskStep(\n em: EntityManager,\n instance: WorkflowInstance,\n stepInstance: StepInstance,\n stepDef: any,\n context: StepExecutionContext\n): Promise<StepExecutionResult> {\n const userTaskConfig = stepDef.userTaskConfig || {}\n\n // Handle assignedTo - if it's an array, treat it as roles\n let assignedTo = userTaskConfig.assignedTo || null\n let assignedToRoles = userTaskConfig.assignedToRoles || null\n\n if (Array.isArray(assignedTo)) {\n assignedToRoles = assignedTo\n assignedTo = null\n }\n\n // Create user task\n const now = new Date()\n const userTask = em.create(UserTask, {\n workflowInstanceId: instance.id,\n stepInstanceId: stepInstance.id,\n taskName: stepDef.stepName,\n description: stepDef.description || null,\n status: 'PENDING',\n formSchema: userTaskConfig.formSchema || null,\n formData: null,\n assignedTo: assignedTo,\n assignedToRoles: assignedToRoles,\n dueDate: userTaskConfig.slaDuration ? calculateDueDate(userTaskConfig.slaDuration) : null,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n createdAt: now,\n updatedAt: now,\n })\n\n await em.persistAndFlush(userTask)\n\n // Log USER_TASK_CREATED event\n await logStepEvent(em, {\n workflowInstanceId: instance.id,\n stepInstanceId: stepInstance.id,\n eventType: 'USER_TASK_CREATED',\n eventData: {\n userTaskId: userTask.id,\n taskName: userTask.taskName,\n assignedTo: userTask.assignedTo,\n assignedToRoles: userTask.assignedToRoles,\n },\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n // Pause workflow execution - workflow waits for user task completion\n instance.status = 'PAUSED'\n instance.updatedAt = now\n await em.flush()\n\n return {\n status: 'WAITING',\n waitReason: 'USER_TASK',\n outputData: {\n userTaskId: userTask.id,\n },\n }\n}\n\n/**\n * Handle SUB_WORKFLOW step - invoke another workflow and wait for completion\n *\n * Creates a child workflow instance with mapped input data,\n * executes it synchronously, and returns mapped output data.\n */\nasync function handleSubWorkflowStep(\n em: EntityManager,\n container: any,\n instance: WorkflowInstance,\n stepInstance: StepInstance,\n stepDef: any,\n context: StepExecutionContext\n): Promise<StepExecutionResult> {\n const { subWorkflowId, inputMapping, outputMapping, version } = stepDef.config || {}\n\n if (!subWorkflowId) {\n return {\n status: 'FAILED',\n error: 'Sub-workflow ID not specified in step configuration'\n }\n }\n\n // Map input data from parent context to child context\n const childContext = mapInputData(instance.context, inputMapping || {})\n\n // Import workflow executor functions\n const { startWorkflow, executeWorkflow } = await import('./workflow-executor')\n\n try {\n // Start child workflow with parent metadata\n const childInstance = await startWorkflow(em, {\n workflowId: subWorkflowId,\n version,\n initialContext: childContext,\n correlationKey: instance.correlationKey || undefined,\n metadata: {\n ...instance.metadata,\n labels: {\n ...instance.metadata?.labels,\n parentInstanceId: instance.id,\n parentStepId: stepDef.stepId,\n parentStepInstanceId: stepInstance.id,\n },\n },\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n // Log sub-workflow invocation event\n await logStepEvent(em, {\n workflowInstanceId: instance.id,\n stepInstanceId: stepInstance.id,\n eventType: 'SUB_WORKFLOW_STARTED',\n eventData: {\n childInstanceId: childInstance.id,\n subWorkflowId,\n version,\n inputData: childContext,\n },\n userId: context.userId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n // Execute child workflow synchronously\n const result = await executeWorkflow(em, container, childInstance.id, {\n userId: context.userId,\n })\n\n // Handle child workflow result\n if (result.status === 'COMPLETED') {\n // Map output data from child context to parent context\n const outputData = mapOutputData(result.context, outputMapping || {})\n\n await logStepEvent(em, {\n workflowInstanceId: instance.id,\n stepInstanceId: stepInstance.id,\n eventType: 'SUB_WORKFLOW_COMPLETED',\n eventData: {\n childInstanceId: childInstance.id,\n outputData,\n },\n userId: context.userId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n return {\n status: 'COMPLETED',\n outputData,\n }\n } else if (result.status === 'FAILED') {\n await logStepEvent(em, {\n workflowInstanceId: instance.id,\n stepInstanceId: stepInstance.id,\n eventType: 'SUB_WORKFLOW_FAILED',\n eventData: {\n childInstanceId: childInstance.id,\n error: result.errors?.join(', '),\n },\n userId: context.userId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n return {\n status: 'FAILED',\n error: `Sub-workflow failed: ${result.errors?.join(', ')}`,\n }\n } else {\n // WAITING, PAUSED, etc. - For synchronous execution, treat as error\n return {\n status: 'FAILED',\n error: `Sub-workflow ended in unexpected state: ${result.status}`,\n }\n }\n } catch (error: any) {\n await logStepEvent(em, {\n workflowInstanceId: instance.id,\n stepInstanceId: stepInstance.id,\n eventType: 'SUB_WORKFLOW_FAILED',\n eventData: {\n subWorkflowId,\n error: error.message,\n },\n userId: context.userId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n return {\n status: 'FAILED',\n error: `Sub-workflow execution failed: ${error.message}`,\n }\n }\n}\n\n/**\n * Handle WAIT_FOR_SIGNAL step - pause workflow until signal received\n *\n * Creates a waiting state and pauses the workflow until an external signal\n * with the matching signal name is received. The signal payload will be merged\n * into the workflow context when received.\n */\nasync function handleWaitForSignalStep(\n em: EntityManager,\n instance: WorkflowInstance,\n stepInstance: StepInstance,\n stepDef: any,\n context: StepExecutionContext\n): Promise<StepExecutionResult> {\n const signalConfig = stepDef.signalConfig || {}\n const signalName = signalConfig.signalName || stepDef.stepId\n const timeout = signalConfig.timeout ? parseDuration(signalConfig.timeout) : null\n\n const now = new Date()\n\n // Log signal awaiting event\n await logStepEvent(em, {\n workflowInstanceId: instance.id,\n stepInstanceId: stepInstance.id,\n eventType: 'SIGNAL_AWAITING',\n eventData: {\n signalName,\n timeout,\n description: stepDef.description,\n },\n userId: context.userId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n // Pause workflow execution\n instance.status = 'PAUSED'\n instance.pausedAt = now\n instance.updatedAt = now\n await em.flush()\n\n // Return WAITING status to halt executor\n return {\n status: 'WAITING',\n waitReason: 'SIGNAL',\n outputData: {\n signalName,\n timeout,\n awaitingSince: now,\n },\n }\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Parse ISO 8601 duration to milliseconds\n *\n * Supports:\n * - ISO 8601: PT5M (5 minutes), PT1H (1 hour), P1D (1 day), P3D (3 days)\n * - Simple formats: 5m, 1h, 3d, 30s\n *\n * @param duration - Duration string\n * @returns Duration in milliseconds\n */\nfunction parseDuration(duration: string): number {\n // Try ISO 8601 format first: P[n]DT[n]H[n]M[n]S\n const iso8601Regex = /P(?:(\\d+)D)?(?:T(?:(\\d+)H)?(?:(\\d+)M)?(?:(\\d+)S)?)?/\n const iso8601Match = duration.match(iso8601Regex)\n\n if (iso8601Match && iso8601Match[0] === duration) {\n const days = parseInt(iso8601Match[1] || '0')\n const hours = parseInt(iso8601Match[2] || '0')\n const minutes = parseInt(iso8601Match[3] || '0')\n const seconds = parseInt(iso8601Match[4] || '0')\n\n return (\n days * 24 * 60 * 60 * 1000 +\n hours * 60 * 60 * 1000 +\n minutes * 60 * 1000 +\n seconds * 1000\n )\n }\n\n // Try simple format: 1d, 5h, 30m, 45s\n const simpleRegex = /^(\\d+)(d|h|m|s)$/\n const simpleMatch = duration.match(simpleRegex)\n\n if (simpleMatch) {\n const value = parseInt(simpleMatch[1])\n const unit = simpleMatch[2]\n\n switch (unit) {\n case 'd':\n return value * 24 * 60 * 60 * 1000\n case 'h':\n return value * 60 * 60 * 1000\n case 'm':\n return value * 60 * 1000\n case 's':\n return value * 1000\n }\n }\n\n throw new StepExecutionError(\n `Invalid duration format: ${duration}`,\n 'INVALID_DURATION',\n { duration }\n )\n}\n\n/**\n * Log step-related event to event sourcing table\n */\nasync function logStepEvent(\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.persistAndFlush(workflowEvent)\n return workflowEvent\n}\n\n/**\n * Calculate due date from ISO 8601 duration string\n *\n * @param duration - ISO 8601 duration (e.g., \"P1D\" for 1 day)\n * @returns Due date\n */\nfunction calculateDueDate(duration: string): Date {\n // Simple implementation for MVP\n // Supports: P1D (1 day), P1H (1 hour), P1W (1 week)\n const now = new Date()\n\n const daysMatch = duration.match(/P(\\d+)D/)\n if (daysMatch) {\n const days = parseInt(daysMatch[1], 10)\n return new Date(now.getTime() + days * 24 * 60 * 60 * 1000)\n }\n\n const hoursMatch = duration.match(/PT(\\d+)H/)\n if (hoursMatch) {\n const hours = parseInt(hoursMatch[1], 10)\n return new Date(now.getTime() + hours * 60 * 60 * 1000)\n }\n\n const weeksMatch = duration.match(/P(\\d+)W/)\n if (weeksMatch) {\n const weeks = parseInt(weeksMatch[1], 10)\n return new Date(now.getTime() + weeks * 7 * 24 * 60 * 60 * 1000)\n }\n\n // Default: 1 day\n return new Date(now.getTime() + 24 * 60 * 60 * 1000)\n}\n\n/**\n * Get nested value from object using dot notation\n *\n * @param obj - Source object\n * @param path - Dot-notation path (e.g., \"user.email\")\n * @returns Value at path or undefined\n */\nfunction getNestedValue(obj: any, path: string): any {\n return path.split('.').reduce((current, key) => current?.[key], obj)\n}\n\n/**\n * Set nested value in object using dot notation\n *\n * @param obj - Target object\n * @param path - Dot-notation path (e.g., \"user.email\")\n * @param value - Value to set\n */\nfunction setNestedValue(obj: any, path: string, value: any): void {\n const keys = path.split('.')\n const lastKey = keys.pop()!\n const target = keys.reduce((current, key) => {\n if (!(key in current)) current[key] = {}\n return current[key]\n }, obj)\n target[lastKey] = value\n}\n\n/**\n * Map data from source context using mapping configuration\n *\n * @param sourceContext - Source data object\n * @param mapping - Mapping configuration (targetKey -> sourcePath)\n * @returns Mapped data object\n */\nfunction mapInputData(\n sourceContext: Record<string, any>,\n mapping: Record<string, string>\n): Record<string, any> {\n const result: Record<string, any> = {}\n\n for (const [targetKey, sourcePath] of Object.entries(mapping)) {\n const value = getNestedValue(sourceContext, sourcePath)\n if (value !== undefined) {\n setNestedValue(result, targetKey, value)\n }\n }\n\n // If no mapping provided, pass entire context\n return Object.keys(result).length > 0 ? result : sourceContext\n}\n\n/**\n * Map output data from child context back to parent\n *\n * @param childContext - Child workflow context\n * @param mapping - Mapping configuration (targetKey -> sourcePath)\n * @returns Mapped output data\n */\nfunction mapOutputData(\n childContext: Record<string, any>,\n mapping: Record<string, string>\n): Record<string, any> {\n const result: Record<string, any> = {}\n\n for (const [targetKey, sourcePath] of Object.entries(mapping)) {\n const value = getNestedValue(childContext, sourcePath)\n if (value !== undefined) {\n setNestedValue(result, targetKey, value)\n }\n }\n\n // If no mapping provided, pass entire child context\n return Object.keys(result).length > 0 ? result : childContext\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["/**\n * Workflows Module - Step Handler Service\n *\n * Handles individual workflow step execution:\n * - Creating step instances when entering a step\n * - Executing step logic based on step type (START, END, AUTOMATED, USER_TASK)\n * - Completing step instances when exiting\n *\n * Functional API (no classes) following Open Mercato conventions.\n */\n\nimport { EntityManager } from '@mikro-orm/core'\nimport {\n WorkflowInstance,\n WorkflowDefinition,\n StepInstance,\n UserTask,\n WorkflowEvent,\n type StepInstanceStatus,\n type WorkflowStepType,\n} from '../data/entities'\n\n// ============================================================================\n// Types and Interfaces\n// ============================================================================\n\nexport interface StepExecutionContext {\n workflowContext: Record<string, any>\n userId?: string\n triggerData?: any\n}\n\nexport interface StepExecutionResult {\n status: 'COMPLETED' | 'WAITING' | 'FAILED'\n outputData?: any\n nextSteps?: string[] // For parallel forks (Phase 7)\n waitReason?: 'USER_TASK' | 'SIGNAL' | 'TIMER'\n error?: string\n}\n\nexport class StepExecutionError extends Error {\n constructor(\n message: string,\n public code: string,\n public details?: any\n ) {\n super(message)\n this.name = 'StepExecutionError'\n }\n}\n\n// ============================================================================\n// Main Step Execution Functions\n// ============================================================================\n\n/**\n * Enter a workflow step - create step instance and mark as ACTIVE\n *\n * @param em - Entity manager\n * @param instance - Workflow instance\n * @param stepId - Step ID to enter\n * @param context - Execution context\n * @returns Created step instance\n */\nexport async function enterStep(\n em: EntityManager,\n instance: WorkflowInstance,\n stepId: string,\n context: StepExecutionContext\n): Promise<StepInstance> {\n // Load workflow definition to get step details\n const definition = await em.findOne(WorkflowDefinition, {\n id: instance.definitionId,\n })\n\n if (!definition) {\n throw new StepExecutionError(\n `Workflow definition not found: ${instance.definitionId}`,\n 'DEFINITION_NOT_FOUND',\n { definitionId: instance.definitionId }\n )\n }\n\n // Find step in definition\n const stepDef = definition.definition.steps.find((s: any) => s.stepId === stepId)\n if (!stepDef) {\n throw new StepExecutionError(\n `Step not found in workflow definition: ${stepId}`,\n 'STEP_NOT_FOUND',\n { workflowId: definition.workflowId, stepId }\n )\n }\n\n const now = new Date()\n\n // Create step instance\n const stepInstance = em.create(StepInstance, {\n workflowInstanceId: instance.id,\n stepId: stepDef.stepId,\n stepName: stepDef.stepName,\n stepType: stepDef.stepType,\n status: 'ACTIVE',\n inputData: context.triggerData || null,\n enteredAt: now,\n retryCount: 0,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n createdAt: now,\n updatedAt: now,\n })\n\n await em.persist(stepInstance).flush()\n\n // Log STEP_ENTERED event\n await logStepEvent(em, {\n workflowInstanceId: instance.id,\n stepInstanceId: stepInstance.id,\n eventType: 'STEP_ENTERED',\n eventData: {\n stepId: stepDef.stepId,\n stepName: stepDef.stepName,\n stepType: stepDef.stepType,\n },\n userId: context.userId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n return stepInstance\n}\n\n/**\n * Exit a workflow step - mark as completed and record timing\n *\n * @param em - Entity manager\n * @param stepInstance - Step instance to exit\n * @param outputData - Optional output data from step execution\n */\nexport async function exitStep(\n em: EntityManager,\n stepInstance: StepInstance,\n outputData?: any\n): Promise<void> {\n const now = new Date()\n\n // Calculate execution time if we have enteredAt\n let executionTimeMs: number | null = null\n if (stepInstance.enteredAt) {\n executionTimeMs = now.getTime() - stepInstance.enteredAt.getTime()\n }\n\n // Update step instance\n stepInstance.status = 'COMPLETED'\n stepInstance.outputData = outputData || null\n stepInstance.exitedAt = now\n stepInstance.executionTimeMs = executionTimeMs\n stepInstance.updatedAt = now\n\n await em.flush()\n\n // Log STEP_EXITED event\n await logStepEvent(em, {\n workflowInstanceId: stepInstance.workflowInstanceId,\n stepInstanceId: stepInstance.id,\n eventType: 'STEP_EXITED',\n eventData: {\n stepId: stepInstance.stepId,\n status: 'COMPLETED',\n executionTimeMs,\n hasOutput: !!outputData,\n },\n tenantId: stepInstance.tenantId,\n organizationId: stepInstance.organizationId,\n })\n}\n\n/**\n * Execute a workflow step based on its type\n *\n * Main entry point for step execution. Handles:\n * - START: Immediate completion\n * - END: Workflow completion\n * - AUTOMATED: Activity execution (MVP: immediate completion)\n * - USER_TASK: Create user task and wait\n * - SUB_WORKFLOW: Invoke child workflow\n *\n * @param em - Entity manager\n * @param instance - Workflow instance\n * @param stepId - Step ID to execute\n * @param context - Execution context\n * @param container - DI container (required for SUB_WORKFLOW steps)\n * @returns Execution result with status and output\n */\nexport async function executeStep(\n em: EntityManager,\n instance: WorkflowInstance,\n stepId: string,\n context: StepExecutionContext,\n container?: any\n): Promise<StepExecutionResult> {\n try {\n // Enter the step (create step instance)\n const stepInstance = await enterStep(em, instance, stepId, context)\n\n // Load workflow definition to get step configuration\n const definition = await em.findOne(WorkflowDefinition, {\n id: instance.definitionId,\n })\n\n if (!definition) {\n throw new StepExecutionError(\n `Workflow definition not found: ${instance.definitionId}`,\n 'DEFINITION_NOT_FOUND',\n { definitionId: instance.definitionId }\n )\n }\n\n const stepDef = definition.definition.steps.find((s: any) => s.stepId === stepId)\n if (!stepDef) {\n throw new StepExecutionError(\n `Step not found: ${stepId}`,\n 'STEP_NOT_FOUND',\n { stepId }\n )\n }\n\n // Execute based on step type\n const result = await executeStepByType(\n em,\n instance,\n stepInstance,\n stepDef,\n context,\n container\n )\n\n // If step completed, exit it\n if (result.status === 'COMPLETED') {\n await exitStep(em, stepInstance, result.outputData)\n }\n\n return result\n } catch (error) {\n // Handle step execution errors\n const errorMessage = error instanceof Error ? error.message : String(error)\n\n // Try to mark step as failed if we have a step instance\n try {\n const failedStepInstance = await em.findOne(StepInstance, {\n workflowInstanceId: instance.id,\n stepId,\n status: 'ACTIVE',\n })\n\n if (failedStepInstance) {\n failedStepInstance.status = 'FAILED'\n failedStepInstance.errorData = {\n error: errorMessage,\n details: error instanceof StepExecutionError ? error.details : undefined,\n }\n failedStepInstance.exitedAt = new Date()\n failedStepInstance.updatedAt = new Date()\n await em.flush()\n\n await logStepEvent(em, {\n workflowInstanceId: instance.id,\n stepInstanceId: failedStepInstance.id,\n eventType: 'STEP_FAILED',\n eventData: { error: errorMessage },\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n }\n } catch (updateError) {\n // Swallow update errors to preserve original error\n console.error('Failed to update step instance with error:', updateError)\n }\n\n return {\n status: 'FAILED',\n error: errorMessage,\n }\n }\n}\n\n// ============================================================================\n// Step Type Handlers\n// ============================================================================\n\n/**\n * Execute step based on its type\n *\n * @param em - Entity manager\n * @param instance - Workflow instance\n * @param stepInstance - Step instance\n * @param stepDef - Step definition from workflow\n * @param context - Execution context\n * @returns Execution result\n */\nasync function executeStepByType(\n em: EntityManager,\n instance: WorkflowInstance,\n stepInstance: StepInstance,\n stepDef: any,\n context: StepExecutionContext,\n container?: any\n): Promise<StepExecutionResult> {\n const stepType: WorkflowStepType = stepDef.stepType\n\n switch (stepType) {\n case 'START':\n return handleStartStep(stepDef, context)\n\n case 'END':\n return handleEndStep(stepDef, context)\n\n case 'AUTOMATED':\n return await handleAutomatedStep(em, instance, stepInstance, stepDef, context, container)\n\n case 'USER_TASK':\n return await handleUserTaskStep(em, instance, stepInstance, stepDef, context)\n\n case 'SUB_WORKFLOW':\n if (!container) {\n throw new StepExecutionError(\n 'Container required for SUB_WORKFLOW execution',\n 'CONTAINER_REQUIRED',\n { stepType }\n )\n }\n return await handleSubWorkflowStep(em, container, instance, stepInstance, stepDef, context)\n\n case 'WAIT_FOR_SIGNAL':\n return await handleWaitForSignalStep(em, instance, stepInstance, stepDef, context)\n\n case 'PARALLEL_FORK':\n case 'PARALLEL_JOIN':\n case 'WAIT_FOR_TIMER':\n // These will be implemented in later phases\n throw new StepExecutionError(\n `Step type not yet implemented: ${stepType}`,\n 'STEP_TYPE_NOT_IMPLEMENTED',\n { stepType }\n )\n\n default:\n throw new StepExecutionError(\n `Unknown step type: ${stepType}`,\n 'UNKNOWN_STEP_TYPE',\n { stepType }\n )\n }\n}\n\n/**\n * Handle START step - no-op, immediately complete\n */\nfunction handleStartStep(\n stepDef: any,\n context: StepExecutionContext\n): StepExecutionResult {\n return {\n status: 'COMPLETED',\n outputData: {\n stepType: 'START',\n timestamp: new Date().toISOString(),\n },\n }\n}\n\n/**\n * Handle END step - mark as complete\n */\nfunction handleEndStep(\n stepDef: any,\n context: StepExecutionContext\n): StepExecutionResult {\n return {\n status: 'COMPLETED',\n outputData: {\n stepType: 'END',\n timestamp: new Date().toISOString(),\n finalContext: context.workflowContext,\n },\n }\n}\n\n/**\n * Handle AUTOMATED step - execute activities\n *\n * Executes activities defined in step configuration.\n * Supports both sync and async activities.\n */\nasync function handleAutomatedStep(\n em: EntityManager,\n instance: WorkflowInstance,\n stepInstance: StepInstance,\n stepDef: any,\n context: StepExecutionContext,\n container?: any\n): Promise<StepExecutionResult> {\n // Extract activities from step definition\n const activities = stepDef.activities || []\n\n if (activities.length === 0) {\n // No activities defined - immediate completion (legacy behavior)\n return {\n status: 'COMPLETED',\n outputData: {\n stepType: 'AUTOMATED',\n timestamp: new Date().toISOString(),\n },\n }\n }\n\n // Import activity executor\n const { executeActivities } = await import('./activity-executor')\n\n try {\n // Execute activities with proper context\n const results = await executeActivities(em, container, activities, {\n workflowInstance: instance,\n workflowContext: context.workflowContext,\n stepContext: { stepId: stepDef.stepId, stepName: stepDef.stepName },\n stepInstanceId: stepInstance.id,\n userId: context.userId,\n })\n\n // Check if there are pending async activities\n const pendingActivities = results.filter(r => r.async && !r.success)\n if (pendingActivities.length > 0) {\n // Workflow should pause and wait for async activities\n instance.status = 'WAITING_FOR_ACTIVITIES'\n instance.pausedAt = new Date()\n instance.updatedAt = new Date()\n await em.flush()\n\n return {\n status: 'WAITING',\n waitReason: 'SIGNAL', // Reuse SIGNAL wait reason (will be resumed by activity completion)\n outputData: {\n pendingActivities: pendingActivities.map(r => ({\n activityId: r.activityId,\n activityName: r.activityName,\n jobId: r.jobId,\n })),\n },\n }\n }\n\n // Check for failures in sync activities\n const failures = results.filter(r => !r.success && !r.async)\n if (failures.length > 0) {\n const errorMessages = failures.map(f => `${f.activityName || f.activityId}: ${f.error}`).join('; ')\n return {\n status: 'FAILED',\n error: `${failures.length} activity(ies) failed: ${errorMessages}`,\n outputData: {\n failures: failures.map(f => ({\n activityId: f.activityId,\n activityName: f.activityName,\n error: f.error,\n retryCount: f.retryCount,\n })),\n },\n }\n }\n\n // All activities completed successfully\n const activityOutputs = results.reduce((acc, r) => {\n if (r.output) {\n acc[r.activityId] = r.output\n }\n return acc\n }, {} as Record<string, any>)\n\n return {\n status: 'COMPLETED',\n outputData: {\n stepType: 'AUTOMATED',\n timestamp: new Date().toISOString(),\n activityResults: activityOutputs,\n activityCount: results.length,\n },\n }\n } catch (error: any) {\n return {\n status: 'FAILED',\n error: `Activity execution failed: ${error.message}`,\n }\n }\n}\n\n/**\n * Handle USER_TASK step - create user task and enter waiting state\n *\n * Creates a UserTask entity and returns WAITING status.\n * The workflow will pause until the task is completed by a user.\n */\nasync function handleUserTaskStep(\n em: EntityManager,\n instance: WorkflowInstance,\n stepInstance: StepInstance,\n stepDef: any,\n context: StepExecutionContext\n): Promise<StepExecutionResult> {\n const userTaskConfig = stepDef.userTaskConfig || {}\n\n // Handle assignedTo - if it's an array, treat it as roles\n let assignedTo = userTaskConfig.assignedTo || null\n let assignedToRoles = userTaskConfig.assignedToRoles || null\n\n if (Array.isArray(assignedTo)) {\n assignedToRoles = assignedTo\n assignedTo = null\n }\n\n // Create user task\n const now = new Date()\n const userTask = em.create(UserTask, {\n workflowInstanceId: instance.id,\n stepInstanceId: stepInstance.id,\n taskName: stepDef.stepName,\n description: stepDef.description || null,\n status: 'PENDING',\n formSchema: userTaskConfig.formSchema || null,\n formData: null,\n assignedTo: assignedTo,\n assignedToRoles: assignedToRoles,\n dueDate: userTaskConfig.slaDuration ? calculateDueDate(userTaskConfig.slaDuration) : null,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n createdAt: now,\n updatedAt: now,\n })\n\n await em.persist(userTask).flush()\n\n // Log USER_TASK_CREATED event\n await logStepEvent(em, {\n workflowInstanceId: instance.id,\n stepInstanceId: stepInstance.id,\n eventType: 'USER_TASK_CREATED',\n eventData: {\n userTaskId: userTask.id,\n taskName: userTask.taskName,\n assignedTo: userTask.assignedTo,\n assignedToRoles: userTask.assignedToRoles,\n },\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n // Pause workflow execution - workflow waits for user task completion\n instance.status = 'PAUSED'\n instance.updatedAt = now\n await em.flush()\n\n return {\n status: 'WAITING',\n waitReason: 'USER_TASK',\n outputData: {\n userTaskId: userTask.id,\n },\n }\n}\n\n/**\n * Handle SUB_WORKFLOW step - invoke another workflow and wait for completion\n *\n * Creates a child workflow instance with mapped input data,\n * executes it synchronously, and returns mapped output data.\n */\nasync function handleSubWorkflowStep(\n em: EntityManager,\n container: any,\n instance: WorkflowInstance,\n stepInstance: StepInstance,\n stepDef: any,\n context: StepExecutionContext\n): Promise<StepExecutionResult> {\n const { subWorkflowId, inputMapping, outputMapping, version } = stepDef.config || {}\n\n if (!subWorkflowId) {\n return {\n status: 'FAILED',\n error: 'Sub-workflow ID not specified in step configuration'\n }\n }\n\n // Map input data from parent context to child context\n const childContext = mapInputData(instance.context, inputMapping || {})\n\n // Import workflow executor functions\n const { startWorkflow, executeWorkflow } = await import('./workflow-executor')\n\n try {\n // Start child workflow with parent metadata\n const childInstance = await startWorkflow(em, {\n workflowId: subWorkflowId,\n version,\n initialContext: childContext,\n correlationKey: instance.correlationKey || undefined,\n metadata: {\n ...instance.metadata,\n labels: {\n ...instance.metadata?.labels,\n parentInstanceId: instance.id,\n parentStepId: stepDef.stepId,\n parentStepInstanceId: stepInstance.id,\n },\n },\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n // Log sub-workflow invocation event\n await logStepEvent(em, {\n workflowInstanceId: instance.id,\n stepInstanceId: stepInstance.id,\n eventType: 'SUB_WORKFLOW_STARTED',\n eventData: {\n childInstanceId: childInstance.id,\n subWorkflowId,\n version,\n inputData: childContext,\n },\n userId: context.userId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n // Execute child workflow synchronously\n const result = await executeWorkflow(em, container, childInstance.id, {\n userId: context.userId,\n })\n\n // Handle child workflow result\n if (result.status === 'COMPLETED') {\n // Map output data from child context to parent context\n const outputData = mapOutputData(result.context, outputMapping || {})\n\n await logStepEvent(em, {\n workflowInstanceId: instance.id,\n stepInstanceId: stepInstance.id,\n eventType: 'SUB_WORKFLOW_COMPLETED',\n eventData: {\n childInstanceId: childInstance.id,\n outputData,\n },\n userId: context.userId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n return {\n status: 'COMPLETED',\n outputData,\n }\n } else if (result.status === 'FAILED') {\n await logStepEvent(em, {\n workflowInstanceId: instance.id,\n stepInstanceId: stepInstance.id,\n eventType: 'SUB_WORKFLOW_FAILED',\n eventData: {\n childInstanceId: childInstance.id,\n error: result.errors?.join(', '),\n },\n userId: context.userId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n return {\n status: 'FAILED',\n error: `Sub-workflow failed: ${result.errors?.join(', ')}`,\n }\n } else {\n // WAITING, PAUSED, etc. - For synchronous execution, treat as error\n return {\n status: 'FAILED',\n error: `Sub-workflow ended in unexpected state: ${result.status}`,\n }\n }\n } catch (error: any) {\n await logStepEvent(em, {\n workflowInstanceId: instance.id,\n stepInstanceId: stepInstance.id,\n eventType: 'SUB_WORKFLOW_FAILED',\n eventData: {\n subWorkflowId,\n error: error.message,\n },\n userId: context.userId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n return {\n status: 'FAILED',\n error: `Sub-workflow execution failed: ${error.message}`,\n }\n }\n}\n\n/**\n * Handle WAIT_FOR_SIGNAL step - pause workflow until signal received\n *\n * Creates a waiting state and pauses the workflow until an external signal\n * with the matching signal name is received. The signal payload will be merged\n * into the workflow context when received.\n */\nasync function handleWaitForSignalStep(\n em: EntityManager,\n instance: WorkflowInstance,\n stepInstance: StepInstance,\n stepDef: any,\n context: StepExecutionContext\n): Promise<StepExecutionResult> {\n const signalConfig = stepDef.signalConfig || {}\n const signalName = signalConfig.signalName || stepDef.stepId\n const timeout = signalConfig.timeout ? parseDuration(signalConfig.timeout) : null\n\n const now = new Date()\n\n // Log signal awaiting event\n await logStepEvent(em, {\n workflowInstanceId: instance.id,\n stepInstanceId: stepInstance.id,\n eventType: 'SIGNAL_AWAITING',\n eventData: {\n signalName,\n timeout,\n description: stepDef.description,\n },\n userId: context.userId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n // Pause workflow execution\n instance.status = 'PAUSED'\n instance.pausedAt = now\n instance.updatedAt = now\n await em.flush()\n\n // Return WAITING status to halt executor\n return {\n status: 'WAITING',\n waitReason: 'SIGNAL',\n outputData: {\n signalName,\n timeout,\n awaitingSince: now,\n },\n }\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Parse ISO 8601 duration to milliseconds\n *\n * Supports:\n * - ISO 8601: PT5M (5 minutes), PT1H (1 hour), P1D (1 day), P3D (3 days)\n * - Simple formats: 5m, 1h, 3d, 30s\n *\n * @param duration - Duration string\n * @returns Duration in milliseconds\n */\nfunction parseDuration(duration: string): number {\n // Try ISO 8601 format first: P[n]DT[n]H[n]M[n]S\n const iso8601Regex = /P(?:(\\d+)D)?(?:T(?:(\\d+)H)?(?:(\\d+)M)?(?:(\\d+)S)?)?/\n const iso8601Match = duration.match(iso8601Regex)\n\n if (iso8601Match && iso8601Match[0] === duration) {\n const days = parseInt(iso8601Match[1] || '0')\n const hours = parseInt(iso8601Match[2] || '0')\n const minutes = parseInt(iso8601Match[3] || '0')\n const seconds = parseInt(iso8601Match[4] || '0')\n\n return (\n days * 24 * 60 * 60 * 1000 +\n hours * 60 * 60 * 1000 +\n minutes * 60 * 1000 +\n seconds * 1000\n )\n }\n\n // Try simple format: 1d, 5h, 30m, 45s\n const simpleRegex = /^(\\d+)(d|h|m|s)$/\n const simpleMatch = duration.match(simpleRegex)\n\n if (simpleMatch) {\n const value = parseInt(simpleMatch[1])\n const unit = simpleMatch[2]\n\n switch (unit) {\n case 'd':\n return value * 24 * 60 * 60 * 1000\n case 'h':\n return value * 60 * 60 * 1000\n case 'm':\n return value * 60 * 1000\n case 's':\n return value * 1000\n }\n }\n\n throw new StepExecutionError(\n `Invalid duration format: ${duration}`,\n 'INVALID_DURATION',\n { duration }\n )\n}\n\n/**\n * Log step-related event to event sourcing table\n */\nasync function logStepEvent(\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\n/**\n * Calculate due date from ISO 8601 duration string\n *\n * @param duration - ISO 8601 duration (e.g., \"P1D\" for 1 day)\n * @returns Due date\n */\nfunction calculateDueDate(duration: string): Date {\n // Simple implementation for MVP\n // Supports: P1D (1 day), P1H (1 hour), P1W (1 week)\n const now = new Date()\n\n const daysMatch = duration.match(/P(\\d+)D/)\n if (daysMatch) {\n const days = parseInt(daysMatch[1], 10)\n return new Date(now.getTime() + days * 24 * 60 * 60 * 1000)\n }\n\n const hoursMatch = duration.match(/PT(\\d+)H/)\n if (hoursMatch) {\n const hours = parseInt(hoursMatch[1], 10)\n return new Date(now.getTime() + hours * 60 * 60 * 1000)\n }\n\n const weeksMatch = duration.match(/P(\\d+)W/)\n if (weeksMatch) {\n const weeks = parseInt(weeksMatch[1], 10)\n return new Date(now.getTime() + weeks * 7 * 24 * 60 * 60 * 1000)\n }\n\n // Default: 1 day\n return new Date(now.getTime() + 24 * 60 * 60 * 1000)\n}\n\n/**\n * Get nested value from object using dot notation\n *\n * @param obj - Source object\n * @param path - Dot-notation path (e.g., \"user.email\")\n * @returns Value at path or undefined\n */\nfunction getNestedValue(obj: any, path: string): any {\n return path.split('.').reduce((current, key) => current?.[key], obj)\n}\n\n/**\n * Set nested value in object using dot notation\n *\n * @param obj - Target object\n * @param path - Dot-notation path (e.g., \"user.email\")\n * @param value - Value to set\n */\nfunction setNestedValue(obj: any, path: string, value: any): void {\n const keys = path.split('.')\n const lastKey = keys.pop()!\n const target = keys.reduce((current, key) => {\n if (!(key in current)) current[key] = {}\n return current[key]\n }, obj)\n target[lastKey] = value\n}\n\n/**\n * Map data from source context using mapping configuration\n *\n * @param sourceContext - Source data object\n * @param mapping - Mapping configuration (targetKey -> sourcePath)\n * @returns Mapped data object\n */\nfunction mapInputData(\n sourceContext: Record<string, any>,\n mapping: Record<string, string>\n): Record<string, any> {\n const result: Record<string, any> = {}\n\n for (const [targetKey, sourcePath] of Object.entries(mapping)) {\n const value = getNestedValue(sourceContext, sourcePath)\n if (value !== undefined) {\n setNestedValue(result, targetKey, value)\n }\n }\n\n // If no mapping provided, pass entire context\n return Object.keys(result).length > 0 ? result : sourceContext\n}\n\n/**\n * Map output data from child context back to parent\n *\n * @param childContext - Child workflow context\n * @param mapping - Mapping configuration (targetKey -> sourcePath)\n * @returns Mapped output data\n */\nfunction mapOutputData(\n childContext: Record<string, any>,\n mapping: Record<string, string>\n): Record<string, any> {\n const result: Record<string, any> = {}\n\n for (const [targetKey, sourcePath] of Object.entries(mapping)) {\n const value = getNestedValue(childContext, sourcePath)\n if (value !== undefined) {\n setNestedValue(result, targetKey, value)\n }\n }\n\n // If no mapping provided, pass entire child context\n return Object.keys(result).length > 0 ? result : childContext\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -183,7 +183,7 @@ async function logWorkflowEvent(em, event) {
|
|
|
183
183
|
...event,
|
|
184
184
|
occurredAt: /* @__PURE__ */ new Date()
|
|
185
185
|
});
|
|
186
|
-
await em.
|
|
186
|
+
await em.persist(workflowEvent).flush();
|
|
187
187
|
return workflowEvent;
|
|
188
188
|
}
|
|
189
189
|
function validateFormData(formData, formSchema) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/workflows/lib/task-handler.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Workflows Module - User Task Handler Service\n *\n * Handles user task lifecycle operations:\n * - Completing user tasks\n * - Claiming tasks from role queues\n * - Reassigning tasks\n * - Escalating overdue tasks\n *\n * Functional API (no classes) following Open Mercato conventions.\n */\n\nimport { EntityManager } from '@mikro-orm/core'\nimport type { AwilixContainer } from 'awilix'\nimport {\n UserTask,\n WorkflowInstance,\n WorkflowEvent,\n StepInstance,\n WorkflowDefinition,\n} from '../data/entities'\nimport { executeWorkflow } from './workflow-executor'\nimport * as stepHandler from './step-handler'\nimport * as transitionHandler from './transition-handler'\n\n// ============================================================================\n// Types and Interfaces\n// ============================================================================\n\nexport interface CompleteUserTaskOptions {\n taskId: string\n formData: Record<string, any>\n userId: string\n comments?: string\n}\n\nexport class UserTaskError extends Error {\n constructor(\n message: string,\n public code: string,\n public details?: any\n ) {\n super(message)\n this.name = 'UserTaskError'\n }\n}\n\n// ============================================================================\n// User Task Completion\n// ============================================================================\n\n/**\n * Complete a user task and resume workflow execution\n *\n * This function:\n * 1. Validates the task exists and can be completed\n * 2. Updates the task with form data and completion info\n * 3. Merges form data into workflow context\n * 4. Logs completion event\n * 5. Resumes workflow execution\n *\n * @param em - Entity manager\n * @param container - DI container for workflow execution\n * @param options - Task completion options\n * @throws UserTaskError if task not found or validation fails\n */\nexport async function completeUserTask(\n em: EntityManager,\n container: AwilixContainer,\n options: CompleteUserTaskOptions\n): Promise<void> {\n const { taskId, formData, userId, comments } = options\n\n // Fetch task\n const task = await em.findOne(UserTask, {\n id: taskId,\n status: { $in: ['PENDING', 'IN_PROGRESS'] },\n })\n\n if (!task) {\n throw new UserTaskError(\n 'Task not found or already completed',\n 'TASK_NOT_FOUND',\n { taskId }\n )\n }\n\n // Validate form data against schema (simple validation for MVP)\n // In Phase 7, we'll add comprehensive JSON Schema validation\n if (task.formSchema) {\n try {\n validateFormData(formData, task.formSchema)\n } catch (error) {\n throw new UserTaskError(\n error instanceof Error ? error.message : 'Form validation failed',\n 'FORM_VALIDATION_FAILED',\n { taskId, formSchema: task.formSchema, formData }\n )\n }\n }\n\n // Update task\n const now = new Date()\n task.status = 'COMPLETED'\n task.formData = formData\n task.completedBy = userId\n task.completedAt = now\n task.comments = comments || null\n task.updatedAt = now\n\n await em.flush()\n\n // Fetch workflow instance\n const instance = await em.findOne(WorkflowInstance, task.workflowInstanceId)\n if (!instance) {\n throw new UserTaskError(\n 'Workflow instance not found',\n 'INSTANCE_NOT_FOUND',\n { workflowInstanceId: task.workflowInstanceId }\n )\n }\n\n // Merge form data into workflow context\n instance.context = {\n ...instance.context,\n ...formData,\n }\n instance.updatedAt = now\n\n // Log USER_TASK_COMPLETED event\n await logWorkflowEvent(em, {\n workflowInstanceId: instance.id,\n stepInstanceId: task.stepInstanceId,\n eventType: 'USER_TASK_COMPLETED',\n eventData: {\n taskId: task.id,\n taskName: task.taskName,\n completedBy: userId,\n formData,\n },\n userId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n // Mark the step instance as completed\n const stepInstance = await em.findOne(StepInstance, {\n id: task.stepInstanceId,\n status: 'ACTIVE',\n })\n\n if (stepInstance) {\n await stepHandler.exitStep(em, stepInstance, { userTaskId: task.id, formData })\n }\n\n // Find the next automatic transition from the current step\n const currentStepId = instance.currentStepId\n\n // Load workflow definition to find transitions\n const definition = await em.findOne(WorkflowDefinition, {\n id: instance.definitionId,\n })\n\n if (!definition) {\n throw new UserTaskError(\n 'Workflow definition not found',\n 'DEFINITION_NOT_FOUND',\n { definitionId: instance.definitionId }\n )\n }\n\n // Find automatic transitions from current step\n const autoTransitions = (definition.definition.transitions || []).filter(\n (t: any) => t.fromStepId === currentStepId && t.trigger === 'auto'\n )\n\n if (autoTransitions.length === 0) {\n // No automatic transitions, workflow stays paused at current step\n return\n }\n\n // Find valid transitions using transition handler\n const transitionContext = {\n workflowContext: instance.context,\n userId,\n }\n\n const validTransitions = await transitionHandler.findValidTransitions(\n em,\n instance,\n currentStepId,\n transitionContext\n )\n\n const firstValidTransition = validTransitions.find(t => t.isValid)\n\n if (!firstValidTransition || !firstValidTransition.transition) {\n // Resume workflow execution anyway, maybe conditions will be met later\n instance.status = 'RUNNING'\n await em.flush()\n return\n }\n\n // Execute the transition to move to next step\n\n const transitionResult = await transitionHandler.executeTransition(\n em,\n container,\n instance,\n currentStepId,\n firstValidTransition.transition.toStepId,\n transitionContext\n )\n\n if (!transitionResult.success) {\n console.error(`[TaskHandler] Transition failed:`, transitionResult.error)\n // Don't throw, just leave workflow in current state\n return\n }\n\n // Now continue workflow execution from the new step\n await executeWorkflow(em, container, instance.id, { userId })\n}\n\n/**\n * Claim a user task from a role queue\n *\n * Allows a user to claim a task that's assigned to their role(s).\n * Prevents race conditions by checking task status.\n *\n * @param em - Entity manager\n * @param taskId - Task ID to claim\n * @param userId - User claiming the task\n * @throws UserTaskError if task cannot be claimed\n */\nexport async function claimUserTask(\n em: EntityManager,\n taskId: string,\n userId: string\n): Promise<void> {\n const task = await em.findOne(UserTask, {\n id: taskId,\n status: 'PENDING',\n })\n\n if (!task) {\n throw new UserTaskError(\n 'Task not found or already claimed',\n 'TASK_NOT_FOUND',\n { taskId }\n )\n }\n\n if (task.assignedTo) {\n throw new UserTaskError(\n 'Task is already assigned to a specific user',\n 'TASK_ALREADY_ASSIGNED',\n { taskId, assignedTo: task.assignedTo }\n )\n }\n\n if (!task.assignedToRoles || task.assignedToRoles.length === 0) {\n throw new UserTaskError(\n 'Task is not assigned to any roles',\n 'TASK_NOT_ROLE_ASSIGNED',\n { taskId }\n )\n }\n\n // Update task\n const now = new Date()\n task.claimedBy = userId\n task.claimedAt = now\n task.status = 'IN_PROGRESS'\n task.updatedAt = now\n\n await em.flush()\n\n // Log event\n const instance = await em.findOne(WorkflowInstance, task.workflowInstanceId)\n if (instance) {\n await logWorkflowEvent(em, {\n workflowInstanceId: instance.id,\n stepInstanceId: task.stepInstanceId,\n eventType: 'USER_TASK_STARTED',\n eventData: {\n taskId: task.id,\n taskName: task.taskName,\n claimedBy: userId,\n },\n userId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n }\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Log workflow event to event sourcing table\n */\nasync function logWorkflowEvent(\n em: EntityManager,\n event: {\n workflowInstanceId: string\n stepInstanceId: string | null\n eventType: string\n eventData: any\n userId?: string\n tenantId: string\n organizationId: string\n }\n): Promise<WorkflowEvent> {\n const workflowEvent = em.create(WorkflowEvent, {\n ...event,\n occurredAt: new Date(),\n })\n\n await em.
|
|
5
|
-
"mappings": "AAcA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,uBAAuB;AAChC,YAAY,iBAAiB;AAC7B,YAAY,uBAAuB;AAa5B,MAAM,sBAAsB,MAAM;AAAA,EACvC,YACE,SACO,MACA,SACP;AACA,UAAM,OAAO;AAHN;AACA;AAGP,SAAK,OAAO;AAAA,EACd;AACF;AAqBA,eAAsB,iBACpB,IACA,WACA,SACe;AACf,QAAM,EAAE,QAAQ,UAAU,QAAQ,SAAS,IAAI;AAG/C,QAAM,OAAO,MAAM,GAAG,QAAQ,UAAU;AAAA,IACtC,IAAI;AAAA,IACJ,QAAQ,EAAE,KAAK,CAAC,WAAW,aAAa,EAAE;AAAA,EAC5C,CAAC;AAED,MAAI,CAAC,MAAM;AACT,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA,EAAE,OAAO;AAAA,IACX;AAAA,EACF;AAIA,MAAI,KAAK,YAAY;AACnB,QAAI;AACF,uBAAiB,UAAU,KAAK,UAAU;AAAA,IAC5C,SAAS,OAAO;AACd,YAAM,IAAI;AAAA,QACR,iBAAiB,QAAQ,MAAM,UAAU;AAAA,QACzC;AAAA,QACA,EAAE,QAAQ,YAAY,KAAK,YAAY,SAAS;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AAGA,QAAM,MAAM,oBAAI,KAAK;AACrB,OAAK,SAAS;AACd,OAAK,WAAW;AAChB,OAAK,cAAc;AACnB,OAAK,cAAc;AACnB,OAAK,WAAW,YAAY;AAC5B,OAAK,YAAY;AAEjB,QAAM,GAAG,MAAM;AAGf,QAAM,WAAW,MAAM,GAAG,QAAQ,kBAAkB,KAAK,kBAAkB;AAC3E,MAAI,CAAC,UAAU;AACb,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA,EAAE,oBAAoB,KAAK,mBAAmB;AAAA,IAChD;AAAA,EACF;AAGA,WAAS,UAAU;AAAA,IACjB,GAAG,SAAS;AAAA,IACZ,GAAG;AAAA,EACL;AACA,WAAS,YAAY;AAGrB,QAAM,iBAAiB,IAAI;AAAA,IACzB,oBAAoB,SAAS;AAAA,IAC7B,gBAAgB,KAAK;AAAA,IACrB,WAAW;AAAA,IACX,WAAW;AAAA,MACT,QAAQ,KAAK;AAAA,MACb,UAAU,KAAK;AAAA,MACf,aAAa;AAAA,MACb;AAAA,IACF;AAAA,IACA;AAAA,IACA,UAAU,SAAS;AAAA,IACnB,gBAAgB,SAAS;AAAA,EAC3B,CAAC;AAGD,QAAM,eAAe,MAAM,GAAG,QAAQ,cAAc;AAAA,IAClD,IAAI,KAAK;AAAA,IACT,QAAQ;AAAA,EACV,CAAC;AAED,MAAI,cAAc;AAChB,UAAM,YAAY,SAAS,IAAI,cAAc,EAAE,YAAY,KAAK,IAAI,SAAS,CAAC;AAAA,EAChF;AAGA,QAAM,gBAAgB,SAAS;AAG/B,QAAM,aAAa,MAAM,GAAG,QAAQ,oBAAoB;AAAA,IACtD,IAAI,SAAS;AAAA,EACf,CAAC;AAED,MAAI,CAAC,YAAY;AACf,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA,EAAE,cAAc,SAAS,aAAa;AAAA,IACxC;AAAA,EACF;AAGA,QAAM,mBAAmB,WAAW,WAAW,eAAe,CAAC,GAAG;AAAA,IAChE,CAAC,MAAW,EAAE,eAAe,iBAAiB,EAAE,YAAY;AAAA,EAC9D;AAEA,MAAI,gBAAgB,WAAW,GAAG;AAEhC;AAAA,EACF;AAGA,QAAM,oBAAoB;AAAA,IACxB,iBAAiB,SAAS;AAAA,IAC1B;AAAA,EACF;AAEA,QAAM,mBAAmB,MAAM,kBAAkB;AAAA,IAC/C;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,uBAAuB,iBAAiB,KAAK,OAAK,EAAE,OAAO;AAEjE,MAAI,CAAC,wBAAwB,CAAC,qBAAqB,YAAY;AAE7D,aAAS,SAAS;AAClB,UAAM,GAAG,MAAM;AACf;AAAA,EACF;AAIA,QAAM,mBAAmB,MAAM,kBAAkB;AAAA,IAC/C;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,qBAAqB,WAAW;AAAA,IAChC;AAAA,EACF;AAEA,MAAI,CAAC,iBAAiB,SAAS;AAC7B,YAAQ,MAAM,oCAAoC,iBAAiB,KAAK;AAExE;AAAA,EACF;AAGA,QAAM,gBAAgB,IAAI,WAAW,SAAS,IAAI,EAAE,OAAO,CAAC;AAC9D;AAaA,eAAsB,cACpB,IACA,QACA,QACe;AACf,QAAM,OAAO,MAAM,GAAG,QAAQ,UAAU;AAAA,IACtC,IAAI;AAAA,IACJ,QAAQ;AAAA,EACV,CAAC;AAED,MAAI,CAAC,MAAM;AACT,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA,EAAE,OAAO;AAAA,IACX;AAAA,EACF;AAEA,MAAI,KAAK,YAAY;AACnB,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA,EAAE,QAAQ,YAAY,KAAK,WAAW;AAAA,IACxC;AAAA,EACF;AAEA,MAAI,CAAC,KAAK,mBAAmB,KAAK,gBAAgB,WAAW,GAAG;AAC9D,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA,EAAE,OAAO;AAAA,IACX;AAAA,EACF;AAGA,QAAM,MAAM,oBAAI,KAAK;AACrB,OAAK,YAAY;AACjB,OAAK,YAAY;AACjB,OAAK,SAAS;AACd,OAAK,YAAY;AAEjB,QAAM,GAAG,MAAM;AAGf,QAAM,WAAW,MAAM,GAAG,QAAQ,kBAAkB,KAAK,kBAAkB;AAC3E,MAAI,UAAU;AACZ,UAAM,iBAAiB,IAAI;AAAA,MACzB,oBAAoB,SAAS;AAAA,MAC7B,gBAAgB,KAAK;AAAA,MACrB,WAAW;AAAA,MACX,WAAW;AAAA,QACT,QAAQ,KAAK;AAAA,QACb,UAAU,KAAK;AAAA,QACf,WAAW;AAAA,MACb;AAAA,MACA;AAAA,MACA,UAAU,SAAS;AAAA,MACnB,gBAAgB,SAAS;AAAA,IAC3B,CAAC;AAAA,EACH;AACF;AASA,eAAe,iBACb,IACA,OASwB;AACxB,QAAM,gBAAgB,GAAG,OAAO,eAAe;AAAA,IAC7C,GAAG;AAAA,IACH,YAAY,oBAAI,KAAK;AAAA,EACvB,CAAC;AAED,QAAM,GAAG,
|
|
4
|
+
"sourcesContent": ["/**\n * Workflows Module - User Task Handler Service\n *\n * Handles user task lifecycle operations:\n * - Completing user tasks\n * - Claiming tasks from role queues\n * - Reassigning tasks\n * - Escalating overdue tasks\n *\n * Functional API (no classes) following Open Mercato conventions.\n */\n\nimport { EntityManager } from '@mikro-orm/core'\nimport type { AwilixContainer } from 'awilix'\nimport {\n UserTask,\n WorkflowInstance,\n WorkflowEvent,\n StepInstance,\n WorkflowDefinition,\n} from '../data/entities'\nimport { executeWorkflow } from './workflow-executor'\nimport * as stepHandler from './step-handler'\nimport * as transitionHandler from './transition-handler'\n\n// ============================================================================\n// Types and Interfaces\n// ============================================================================\n\nexport interface CompleteUserTaskOptions {\n taskId: string\n formData: Record<string, any>\n userId: string\n comments?: string\n}\n\nexport class UserTaskError extends Error {\n constructor(\n message: string,\n public code: string,\n public details?: any\n ) {\n super(message)\n this.name = 'UserTaskError'\n }\n}\n\n// ============================================================================\n// User Task Completion\n// ============================================================================\n\n/**\n * Complete a user task and resume workflow execution\n *\n * This function:\n * 1. Validates the task exists and can be completed\n * 2. Updates the task with form data and completion info\n * 3. Merges form data into workflow context\n * 4. Logs completion event\n * 5. Resumes workflow execution\n *\n * @param em - Entity manager\n * @param container - DI container for workflow execution\n * @param options - Task completion options\n * @throws UserTaskError if task not found or validation fails\n */\nexport async function completeUserTask(\n em: EntityManager,\n container: AwilixContainer,\n options: CompleteUserTaskOptions\n): Promise<void> {\n const { taskId, formData, userId, comments } = options\n\n // Fetch task\n const task = await em.findOne(UserTask, {\n id: taskId,\n status: { $in: ['PENDING', 'IN_PROGRESS'] },\n })\n\n if (!task) {\n throw new UserTaskError(\n 'Task not found or already completed',\n 'TASK_NOT_FOUND',\n { taskId }\n )\n }\n\n // Validate form data against schema (simple validation for MVP)\n // In Phase 7, we'll add comprehensive JSON Schema validation\n if (task.formSchema) {\n try {\n validateFormData(formData, task.formSchema)\n } catch (error) {\n throw new UserTaskError(\n error instanceof Error ? error.message : 'Form validation failed',\n 'FORM_VALIDATION_FAILED',\n { taskId, formSchema: task.formSchema, formData }\n )\n }\n }\n\n // Update task\n const now = new Date()\n task.status = 'COMPLETED'\n task.formData = formData\n task.completedBy = userId\n task.completedAt = now\n task.comments = comments || null\n task.updatedAt = now\n\n await em.flush()\n\n // Fetch workflow instance\n const instance = await em.findOne(WorkflowInstance, task.workflowInstanceId)\n if (!instance) {\n throw new UserTaskError(\n 'Workflow instance not found',\n 'INSTANCE_NOT_FOUND',\n { workflowInstanceId: task.workflowInstanceId }\n )\n }\n\n // Merge form data into workflow context\n instance.context = {\n ...instance.context,\n ...formData,\n }\n instance.updatedAt = now\n\n // Log USER_TASK_COMPLETED event\n await logWorkflowEvent(em, {\n workflowInstanceId: instance.id,\n stepInstanceId: task.stepInstanceId,\n eventType: 'USER_TASK_COMPLETED',\n eventData: {\n taskId: task.id,\n taskName: task.taskName,\n completedBy: userId,\n formData,\n },\n userId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n\n // Mark the step instance as completed\n const stepInstance = await em.findOne(StepInstance, {\n id: task.stepInstanceId,\n status: 'ACTIVE',\n })\n\n if (stepInstance) {\n await stepHandler.exitStep(em, stepInstance, { userTaskId: task.id, formData })\n }\n\n // Find the next automatic transition from the current step\n const currentStepId = instance.currentStepId\n\n // Load workflow definition to find transitions\n const definition = await em.findOne(WorkflowDefinition, {\n id: instance.definitionId,\n })\n\n if (!definition) {\n throw new UserTaskError(\n 'Workflow definition not found',\n 'DEFINITION_NOT_FOUND',\n { definitionId: instance.definitionId }\n )\n }\n\n // Find automatic transitions from current step\n const autoTransitions = (definition.definition.transitions || []).filter(\n (t: any) => t.fromStepId === currentStepId && t.trigger === 'auto'\n )\n\n if (autoTransitions.length === 0) {\n // No automatic transitions, workflow stays paused at current step\n return\n }\n\n // Find valid transitions using transition handler\n const transitionContext = {\n workflowContext: instance.context,\n userId,\n }\n\n const validTransitions = await transitionHandler.findValidTransitions(\n em,\n instance,\n currentStepId,\n transitionContext\n )\n\n const firstValidTransition = validTransitions.find(t => t.isValid)\n\n if (!firstValidTransition || !firstValidTransition.transition) {\n // Resume workflow execution anyway, maybe conditions will be met later\n instance.status = 'RUNNING'\n await em.flush()\n return\n }\n\n // Execute the transition to move to next step\n\n const transitionResult = await transitionHandler.executeTransition(\n em,\n container,\n instance,\n currentStepId,\n firstValidTransition.transition.toStepId,\n transitionContext\n )\n\n if (!transitionResult.success) {\n console.error(`[TaskHandler] Transition failed:`, transitionResult.error)\n // Don't throw, just leave workflow in current state\n return\n }\n\n // Now continue workflow execution from the new step\n await executeWorkflow(em, container, instance.id, { userId })\n}\n\n/**\n * Claim a user task from a role queue\n *\n * Allows a user to claim a task that's assigned to their role(s).\n * Prevents race conditions by checking task status.\n *\n * @param em - Entity manager\n * @param taskId - Task ID to claim\n * @param userId - User claiming the task\n * @throws UserTaskError if task cannot be claimed\n */\nexport async function claimUserTask(\n em: EntityManager,\n taskId: string,\n userId: string\n): Promise<void> {\n const task = await em.findOne(UserTask, {\n id: taskId,\n status: 'PENDING',\n })\n\n if (!task) {\n throw new UserTaskError(\n 'Task not found or already claimed',\n 'TASK_NOT_FOUND',\n { taskId }\n )\n }\n\n if (task.assignedTo) {\n throw new UserTaskError(\n 'Task is already assigned to a specific user',\n 'TASK_ALREADY_ASSIGNED',\n { taskId, assignedTo: task.assignedTo }\n )\n }\n\n if (!task.assignedToRoles || task.assignedToRoles.length === 0) {\n throw new UserTaskError(\n 'Task is not assigned to any roles',\n 'TASK_NOT_ROLE_ASSIGNED',\n { taskId }\n )\n }\n\n // Update task\n const now = new Date()\n task.claimedBy = userId\n task.claimedAt = now\n task.status = 'IN_PROGRESS'\n task.updatedAt = now\n\n await em.flush()\n\n // Log event\n const instance = await em.findOne(WorkflowInstance, task.workflowInstanceId)\n if (instance) {\n await logWorkflowEvent(em, {\n workflowInstanceId: instance.id,\n stepInstanceId: task.stepInstanceId,\n eventType: 'USER_TASK_STARTED',\n eventData: {\n taskId: task.id,\n taskName: task.taskName,\n claimedBy: userId,\n },\n userId,\n tenantId: instance.tenantId,\n organizationId: instance.organizationId,\n })\n }\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Log workflow event to event sourcing table\n */\nasync function logWorkflowEvent(\n em: EntityManager,\n event: {\n workflowInstanceId: string\n stepInstanceId: string | null\n eventType: string\n eventData: any\n userId?: string\n tenantId: string\n organizationId: string\n }\n): Promise<WorkflowEvent> {\n const workflowEvent = em.create(WorkflowEvent, {\n ...event,\n occurredAt: new Date(),\n })\n\n await em.persist(workflowEvent).flush()\n return workflowEvent\n}\n\n/**\n * Validate form data against JSON schema (basic validation for MVP)\n *\n * In Phase 7, we'll implement comprehensive JSON Schema validation.\n * For MVP, we do basic type checking.\n *\n * @param formData - User-provided form data\n * @param formSchema - JSON schema defining expected structure\n * @throws Error if validation fails\n */\nfunction validateFormData(\n formData: Record<string, any>,\n formSchema: any\n): void {\n // For MVP: Basic validation - just check required fields exist\n if (!formSchema || !formSchema.properties) {\n return // No schema to validate against\n }\n\n const requiredFields = formSchema.required || []\n\n for (const field of requiredFields) {\n if (!(field in formData) || formData[field] === null || formData[field] === undefined) {\n throw new Error(`Required field missing: ${field}`)\n }\n }\n\n // Additional type validation can be added in Phase 7\n // For now, this basic validation is sufficient\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|