@open-mercato/core 0.6.6-develop.6465.1.019f0fb26f → 0.6.6-develop.6471.1.9ab5bdd79a
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/bootstrap.js +13 -11
- package/dist/bootstrap.js.map +2 -2
- package/dist/helpers/integration/queue-runner.js +4 -2
- package/dist/helpers/integration/queue-runner.js.map +2 -2
- package/dist/modules/api_keys/services/apiKeyService.js +5 -3
- package/dist/modules/api_keys/services/apiKeyService.js.map +2 -2
- package/dist/modules/attachments/api/image/[id]/[[...slug]]/route.js +4 -2
- package/dist/modules/attachments/api/image/[id]/[[...slug]]/route.js.map +2 -2
- package/dist/modules/attachments/api/library/[id]/route.js +3 -1
- package/dist/modules/attachments/api/library/[id]/route.js.map +2 -2
- package/dist/modules/attachments/api/route.js +8 -6
- package/dist/modules/attachments/api/route.js.map +2 -2
- package/dist/modules/attachments/components/AttachmentPartitionSettings.js +5 -3
- package/dist/modules/attachments/components/AttachmentPartitionSettings.js.map +2 -2
- package/dist/modules/attachments/lib/assignmentDetails.js +3 -1
- package/dist/modules/attachments/lib/assignmentDetails.js.map +2 -2
- package/dist/modules/attachments/lib/drivers/driverFactory.js +3 -1
- package/dist/modules/attachments/lib/drivers/driverFactory.js.map +2 -2
- package/dist/modules/attachments/lib/ocrQueue.js +10 -11
- package/dist/modules/attachments/lib/ocrQueue.js.map +2 -2
- package/dist/modules/attachments/lib/ocrService.js +6 -4
- package/dist/modules/attachments/lib/ocrService.js.map +2 -2
- package/dist/modules/audit_logs/api/audit-logs/actions/redo/route.js +3 -1
- package/dist/modules/audit_logs/api/audit-logs/actions/redo/route.js.map +2 -2
- package/dist/modules/audit_logs/api/audit-logs/actions/undo/route.js +3 -1
- package/dist/modules/audit_logs/api/audit-logs/actions/undo/route.js.map +2 -2
- package/dist/modules/audit_logs/backend/audit-logs/page.js +3 -1
- package/dist/modules/audit_logs/backend/audit-logs/page.js.map +2 -2
- package/dist/modules/audit_logs/components/AuditLogsActions.js +4 -2
- package/dist/modules/audit_logs/components/AuditLogsActions.js.map +2 -2
- package/dist/modules/audit_logs/services/accessLogService.js +4 -2
- package/dist/modules/audit_logs/services/accessLogService.js.map +2 -2
- package/dist/modules/audit_logs/services/actionLogService.js +7 -5
- package/dist/modules/audit_logs/services/actionLogService.js.map +3 -3
- package/dist/modules/auth/api/profile/route.js +4 -2
- package/dist/modules/auth/api/profile/route.js.map +2 -2
- package/dist/modules/auth/api/reset/confirm.js +3 -1
- package/dist/modules/auth/api/reset/confirm.js.map +2 -2
- package/dist/modules/auth/api/reset.js +4 -2
- package/dist/modules/auth/api/reset.js.map +2 -2
- package/dist/modules/auth/api/roles/route.js +3 -1
- package/dist/modules/auth/api/roles/route.js.map +2 -2
- package/dist/modules/auth/api/sidebar/variants/route.js +3 -1
- package/dist/modules/auth/api/sidebar/variants/route.js.map +2 -2
- package/dist/modules/auth/api/users/resend-invite/route.js +4 -2
- package/dist/modules/auth/api/users/resend-invite/route.js.map +2 -2
- package/dist/modules/auth/api/users/route.js +3 -1
- package/dist/modules/auth/api/users/route.js.map +2 -2
- package/dist/modules/auth/backend/auth/profile/page.js +3 -1
- package/dist/modules/auth/backend/auth/profile/page.js.map +2 -2
- package/dist/modules/auth/backend/profile/change-password/page.js +3 -1
- package/dist/modules/auth/backend/profile/change-password/page.js.map +2 -2
- package/dist/modules/auth/backend/users/[id]/edit/page.js +5 -3
- package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
- package/dist/modules/auth/backend/users/create/page.js +4 -2
- package/dist/modules/auth/backend/users/create/page.js.map +2 -2
- package/dist/modules/auth/cli.js +10 -0
- package/dist/modules/auth/cli.js.map +2 -2
- package/dist/modules/auth/commands/users.js +4 -2
- package/dist/modules/auth/commands/users.js.map +2 -2
- package/dist/modules/auth/lib/consentIntegrity.js +3 -3
- package/dist/modules/auth/lib/consentIntegrity.js.map +2 -2
- package/dist/modules/auth/lib/setup-app.js +9 -10
- package/dist/modules/auth/lib/setup-app.js.map +2 -2
- package/dist/modules/auth/lib/tenantAccess.js +3 -1
- package/dist/modules/auth/lib/tenantAccess.js.map +2 -2
- package/dist/modules/auth/lib/tokenHash.js +3 -3
- package/dist/modules/auth/lib/tokenHash.js.map +2 -2
- package/dist/modules/business_rules/api/rules/route.js +4 -2
- package/dist/modules/business_rules/api/rules/route.js.map +2 -2
- package/dist/modules/business_rules/lib/expression-evaluator.js +7 -5
- package/dist/modules/business_rules/lib/expression-evaluator.js.map +2 -2
- package/dist/modules/business_rules/lib/rule-engine.js +5 -3
- package/dist/modules/business_rules/lib/rule-engine.js.map +2 -2
- package/dist/modules/business_rules/lib/rule-evaluator.js +11 -12
- package/dist/modules/business_rules/lib/rule-evaluator.js.map +2 -2
- package/dist/modules/business_rules/subscribers/crud-rule-trigger.js +3 -1
- package/dist/modules/business_rules/subscribers/crud-rule-trigger.js.map +2 -2
- package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js +3 -1
- package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js.map +2 -2
- package/dist/modules/catalog/ai-agents-context.js +4 -5
- package/dist/modules/catalog/ai-agents-context.js.map +2 -2
- package/dist/modules/catalog/ai-tools/_shared.js +3 -1
- package/dist/modules/catalog/ai-tools/_shared.js.map +2 -2
- package/dist/modules/catalog/ai-tools/authoring-pack.js +3 -1
- package/dist/modules/catalog/ai-tools/authoring-pack.js.map +2 -2
- package/dist/modules/catalog/ai-tools/merchandising-pack.js +3 -1
- package/dist/modules/catalog/ai-tools/merchandising-pack.js.map +2 -2
- package/dist/modules/catalog/api/dictionaries/[key]/route.js +3 -1
- package/dist/modules/catalog/api/dictionaries/[key]/route.js.map +2 -2
- package/dist/modules/catalog/api/prices/route.js +3 -1
- package/dist/modules/catalog/api/prices/route.js.map +2 -2
- package/dist/modules/catalog/api/products/route.js +5 -3
- package/dist/modules/catalog/api/products/route.js.map +2 -2
- package/dist/modules/catalog/api/settings/route.js +4 -2
- package/dist/modules/catalog/api/settings/route.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/[id]/page.js +14 -12
- package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js +8 -6
- package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/[productId]/variants/create/page.js +5 -3
- package/dist/modules/catalog/backend/catalog/products/[productId]/variants/create/page.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/create/page.js +5 -6
- package/dist/modules/catalog/backend/catalog/products/create/page.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/optionSchemaClient.js +3 -1
- package/dist/modules/catalog/backend/catalog/products/optionSchemaClient.js.map +2 -2
- package/dist/modules/catalog/components/PriceKindSettings.js +5 -3
- package/dist/modules/catalog/components/PriceKindSettings.js.map +2 -2
- package/dist/modules/catalog/components/UnitPriceDisplaySettings.js +4 -2
- package/dist/modules/catalog/components/UnitPriceDisplaySettings.js.map +2 -2
- package/dist/modules/catalog/inbox-actions.js +4 -2
- package/dist/modules/catalog/inbox-actions.js.map +2 -2
- package/dist/modules/catalog/seed/examples.js +4 -5
- package/dist/modules/catalog/seed/examples.js.map +2 -2
- package/dist/modules/catalog/subscribers/low-stock-notification.js +3 -1
- package/dist/modules/catalog/subscribers/low-stock-notification.js.map +2 -2
- package/dist/modules/catalog/widgets/injection/product-seo/state.js +3 -1
- package/dist/modules/catalog/widgets/injection/product-seo/state.js.map +2 -2
- package/dist/modules/communication_channels/api/get/oauth/[provider]/callback/route.js +12 -11
- package/dist/modules/communication_channels/api/get/oauth/[provider]/callback/route.js.map +2 -2
- package/dist/modules/communication_channels/api/post/channels/[id]/import-history/route.js +3 -1
- package/dist/modules/communication_channels/api/post/channels/[id]/import-history/route.js.map +2 -2
- package/dist/modules/communication_channels/api/post/channels/[id]/push/register/route.js +3 -1
- package/dist/modules/communication_channels/api/post/channels/[id]/push/register/route.js.map +2 -2
- package/dist/modules/communication_channels/api/post/webhook/[provider]/route.js +5 -3
- package/dist/modules/communication_channels/api/post/webhook/[provider]/route.js.map +2 -2
- package/dist/modules/communication_channels/api/post/webhooks/gmail/route.js +6 -6
- package/dist/modules/communication_channels/api/post/webhooks/gmail/route.js.map +2 -2
- package/dist/modules/communication_channels/commands/connect-credential-channel.js +4 -6
- package/dist/modules/communication_channels/commands/connect-credential-channel.js.map +2 -2
- package/dist/modules/communication_channels/commands/delete-channel.js +3 -3
- package/dist/modules/communication_channels/commands/delete-channel.js.map +2 -2
- package/dist/modules/communication_channels/commands/deliver-outbound-message.js +4 -5
- package/dist/modules/communication_channels/commands/deliver-outbound-message.js.map +2 -2
- package/dist/modules/communication_channels/commands/disconnect-channel.js +3 -3
- package/dist/modules/communication_channels/commands/disconnect-channel.js.map +2 -2
- package/dist/modules/communication_channels/commands/ingest-inbound-message.js +5 -12
- package/dist/modules/communication_channels/commands/ingest-inbound-message.js.map +2 -2
- package/dist/modules/communication_channels/commands/push-unregister.js +3 -3
- package/dist/modules/communication_channels/commands/push-unregister.js.map +2 -2
- package/dist/modules/communication_channels/commands/reassign-conversation.js +5 -3
- package/dist/modules/communication_channels/commands/reassign-conversation.js.map +2 -2
- package/dist/modules/communication_channels/lib/dead-letter.js +3 -3
- package/dist/modules/communication_channels/lib/dead-letter.js.map +2 -2
- package/dist/modules/communication_channels/lib/email-mime.js +4 -6
- package/dist/modules/communication_channels/lib/email-mime.js.map +2 -2
- package/dist/modules/communication_channels/lib/oauth-client-config.js +5 -3
- package/dist/modules/communication_channels/lib/oauth-client-config.js.map +2 -2
- package/dist/modules/communication_channels/lib/send-as-user.js +3 -1
- package/dist/modules/communication_channels/lib/send-as-user.js.map +2 -2
- package/dist/modules/communication_channels/lib/thread-token.js +4 -2
- package/dist/modules/communication_channels/lib/thread-token.js.map +2 -2
- package/dist/modules/communication_channels/setup.js +3 -4
- package/dist/modules/communication_channels/setup.js.map +2 -2
- package/dist/modules/communication_channels/workers/channel-import-history.js +4 -6
- package/dist/modules/communication_channels/workers/channel-import-history.js.map +2 -2
- package/dist/modules/communication_channels/workers/gmail-history-sync.js +8 -16
- package/dist/modules/communication_channels/workers/gmail-history-sync.js.map +2 -2
- package/dist/modules/communication_channels/workers/gmail-renew-watch.js +5 -7
- package/dist/modules/communication_channels/workers/gmail-renew-watch.js.map +2 -2
- package/dist/modules/communication_channels/workers/outbound-delivery.js +6 -12
- package/dist/modules/communication_channels/workers/outbound-delivery.js.map +2 -2
- package/dist/modules/communication_channels/workers/poll-channel.js +7 -15
- package/dist/modules/communication_channels/workers/poll-channel.js.map +2 -2
- package/dist/modules/communication_channels/workers/poll-tick.js +5 -6
- package/dist/modules/communication_channels/workers/poll-tick.js.map +2 -2
- package/dist/modules/communication_channels/workers/reaction-processor.js +5 -9
- package/dist/modules/communication_channels/workers/reaction-processor.js.map +2 -2
- package/dist/modules/configs/api/cache/route.js +4 -2
- package/dist/modules/configs/api/cache/route.js.map +2 -2
- package/dist/modules/configs/api/system-status/route.js +4 -2
- package/dist/modules/configs/api/system-status/route.js.map +2 -2
- package/dist/modules/configs/api/upgrade-actions/route.js +4 -2
- package/dist/modules/configs/api/upgrade-actions/route.js.map +2 -2
- package/dist/modules/configs/components/ModuleTelemetryPanel.js +3 -1
- package/dist/modules/configs/components/ModuleTelemetryPanel.js.map +2 -2
- package/dist/modules/configs/lib/touchGeneratedBarrels.js +2 -1
- package/dist/modules/configs/lib/touchGeneratedBarrels.js.map +2 -2
- package/dist/modules/configs/services/upgradeActionsService.js +6 -3
- package/dist/modules/configs/services/upgradeActionsService.js.map +2 -2
- package/dist/modules/currencies/components/CurrencyFetchingConfig.js +3 -1
- package/dist/modules/currencies/components/CurrencyFetchingConfig.js.map +2 -2
- package/dist/modules/currencies/lib/exchangeRateFormConfig.js +3 -1
- package/dist/modules/currencies/lib/exchangeRateFormConfig.js.map +2 -2
- package/dist/modules/currencies/services/providers/nbp.js +6 -4
- package/dist/modules/currencies/services/providers/nbp.js.map +2 -2
- package/dist/modules/currencies/services/providers/raiffeisen.js +7 -7
- package/dist/modules/currencies/services/providers/raiffeisen.js.map +2 -2
- package/dist/modules/customer_accounts/api/domain-resolve/all.js +6 -5
- package/dist/modules/customer_accounts/api/domain-resolve/all.js.map +2 -2
- package/dist/modules/customer_accounts/api/signup.js +4 -2
- package/dist/modules/customer_accounts/api/signup.js.map +2 -2
- package/dist/modules/customer_accounts/lib/customerAuthServer.js +3 -1
- package/dist/modules/customer_accounts/lib/customerAuthServer.js.map +2 -2
- package/dist/modules/customer_accounts/subscribers/autoLinkCrm.js +3 -1
- package/dist/modules/customer_accounts/subscribers/autoLinkCrm.js.map +2 -2
- package/dist/modules/customer_accounts/subscribers/autoLinkCrmReverse.js +3 -1
- package/dist/modules/customer_accounts/subscribers/autoLinkCrmReverse.js.map +2 -2
- package/dist/modules/customer_accounts/subscribers/unlinkOnCompanyDelete.js +3 -1
- package/dist/modules/customer_accounts/subscribers/unlinkOnCompanyDelete.js.map +2 -2
- package/dist/modules/customer_accounts/subscribers/unlinkOnPersonDelete.js +3 -1
- package/dist/modules/customer_accounts/subscribers/unlinkOnPersonDelete.js.map +2 -2
- package/dist/modules/customers/ai-agents-context.js +4 -5
- package/dist/modules/customers/ai-agents-context.js.map +2 -2
- package/dist/modules/customers/api/activities/route.js +6 -4
- package/dist/modules/customers/api/activities/route.js.map +2 -2
- package/dist/modules/customers/api/comments/route.js +3 -1
- package/dist/modules/customers/api/comments/route.js.map +2 -2
- package/dist/modules/customers/api/companies/[id]/people/route.js +3 -1
- package/dist/modules/customers/api/companies/[id]/people/route.js.map +2 -2
- package/dist/modules/customers/api/companies/[id]/route.js +5 -3
- package/dist/modules/customers/api/companies/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/companies/route.js +5 -3
- package/dist/modules/customers/api/companies/route.js.map +2 -2
- package/dist/modules/customers/api/dashboard/widgets/customer-todos/route.js +3 -1
- package/dist/modules/customers/api/dashboard/widgets/customer-todos/route.js.map +2 -2
- package/dist/modules/customers/api/dashboard/widgets/new-customers/route.js +3 -1
- package/dist/modules/customers/api/dashboard/widgets/new-customers/route.js.map +2 -2
- package/dist/modules/customers/api/dashboard/widgets/new-deals/route.js +3 -1
- package/dist/modules/customers/api/dashboard/widgets/new-deals/route.js.map +2 -2
- package/dist/modules/customers/api/dashboard/widgets/next-interactions/route.js +3 -1
- package/dist/modules/customers/api/dashboard/widgets/next-interactions/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/companies/route.js +3 -1
- package/dist/modules/customers/api/deals/[id]/companies/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/people/route.js +3 -1
- package/dist/modules/customers/api/deals/[id]/people/route.js.map +2 -2
- package/dist/modules/customers/api/deals/aggregate/route.js +3 -1
- package/dist/modules/customers/api/deals/aggregate/route.js.map +2 -2
- package/dist/modules/customers/api/deals/bulk-update-owner/route.js +7 -5
- package/dist/modules/customers/api/deals/bulk-update-owner/route.js.map +2 -2
- package/dist/modules/customers/api/deals/bulk-update-stage/route.js +7 -5
- package/dist/modules/customers/api/deals/bulk-update-stage/route.js.map +2 -2
- package/dist/modules/customers/api/deals/route.js +3 -1
- package/dist/modules/customers/api/deals/route.js.map +2 -2
- package/dist/modules/customers/api/deals/summary/route.js +3 -1
- package/dist/modules/customers/api/deals/summary/route.js.map +2 -2
- package/dist/modules/customers/api/dictionaries/[kind]/[id]/route.js +4 -2
- package/dist/modules/customers/api/dictionaries/[kind]/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/dictionaries/[kind]/route.js +5 -3
- package/dist/modules/customers/api/dictionaries/[kind]/route.js.map +2 -2
- package/dist/modules/customers/api/dictionaries/cache.js +3 -1
- package/dist/modules/customers/api/dictionaries/cache.js.map +2 -2
- package/dist/modules/customers/api/dictionaries/context.js +3 -1
- package/dist/modules/customers/api/dictionaries/context.js.map +2 -2
- package/dist/modules/customers/api/dictionaries/currency/route.js +3 -1
- package/dist/modules/customers/api/dictionaries/currency/route.js.map +2 -2
- package/dist/modules/customers/api/dictionaries/kind-settings/route.js +4 -2
- package/dist/modules/customers/api/dictionaries/kind-settings/route.js.map +2 -2
- package/dist/modules/customers/api/entity-roles-factory.js +7 -5
- package/dist/modules/customers/api/entity-roles-factory.js.map +2 -2
- package/dist/modules/customers/api/interactions/cancel/route.js +3 -1
- package/dist/modules/customers/api/interactions/cancel/route.js.map +2 -2
- package/dist/modules/customers/api/interactions/complete/route.js +3 -1
- package/dist/modules/customers/api/interactions/complete/route.js.map +2 -2
- package/dist/modules/customers/api/interactions/conflicts/route.js +3 -1
- package/dist/modules/customers/api/interactions/conflicts/route.js.map +2 -2
- package/dist/modules/customers/api/interactions/counts/route.js +3 -1
- package/dist/modules/customers/api/interactions/counts/route.js.map +2 -2
- package/dist/modules/customers/api/interactions/route.js +7 -4
- package/dist/modules/customers/api/interactions/route.js.map +2 -2
- package/dist/modules/customers/api/interactions/tasks/route.js +3 -1
- package/dist/modules/customers/api/interactions/tasks/route.js.map +2 -2
- package/dist/modules/customers/api/labels/assign/route.js +3 -1
- package/dist/modules/customers/api/labels/assign/route.js.map +2 -2
- package/dist/modules/customers/api/labels/route.js +6 -3
- package/dist/modules/customers/api/labels/route.js.map +2 -2
- package/dist/modules/customers/api/labels/unassign/route.js +3 -1
- package/dist/modules/customers/api/labels/unassign/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/enriched/route.js +3 -1
- package/dist/modules/customers/api/people/[id]/companies/enriched/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/route.js +5 -3
- package/dist/modules/customers/api/people/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/people/route.js +5 -3
- package/dist/modules/customers/api/people/route.js.map +2 -2
- package/dist/modules/customers/api/pipeline-stages/reorder/route.js +3 -1
- package/dist/modules/customers/api/pipeline-stages/reorder/route.js.map +2 -2
- package/dist/modules/customers/api/pipeline-stages/route.js +6 -4
- package/dist/modules/customers/api/pipeline-stages/route.js.map +2 -2
- package/dist/modules/customers/api/pipelines/route.js +6 -4
- package/dist/modules/customers/api/pipelines/route.js.map +2 -2
- package/dist/modules/customers/api/settings/address-format/route.js +4 -2
- package/dist/modules/customers/api/settings/address-format/route.js.map +2 -2
- package/dist/modules/customers/api/settings/dictionary-sort-modes/route.js +4 -2
- package/dist/modules/customers/api/settings/dictionary-sort-modes/route.js.map +2 -2
- package/dist/modules/customers/api/settings/stuck-threshold/route.js +4 -2
- package/dist/modules/customers/api/settings/stuck-threshold/route.js.map +2 -2
- package/dist/modules/customers/api/tags/assign/route.js +3 -1
- package/dist/modules/customers/api/tags/assign/route.js.map +2 -2
- package/dist/modules/customers/api/tags/unassign/route.js +3 -1
- package/dist/modules/customers/api/tags/unassign/route.js.map +2 -2
- package/dist/modules/customers/api/todos/route.js +6 -4
- package/dist/modules/customers/api/todos/route.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +5 -3
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealActivities.js +3 -1
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealActivities.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealClosure.js +3 -1
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealClosure.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/map/components/DealsMapCanvasImpl.js +4 -2
- package/dist/modules/customers/backend/customers/deals/map/components/DealsMapCanvasImpl.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/page.js +4 -2
- package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +5 -3
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/commands/deals.js +3 -1
- package/dist/modules/customers/commands/deals.js.map +2 -2
- package/dist/modules/customers/commands/dictionaries.js +3 -1
- package/dist/modules/customers/commands/dictionaries.js.map +2 -2
- package/dist/modules/customers/commands/interactions.js +4 -2
- package/dist/modules/customers/commands/interactions.js.map +2 -2
- package/dist/modules/customers/commands/shared.js +4 -2
- package/dist/modules/customers/commands/shared.js.map +2 -2
- package/dist/modules/customers/commands/todos.js +3 -1
- package/dist/modules/customers/commands/todos.js.map +2 -2
- package/dist/modules/customers/components/DictionarySettings.js +5 -3
- package/dist/modules/customers/components/DictionarySettings.js.map +2 -2
- package/dist/modules/customers/components/DictionarySortSettings.js +3 -1
- package/dist/modules/customers/components/DictionarySortSettings.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivitiesCard.js +3 -1
- package/dist/modules/customers/components/detail/ActivitiesCard.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivitiesDayStrip.js +3 -1
- package/dist/modules/customers/components/detail/ActivitiesDayStrip.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivitiesSection.js +6 -4
- package/dist/modules/customers/components/detail/ActivitiesSection.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivityCard.js +3 -1
- package/dist/modules/customers/components/detail/ActivityCard.js.map +2 -2
- package/dist/modules/customers/components/detail/ChangelogTab.js +3 -1
- package/dist/modules/customers/components/detail/ChangelogTab.js.map +2 -2
- package/dist/modules/customers/components/detail/CompanyCard.js +3 -1
- package/dist/modules/customers/components/detail/CompanyCard.js.map +2 -2
- package/dist/modules/customers/components/detail/ConfirmDealLostDialog.js +3 -1
- package/dist/modules/customers/components/detail/ConfirmDealLostDialog.js.map +2 -2
- package/dist/modules/customers/components/detail/EntityTagsDialog.js +3 -1
- package/dist/modules/customers/components/detail/EntityTagsDialog.js.map +2 -2
- package/dist/modules/customers/components/detail/InlineActivityComposer.js +3 -1
- package/dist/modules/customers/components/detail/InlineActivityComposer.js.map +2 -2
- package/dist/modules/customers/components/detail/ManageTagsDialog.js +3 -1
- package/dist/modules/customers/components/detail/ManageTagsDialog.js.map +2 -2
- package/dist/modules/customers/components/detail/RoleAssignmentRow.js +5 -3
- package/dist/modules/customers/components/detail/RoleAssignmentRow.js.map +2 -2
- package/dist/modules/customers/components/detail/RolesSection.js +4 -2
- package/dist/modules/customers/components/detail/RolesSection.js.map +2 -2
- package/dist/modules/customers/components/detail/hooks/useInteractionMutations.js +5 -3
- package/dist/modules/customers/components/detail/hooks/useInteractionMutations.js.map +2 -2
- package/dist/modules/customers/components/linking/LinkEntityDialog.js +4 -2
- package/dist/modules/customers/components/linking/LinkEntityDialog.js.map +2 -2
- package/dist/modules/customers/inbox-actions.js +3 -1
- package/dist/modules/customers/inbox-actions.js.map +2 -2
- package/dist/modules/customers/lib/bulkDeals.js +3 -1
- package/dist/modules/customers/lib/bulkDeals.js.map +2 -2
- package/dist/modules/customers/lib/dealClosureNotification.js +4 -2
- package/dist/modules/customers/lib/dealClosureNotification.js.map +2 -2
- package/dist/modules/customers/lib/dealStageTransitionTable.js +3 -1
- package/dist/modules/customers/lib/dealStageTransitionTable.js.map +2 -2
- package/dist/modules/customers/lib/interactionFeatureFlags.js +3 -1
- package/dist/modules/customers/lib/interactionFeatureFlags.js.map +2 -2
- package/dist/modules/customers/lib/todoCompatibility.js +3 -1
- package/dist/modules/customers/lib/todoCompatibility.js.map +2 -2
- package/dist/modules/customers/search.js +14 -7
- package/dist/modules/customers/search.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/customer-todos/widget.client.js +3 -1
- package/dist/modules/customers/widgets/dashboard/customer-todos/widget.client.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/new-customers/widget.client.js +3 -1
- package/dist/modules/customers/widgets/dashboard/new-customers/widget.client.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/new-deals/widget.client.js +3 -1
- package/dist/modules/customers/widgets/dashboard/new-deals/widget.client.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/next-interactions/widget.client.js +3 -1
- package/dist/modules/customers/widgets/dashboard/next-interactions/widget.client.js.map +2 -2
- package/dist/modules/dashboards/api/widgets/data/batch/route.js +3 -1
- package/dist/modules/dashboards/api/widgets/data/batch/route.js.map +2 -2
- package/dist/modules/dashboards/api/widgets/data/route.js +3 -1
- package/dist/modules/dashboards/api/widgets/data/route.js.map +2 -2
- package/dist/modules/dashboards/components/WidgetVisibilityEditor.js +5 -3
- package/dist/modules/dashboards/components/WidgetVisibilityEditor.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.client.js +3 -1
- package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.client.js +3 -1
- package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.client.js +3 -1
- package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/orders-kpi/widget.client.js +3 -1
- package/dist/modules/dashboards/widgets/dashboard/orders-kpi/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.client.js +3 -1
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.client.js +3 -1
- package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.js +3 -1
- package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.js +3 -1
- package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.client.js +3 -1
- package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/top-products/widget.client.js +3 -1
- package/dist/modules/dashboards/widgets/dashboard/top-products/widget.client.js.map +2 -2
- package/dist/modules/data_sync/api/run.js +3 -1
- package/dist/modules/data_sync/api/run.js.map +2 -2
- package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js +1 -1
- package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js.map +2 -2
- package/dist/modules/data_sync/lib/adapter-registry.js +11 -4
- package/dist/modules/data_sync/lib/adapter-registry.js.map +2 -2
- package/dist/modules/data_sync/lib/sync-engine.js +23 -2
- package/dist/modules/data_sync/lib/sync-engine.js.map +2 -2
- package/dist/modules/data_sync/workers/sync-export.js +3 -1
- package/dist/modules/data_sync/workers/sync-export.js.map +2 -2
- package/dist/modules/data_sync/workers/sync-import.js +3 -1
- package/dist/modules/data_sync/workers/sync-import.js.map +2 -2
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js +4 -2
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js.map +2 -2
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/reorder/route.js +3 -1
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/reorder/route.js.map +2 -2
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/route.js +4 -2
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/route.js.map +2 -2
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/set-default/route.js +3 -1
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/set-default/route.js.map +2 -2
- package/dist/modules/dictionaries/api/[dictionaryId]/route.js +5 -3
- package/dist/modules/dictionaries/api/[dictionaryId]/route.js.map +2 -2
- package/dist/modules/dictionaries/api/context.js +3 -1
- package/dist/modules/dictionaries/api/context.js.map +2 -2
- package/dist/modules/dictionaries/api/route.js +4 -2
- package/dist/modules/dictionaries/api/route.js.map +2 -2
- package/dist/modules/dictionaries/components/DictionariesManager.js +5 -3
- package/dist/modules/dictionaries/components/DictionariesManager.js.map +2 -2
- package/dist/modules/dictionaries/components/DictionaryEntriesEditor.js +4 -2
- package/dist/modules/dictionaries/components/DictionaryEntriesEditor.js.map +2 -2
- package/dist/modules/dictionaries/components/DictionaryEntrySelect.js +4 -2
- package/dist/modules/dictionaries/components/DictionaryEntrySelect.js.map +2 -2
- package/dist/modules/dictionaries/components/DictionarySelectControl.js +3 -1
- package/dist/modules/dictionaries/components/DictionarySelectControl.js.map +2 -2
- package/dist/modules/dictionaries/fields/dictionary.js +3 -1
- package/dist/modules/dictionaries/fields/dictionary.js.map +2 -2
- package/dist/modules/directory/api/organization-branding/route.js +3 -1
- package/dist/modules/directory/api/organization-branding/route.js.map +2 -2
- package/dist/modules/directory/api/organization-switcher/route.js +3 -1
- package/dist/modules/directory/api/organization-switcher/route.js.map +2 -2
- package/dist/modules/directory/commands/tenants.js +5 -3
- package/dist/modules/directory/commands/tenants.js.map +2 -2
- package/dist/modules/directory/utils/organizationScope.js +6 -4
- package/dist/modules/directory/utils/organizationScope.js.map +2 -2
- package/dist/modules/entities/api/definitions.cache.js +3 -1
- package/dist/modules/entities/api/definitions.cache.js.map +2 -2
- package/dist/modules/entities/api/definitions.js +7 -5
- package/dist/modules/entities/api/definitions.js.map +2 -2
- package/dist/modules/entities/api/records.js +4 -8
- package/dist/modules/entities/api/records.js.map +2 -2
- package/dist/modules/entities/components/EncryptionManager.js +3 -1
- package/dist/modules/entities/components/EncryptionManager.js.map +2 -2
- package/dist/modules/entities/lib/makeActivityRoute.js +3 -1
- package/dist/modules/entities/lib/makeActivityRoute.js.map +2 -2
- package/dist/modules/feature_toggles/api/overrides/route.js +3 -1
- package/dist/modules/feature_toggles/api/overrides/route.js.map +2 -2
- package/dist/modules/feature_toggles/lib/feature-flag-check.js +5 -9
- package/dist/modules/feature_toggles/lib/feature-flag-check.js.map +2 -2
- package/dist/modules/inbox_ops/api/emails/[id]/reprocess/route.js +4 -2
- package/dist/modules/inbox_ops/api/emails/[id]/reprocess/route.js.map +2 -2
- package/dist/modules/inbox_ops/api/emails/[id]/route.js +4 -2
- package/dist/modules/inbox_ops/api/emails/[id]/route.js.map +2 -2
- package/dist/modules/inbox_ops/api/emails/route.js +3 -1
- package/dist/modules/inbox_ops/api/emails/route.js.map +2 -2
- package/dist/modules/inbox_ops/api/extract/route.js +3 -1
- package/dist/modules/inbox_ops/api/extract/route.js.map +2 -2
- package/dist/modules/inbox_ops/api/proposals/[id]/actions/[actionId]/route.js +3 -1
- package/dist/modules/inbox_ops/api/proposals/[id]/actions/[actionId]/route.js.map +2 -2
- package/dist/modules/inbox_ops/api/proposals/[id]/replies/[replyId]/send/route.js +4 -2
- package/dist/modules/inbox_ops/api/proposals/[id]/replies/[replyId]/send/route.js.map +2 -2
- package/dist/modules/inbox_ops/api/proposals/counts/route.js +4 -2
- package/dist/modules/inbox_ops/api/proposals/counts/route.js.map +2 -2
- package/dist/modules/inbox_ops/api/proposals/route.js +3 -1
- package/dist/modules/inbox_ops/api/proposals/route.js.map +2 -2
- package/dist/modules/inbox_ops/api/routeHelpers.js +3 -1
- package/dist/modules/inbox_ops/api/routeHelpers.js.map +2 -2
- package/dist/modules/inbox_ops/api/settings/route.js +3 -1
- package/dist/modules/inbox_ops/api/settings/route.js.map +2 -2
- package/dist/modules/inbox_ops/api/webhook/inbound.js +7 -5
- package/dist/modules/inbox_ops/api/webhook/inbound.js.map +2 -2
- package/dist/modules/inbox_ops/lib/cache.js +4 -2
- package/dist/modules/inbox_ops/lib/cache.js.map +2 -2
- package/dist/modules/inbox_ops/lib/catalogLookup.js +3 -1
- package/dist/modules/inbox_ops/lib/catalogLookup.js.map +2 -2
- package/dist/modules/inbox_ops/lib/eventBus.js +3 -4
- package/dist/modules/inbox_ops/lib/eventBus.js.map +2 -2
- package/dist/modules/inbox_ops/lib/messagesIntegration.js +4 -8
- package/dist/modules/inbox_ops/lib/messagesIntegration.js.map +2 -2
- package/dist/modules/inbox_ops/subscribers/executionAuditor.js +3 -1
- package/dist/modules/inbox_ops/subscribers/executionAuditor.js.map +2 -2
- package/dist/modules/inbox_ops/subscribers/extractionWorker.js +10 -8
- package/dist/modules/inbox_ops/subscribers/extractionWorker.js.map +2 -2
- package/dist/modules/inbox_ops/subscribers/proposalNotifier.js +3 -1
- package/dist/modules/inbox_ops/subscribers/proposalNotifier.js.map +2 -2
- package/dist/modules/messages/api/[id]/route.js +3 -4
- package/dist/modules/messages/api/[id]/route.js.map +2 -2
- package/dist/modules/messages/commands/actions.js +3 -1
- package/dist/modules/messages/commands/actions.js.map +2 -2
- package/dist/modules/messages/components/MessagesInboxPageClient.js +3 -1
- package/dist/modules/messages/components/MessagesInboxPageClient.js.map +2 -2
- package/dist/modules/messages/lib/email-sender.js +3 -7
- package/dist/modules/messages/lib/email-sender.js.map +2 -2
- package/dist/modules/messages/lib/message-objects-registry.js +3 -1
- package/dist/modules/messages/lib/message-objects-registry.js.map +2 -2
- package/dist/modules/messages/lib/message-types-registry.js +3 -1
- package/dist/modules/messages/lib/message-types-registry.js.map +2 -2
- package/dist/modules/messages/workers/send-email.worker.js +6 -4
- package/dist/modules/messages/workers/send-email.worker.js.map +2 -2
- package/dist/modules/notifications/lib/notificationMapper.js +3 -4
- package/dist/modules/notifications/lib/notificationMapper.js.map +2 -2
- package/dist/modules/notifications/lib/notificationService.js +4 -5
- package/dist/modules/notifications/lib/notificationService.js.map +2 -2
- package/dist/modules/notifications/subscribers/deliver-notification.js +8 -13
- package/dist/modules/notifications/subscribers/deliver-notification.js.map +2 -2
- package/dist/modules/payment_gateways/api/webhook/[provider]/route.js +3 -1
- package/dist/modules/payment_gateways/api/webhook/[provider]/route.js.map +2 -2
- package/dist/modules/perspectives/services/perspectiveService.js +3 -3
- package/dist/modules/perspectives/services/perspectiveService.js.map +2 -2
- package/dist/modules/planner/api/access.js +3 -3
- package/dist/modules/planner/api/access.js.map +2 -2
- package/dist/modules/planner/api/availability-date-specific.js +3 -1
- package/dist/modules/planner/api/availability-date-specific.js.map +2 -2
- package/dist/modules/planner/api/availability-weekly.js +3 -1
- package/dist/modules/planner/api/availability-weekly.js.map +2 -2
- package/dist/modules/planner/backend/planner/availability-rulesets/page.js +4 -2
- package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
- package/dist/modules/planner/components/AvailabilityRulesEditor.js +3 -1
- package/dist/modules/planner/components/AvailabilityRulesEditor.js.map +2 -2
- package/dist/modules/progress/api/jobs/route.js +3 -1
- package/dist/modules/progress/api/jobs/route.js.map +2 -2
- package/dist/modules/query_index/components/QueryIndexesTable.js +5 -3
- package/dist/modules/query_index/components/QueryIndexesTable.js.map +2 -2
- package/dist/modules/query_index/lib/batch.js +4 -2
- package/dist/modules/query_index/lib/batch.js.map +2 -2
- package/dist/modules/query_index/lib/coverage.js +3 -1
- package/dist/modules/query_index/lib/coverage.js.map +2 -2
- package/dist/modules/query_index/lib/engine.js +13 -18
- package/dist/modules/query_index/lib/engine.js.map +2 -2
- package/dist/modules/query_index/lib/reindexer.js +8 -6
- package/dist/modules/query_index/lib/reindexer.js.map +2 -2
- package/dist/modules/query_index/lib/search-tokens.js +3 -1
- package/dist/modules/query_index/lib/search-tokens.js.map +2 -2
- package/dist/modules/query_index/subscribers/coverage_refresh.js +3 -1
- package/dist/modules/query_index/subscribers/coverage_refresh.js.map +2 -2
- package/dist/modules/resources/api/comments.js +3 -1
- package/dist/modules/resources/api/comments.js.map +2 -2
- package/dist/modules/resources/api/resources/tags/assign/route.js +3 -1
- package/dist/modules/resources/api/resources/tags/assign/route.js.map +2 -2
- package/dist/modules/resources/api/resources/tags/unassign/route.js +3 -1
- package/dist/modules/resources/api/resources/tags/unassign/route.js.map +2 -2
- package/dist/modules/resources/backend/resources/resource-types/[id]/edit/page.js +3 -1
- package/dist/modules/resources/backend/resources/resource-types/[id]/edit/page.js.map +2 -2
- package/dist/modules/resources/backend/resources/resource-types/page.js +4 -2
- package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
- package/dist/modules/resources/commands/activities.js +6 -5
- package/dist/modules/resources/commands/activities.js.map +2 -2
- package/dist/modules/resources/commands/comments.js +6 -4
- package/dist/modules/resources/commands/comments.js.map +2 -2
- package/dist/modules/resources/commands/shared.js +24 -1
- package/dist/modules/resources/commands/shared.js.map +2 -2
- package/dist/modules/sales/api/channels/route.js +3 -1
- package/dist/modules/sales/api/channels/route.js.map +2 -2
- package/dist/modules/sales/api/document-history/route.js +3 -1
- package/dist/modules/sales/api/document-history/route.js.map +2 -2
- package/dist/modules/sales/api/document-numbers/route.js +3 -1
- package/dist/modules/sales/api/document-numbers/route.js.map +2 -2
- package/dist/modules/sales/api/quotes/accept/route.js +4 -2
- package/dist/modules/sales/api/quotes/accept/route.js.map +2 -2
- package/dist/modules/sales/api/quotes/convert/route.js +3 -1
- package/dist/modules/sales/api/quotes/convert/route.js.map +2 -2
- package/dist/modules/sales/api/quotes/public/[token]/route.js +3 -1
- package/dist/modules/sales/api/quotes/public/[token]/route.js.map +2 -2
- package/dist/modules/sales/api/quotes/send/route.js +3 -1
- package/dist/modules/sales/api/quotes/send/route.js.map +2 -2
- package/dist/modules/sales/api/returns/[id]/route.js +3 -1
- package/dist/modules/sales/api/returns/[id]/route.js.map +2 -2
- package/dist/modules/sales/api/settings/document-numbers/route.js +4 -2
- package/dist/modules/sales/api/settings/document-numbers/route.js.map +2 -2
- package/dist/modules/sales/api/settings/order-editing/route.js +4 -2
- package/dist/modules/sales/api/settings/order-editing/route.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js +3 -1
- package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/offers/page.js +6 -4
- package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/page.js +4 -2
- package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/documents/[id]/page.js +20 -18
- package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +4 -8
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/commands/payments.js +3 -1
- package/dist/modules/sales/commands/payments.js.map +2 -2
- package/dist/modules/sales/commands/shipments.js +3 -1
- package/dist/modules/sales/commands/shipments.js.map +2 -2
- package/dist/modules/sales/components/AdjustmentKindSettings.js +5 -3
- package/dist/modules/sales/components/AdjustmentKindSettings.js.map +2 -2
- package/dist/modules/sales/components/DocumentNumberSettings.js +4 -2
- package/dist/modules/sales/components/DocumentNumberSettings.js.map +2 -2
- package/dist/modules/sales/components/OrderEditingSettings.js +4 -2
- package/dist/modules/sales/components/OrderEditingSettings.js.map +2 -2
- package/dist/modules/sales/components/PaymentMethodsSettings.js +5 -3
- package/dist/modules/sales/components/PaymentMethodsSettings.js.map +2 -2
- package/dist/modules/sales/components/ShippingMethodsSettings.js +5 -3
- package/dist/modules/sales/components/ShippingMethodsSettings.js.map +2 -2
- package/dist/modules/sales/components/StatusSettings.js +5 -3
- package/dist/modules/sales/components/StatusSettings.js.map +2 -2
- package/dist/modules/sales/components/TaxRatesSettings.js +5 -3
- package/dist/modules/sales/components/TaxRatesSettings.js.map +2 -2
- package/dist/modules/sales/components/channels/ChannelOfferForm.js +16 -14
- package/dist/modules/sales/components/channels/ChannelOfferForm.js.map +2 -2
- package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js +4 -2
- package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js.map +2 -2
- package/dist/modules/sales/components/documents/AddressesSection.js +5 -3
- package/dist/modules/sales/components/documents/AddressesSection.js.map +2 -2
- package/dist/modules/sales/components/documents/AdjustmentDialog.js +3 -1
- package/dist/modules/sales/components/documents/AdjustmentDialog.js.map +2 -2
- package/dist/modules/sales/components/documents/AdjustmentsSection.js +5 -3
- package/dist/modules/sales/components/documents/AdjustmentsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/ItemsSection.js +6 -4
- package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/LineItemDialog.js +8 -6
- package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
- package/dist/modules/sales/components/documents/PaymentDialog.js +5 -3
- package/dist/modules/sales/components/documents/PaymentDialog.js.map +2 -2
- package/dist/modules/sales/components/documents/PaymentsSection.js +4 -2
- package/dist/modules/sales/components/documents/PaymentsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesDocumentForm.js +14 -12
- package/dist/modules/sales/components/documents/SalesDocumentForm.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js +5 -3
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
- package/dist/modules/sales/components/documents/ShipmentDialog.js +9 -7
- package/dist/modules/sales/components/documents/ShipmentDialog.js.map +2 -2
- package/dist/modules/sales/components/documents/ShipmentsSection.js +4 -2
- package/dist/modules/sales/components/documents/ShipmentsSection.js.map +2 -2
- package/dist/modules/sales/frontend/quote/[token]/page.js +4 -2
- package/dist/modules/sales/frontend/quote/[token]/page.js.map +2 -2
- package/dist/modules/sales/seed/examples.js +7 -9
- package/dist/modules/sales/seed/examples.js.map +2 -2
- package/dist/modules/sales/subscribers/quote-expiring-notification.js +3 -1
- package/dist/modules/sales/subscribers/quote-expiring-notification.js.map +2 -2
- package/dist/modules/sales/subscribers/reconcileOnAddressDelete.js +3 -1
- package/dist/modules/sales/subscribers/reconcileOnAddressDelete.js.map +2 -2
- package/dist/modules/sales/subscribers/reconcileOnCompanyDelete.js +3 -1
- package/dist/modules/sales/subscribers/reconcileOnCompanyDelete.js.map +2 -2
- package/dist/modules/sales/subscribers/reconcileOnCustomerDelete.js +3 -1
- package/dist/modules/sales/subscribers/reconcileOnCustomerDelete.js.map +2 -2
- package/dist/modules/sales/widgets/dashboard/makeDashboardWidgetRoute.js +5 -3
- package/dist/modules/sales/widgets/dashboard/makeDashboardWidgetRoute.js.map +2 -2
- package/dist/modules/sales/widgets/dashboard/new-orders/widget.client.js +3 -1
- package/dist/modules/sales/widgets/dashboard/new-orders/widget.client.js.map +2 -2
- package/dist/modules/sales/widgets/dashboard/new-quotes/widget.client.js +3 -1
- package/dist/modules/sales/widgets/dashboard/new-quotes/widget.client.js.map +2 -2
- package/dist/modules/shipping_carriers/api/tracking/route.js +5 -0
- package/dist/modules/shipping_carriers/api/tracking/route.js.map +2 -2
- package/dist/modules/shipping_carriers/api/webhook/[provider]/route.js +3 -1
- package/dist/modules/shipping_carriers/api/webhook/[provider]/route.js.map +2 -2
- package/dist/modules/shipping_carriers/lib/shipping-service.js +41 -19
- package/dist/modules/shipping_carriers/lib/shipping-service.js.map +2 -2
- package/dist/modules/shipping_carriers/lib/upstream-error-response.js +3 -1
- package/dist/modules/shipping_carriers/lib/upstream-error-response.js.map +2 -2
- package/dist/modules/shipping_carriers/workers/webhook-processor.js +3 -5
- package/dist/modules/shipping_carriers/workers/webhook-processor.js.map +2 -2
- package/dist/modules/staff/api/comments.js +3 -1
- package/dist/modules/staff/api/comments.js.map +2 -2
- package/dist/modules/staff/api/leave-requests/accept/route.js +3 -1
- package/dist/modules/staff/api/leave-requests/accept/route.js.map +2 -2
- package/dist/modules/staff/api/leave-requests/reject/route.js +3 -1
- package/dist/modules/staff/api/leave-requests/reject/route.js.map +2 -2
- package/dist/modules/staff/api/team-members/assignable/route.js +3 -1
- package/dist/modules/staff/api/team-members/assignable/route.js.map +2 -2
- package/dist/modules/staff/api/team-members/self/route.js +4 -2
- package/dist/modules/staff/api/team-members/self/route.js.map +2 -2
- package/dist/modules/staff/api/team-members/tags/assign/route.js +3 -1
- package/dist/modules/staff/api/team-members/tags/assign/route.js.map +2 -2
- package/dist/modules/staff/api/team-members/tags/unassign/route.js +3 -1
- package/dist/modules/staff/api/team-members/tags/unassign/route.js.map +2 -2
- package/dist/modules/staff/api/timesheets/my-projects/[projectId]/route.js +3 -1
- package/dist/modules/staff/api/timesheets/my-projects/[projectId]/route.js.map +2 -2
- package/dist/modules/staff/api/timesheets/my-projects/route.js +3 -1
- package/dist/modules/staff/api/timesheets/my-projects/route.js.map +2 -2
- package/dist/modules/staff/api/timesheets/projects/kpis/route.js +3 -1
- package/dist/modules/staff/api/timesheets/projects/kpis/route.js.map +2 -2
- package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/route.js +3 -1
- package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/route.js.map +2 -2
- package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js +4 -2
- package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js.map +2 -2
- package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.js +4 -2
- package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.js.map +2 -2
- package/dist/modules/staff/api/timesheets/time-entries/bulk/route.js +3 -1
- package/dist/modules/staff/api/timesheets/time-entries/bulk/route.js.map +2 -2
- package/dist/modules/staff/api/timesheets/time-entries/start-timer/route.js +3 -1
- package/dist/modules/staff/api/timesheets/time-entries/start-timer/route.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-members/page.js +4 -2
- package/dist/modules/staff/backend/staff/team-members/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-roles/page.js +4 -2
- package/dist/modules/staff/backend/staff/team-roles/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +4 -2
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/teams/page.js +4 -2
- package/dist/modules/staff/backend/staff/teams/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/timesheets/page.js +7 -5
- package/dist/modules/staff/backend/staff/timesheets/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js +3 -1
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/timesheets/projects/page.js +4 -2
- package/dist/modules/staff/backend/staff/timesheets/projects/page.js.map +2 -2
- package/dist/modules/staff/commands/timesheets-entries.js +3 -1
- package/dist/modules/staff/commands/timesheets-entries.js.map +2 -2
- package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.client.js +3 -1
- package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.client.js.map +2 -2
- package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.js +5 -3
- package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.js.map +2 -2
- package/dist/modules/sync_excel/api/import/route.js +3 -1
- package/dist/modules/sync_excel/api/import/route.js.map +2 -2
- package/dist/modules/translations/api/[entityType]/[entityId]/route.js +5 -3
- package/dist/modules/translations/api/[entityType]/[entityId]/route.js.map +2 -2
- package/dist/modules/translations/api/get/locales.js +3 -1
- package/dist/modules/translations/api/get/locales.js.map +2 -2
- package/dist/modules/translations/api/put/locales.js +3 -1
- package/dist/modules/translations/api/put/locales.js.map +2 -2
- package/dist/modules/translations/components/TranslationManager.js +3 -1
- package/dist/modules/translations/components/TranslationManager.js.map +2 -2
- package/dist/modules/translations/subscribers/cleanup.js +3 -1
- package/dist/modules/translations/subscribers/cleanup.js.map +2 -2
- package/dist/modules/workflows/api/definitions/[id]/customize/route.js +4 -2
- package/dist/modules/workflows/api/definitions/[id]/customize/route.js.map +2 -2
- package/dist/modules/workflows/api/definitions/[id]/reset-to-code/route.js +4 -2
- package/dist/modules/workflows/api/definitions/[id]/reset-to-code/route.js.map +2 -2
- package/dist/modules/workflows/api/definitions/[id]/route.js +6 -4
- package/dist/modules/workflows/api/definitions/[id]/route.js.map +2 -2
- package/dist/modules/workflows/api/definitions/route.js +4 -2
- package/dist/modules/workflows/api/definitions/route.js.map +2 -2
- package/dist/modules/workflows/api/events/[id]/route.js +3 -1
- package/dist/modules/workflows/api/events/[id]/route.js.map +2 -2
- package/dist/modules/workflows/api/events/route.js +3 -1
- package/dist/modules/workflows/api/events/route.js.map +2 -2
- package/dist/modules/workflows/api/instances/[id]/advance/route.js +3 -1
- package/dist/modules/workflows/api/instances/[id]/advance/route.js.map +2 -2
- package/dist/modules/workflows/api/instances/[id]/cancel/route.js +3 -1
- package/dist/modules/workflows/api/instances/[id]/cancel/route.js.map +2 -2
- package/dist/modules/workflows/api/instances/[id]/events/route.js +3 -1
- package/dist/modules/workflows/api/instances/[id]/events/route.js.map +2 -2
- package/dist/modules/workflows/api/instances/[id]/retry/route.js +3 -1
- package/dist/modules/workflows/api/instances/[id]/retry/route.js.map +2 -2
- package/dist/modules/workflows/api/instances/[id]/route.js +3 -1
- package/dist/modules/workflows/api/instances/[id]/route.js.map +2 -2
- package/dist/modules/workflows/api/instances/[id]/signal/route.js +5 -7
- package/dist/modules/workflows/api/instances/[id]/signal/route.js.map +2 -2
- package/dist/modules/workflows/api/instances/route.js +5 -3
- package/dist/modules/workflows/api/instances/route.js.map +2 -2
- package/dist/modules/workflows/api/instances/validate-start/route.js +3 -1
- package/dist/modules/workflows/api/instances/validate-start/route.js.map +2 -2
- package/dist/modules/workflows/api/signals/route.js +3 -1
- package/dist/modules/workflows/api/signals/route.js.map +2 -2
- package/dist/modules/workflows/api/tasks/[id]/claim/route.js +3 -1
- package/dist/modules/workflows/api/tasks/[id]/claim/route.js.map +2 -2
- package/dist/modules/workflows/api/tasks/[id]/complete/route.js +3 -1
- package/dist/modules/workflows/api/tasks/[id]/complete/route.js.map +2 -2
- package/dist/modules/workflows/api/tasks/[id]/route.js +3 -1
- package/dist/modules/workflows/api/tasks/[id]/route.js.map +2 -2
- package/dist/modules/workflows/api/tasks/route.js +3 -1
- package/dist/modules/workflows/api/tasks/route.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/visual-editor/page.js +4 -2
- package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +2 -2
- package/dist/modules/workflows/backend/instances/[id]/page.js +5 -3
- package/dist/modules/workflows/backend/instances/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/[id]/page.js +3 -1
- package/dist/modules/workflows/backend/tasks/[id]/page.js.map +2 -2
- package/dist/modules/workflows/components/BusinessRulesSelector.js +5 -3
- package/dist/modules/workflows/components/BusinessRulesSelector.js.map +2 -2
- package/dist/modules/workflows/components/WorkflowSelector.js +5 -3
- package/dist/modules/workflows/components/WorkflowSelector.js.map +2 -2
- package/dist/modules/workflows/components/fields/BusinessRuleConditionsEditor.js +3 -1
- package/dist/modules/workflows/components/fields/BusinessRuleConditionsEditor.js.map +2 -2
- package/dist/modules/workflows/components/fields/StartPreConditionsEditor.js +3 -1
- package/dist/modules/workflows/components/fields/StartPreConditionsEditor.js.map +2 -2
- package/dist/modules/workflows/components/fields/WorkflowSelectorField.js +3 -1
- package/dist/modules/workflows/components/fields/WorkflowSelectorField.js.map +2 -2
- package/dist/modules/workflows/frontend/checkout-demo/page.js +8 -7
- package/dist/modules/workflows/frontend/checkout-demo/page.js.map +2 -2
- package/dist/modules/workflows/lib/activity-executor.js +25 -21
- package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
- package/dist/modules/workflows/lib/activity-worker-handler.js +8 -15
- package/dist/modules/workflows/lib/activity-worker-handler.js.map +2 -2
- package/dist/modules/workflows/lib/code-registry.js +7 -7
- package/dist/modules/workflows/lib/code-registry.js.map +2 -2
- package/dist/modules/workflows/lib/compensation-handler.js +4 -2
- package/dist/modules/workflows/lib/compensation-handler.js.map +2 -2
- package/dist/modules/workflows/lib/edgeFormTransforms.js +3 -1
- package/dist/modules/workflows/lib/edgeFormTransforms.js.map +2 -2
- package/dist/modules/workflows/lib/event-trigger-service.js +5 -3
- package/dist/modules/workflows/lib/event-trigger-service.js.map +2 -2
- package/dist/modules/workflows/lib/nodeFormTransforms.js +3 -1
- package/dist/modules/workflows/lib/nodeFormTransforms.js.map +2 -2
- package/dist/modules/workflows/lib/seeds.js +16 -2
- package/dist/modules/workflows/lib/seeds.js.map +2 -2
- package/dist/modules/workflows/lib/signal-handler.js +3 -1
- package/dist/modules/workflows/lib/signal-handler.js.map +2 -2
- package/dist/modules/workflows/lib/start-validator.js +9 -3
- package/dist/modules/workflows/lib/start-validator.js.map +2 -2
- package/dist/modules/workflows/lib/step-handler.js +3 -1
- package/dist/modules/workflows/lib/step-handler.js.map +2 -2
- package/dist/modules/workflows/lib/task-handler.js +3 -1
- package/dist/modules/workflows/lib/task-handler.js.map +2 -2
- package/dist/modules/workflows/lib/transition-handler.js +5 -3
- package/dist/modules/workflows/lib/transition-handler.js.map +2 -2
- package/dist/modules/workflows/lib/workflow-executor.js +27 -15
- package/dist/modules/workflows/lib/workflow-executor.js.map +2 -2
- package/dist/modules/workflows/subscribers/event-trigger.js +21 -18
- package/dist/modules/workflows/subscribers/event-trigger.js.map +2 -2
- package/dist/modules/workflows/subscribers/task-assigned-notification.js +3 -1
- package/dist/modules/workflows/subscribers/task-assigned-notification.js.map +2 -2
- package/dist/modules/workflows/workers/workflow-activities.worker.js +30 -20
- package/dist/modules/workflows/workers/workflow-activities.worker.js.map +2 -2
- package/package.json +7 -7
- package/src/bootstrap.ts +14 -11
- package/src/helpers/integration/queue-runner.ts +2 -2
- package/src/modules/api_keys/services/apiKeyService.ts +6 -3
- package/src/modules/attachments/api/image/[id]/[[...slug]]/route.ts +5 -2
- package/src/modules/attachments/api/library/[id]/route.ts +4 -1
- package/src/modules/attachments/api/route.ts +9 -6
- package/src/modules/attachments/components/AttachmentPartitionSettings.tsx +6 -3
- package/src/modules/attachments/lib/assignmentDetails.ts +4 -1
- package/src/modules/attachments/lib/drivers/driverFactory.ts +4 -1
- package/src/modules/attachments/lib/ocrQueue.ts +11 -11
- package/src/modules/attachments/lib/ocrService.ts +7 -4
- package/src/modules/audit_logs/api/audit-logs/actions/redo/route.ts +4 -1
- package/src/modules/audit_logs/api/audit-logs/actions/undo/route.ts +4 -1
- package/src/modules/audit_logs/backend/audit-logs/page.tsx +4 -1
- package/src/modules/audit_logs/components/AuditLogsActions.tsx +5 -2
- package/src/modules/audit_logs/services/accessLogService.ts +5 -4
- package/src/modules/audit_logs/services/actionLogService.ts +5 -2
- package/src/modules/auth/api/profile/route.ts +5 -2
- package/src/modules/auth/api/reset/confirm.ts +4 -1
- package/src/modules/auth/api/reset.ts +5 -2
- package/src/modules/auth/api/roles/route.ts +4 -1
- package/src/modules/auth/api/sidebar/variants/route.ts +4 -2
- package/src/modules/auth/api/users/resend-invite/route.ts +5 -2
- package/src/modules/auth/api/users/route.ts +4 -1
- package/src/modules/auth/backend/auth/profile/page.tsx +4 -1
- package/src/modules/auth/backend/profile/change-password/page.tsx +4 -1
- package/src/modules/auth/backend/users/[id]/edit/page.tsx +6 -3
- package/src/modules/auth/backend/users/create/page.tsx +5 -2
- package/src/modules/auth/cli.ts +10 -0
- package/src/modules/auth/commands/users.ts +5 -2
- package/src/modules/auth/lib/consentIntegrity.ts +4 -4
- package/src/modules/auth/lib/setup-app.ts +10 -10
- package/src/modules/auth/lib/tenantAccess.ts +4 -1
- package/src/modules/auth/lib/tokenHash.ts +4 -4
- package/src/modules/business_rules/api/rules/route.ts +5 -2
- package/src/modules/business_rules/lib/expression-evaluator.ts +8 -6
- package/src/modules/business_rules/lib/rule-engine.ts +6 -3
- package/src/modules/business_rules/lib/rule-evaluator.ts +11 -11
- package/src/modules/business_rules/subscribers/crud-rule-trigger.ts +4 -1
- package/src/modules/business_rules/subscribers/rule-execution-failed-notification.ts +4 -1
- package/src/modules/catalog/ai-agents-context.ts +5 -5
- package/src/modules/catalog/ai-tools/_shared.ts +4 -1
- package/src/modules/catalog/ai-tools/authoring-pack.ts +4 -1
- package/src/modules/catalog/ai-tools/merchandising-pack.ts +4 -1
- package/src/modules/catalog/api/dictionaries/[key]/route.ts +4 -1
- package/src/modules/catalog/api/prices/route.ts +4 -1
- package/src/modules/catalog/api/products/route.ts +6 -3
- package/src/modules/catalog/api/settings/route.ts +5 -2
- package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +15 -12
- package/src/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.tsx +9 -6
- package/src/modules/catalog/backend/catalog/products/[productId]/variants/create/page.tsx +6 -3
- package/src/modules/catalog/backend/catalog/products/create/page.tsx +6 -6
- package/src/modules/catalog/backend/catalog/products/optionSchemaClient.ts +4 -1
- package/src/modules/catalog/components/PriceKindSettings.tsx +6 -3
- package/src/modules/catalog/components/UnitPriceDisplaySettings.tsx +5 -2
- package/src/modules/catalog/inbox-actions.ts +5 -2
- package/src/modules/catalog/seed/examples.ts +5 -5
- package/src/modules/catalog/subscribers/low-stock-notification.ts +4 -1
- package/src/modules/catalog/widgets/injection/product-seo/state.ts +4 -1
- package/src/modules/communication_channels/api/get/oauth/[provider]/callback/route.ts +13 -13
- package/src/modules/communication_channels/api/post/channels/[id]/import-history/route.ts +4 -1
- package/src/modules/communication_channels/api/post/channels/[id]/push/register/route.ts +4 -1
- package/src/modules/communication_channels/api/post/webhook/[provider]/route.ts +6 -3
- package/src/modules/communication_channels/api/post/webhooks/gmail/route.ts +7 -6
- package/src/modules/communication_channels/commands/connect-credential-channel.ts +5 -10
- package/src/modules/communication_channels/commands/delete-channel.ts +4 -5
- package/src/modules/communication_channels/commands/deliver-outbound-message.ts +5 -5
- package/src/modules/communication_channels/commands/disconnect-channel.ts +4 -5
- package/src/modules/communication_channels/commands/ingest-inbound-message.ts +6 -12
- package/src/modules/communication_channels/commands/push-unregister.ts +4 -3
- package/src/modules/communication_channels/commands/reassign-conversation.ts +6 -3
- package/src/modules/communication_channels/lib/dead-letter.ts +4 -5
- package/src/modules/communication_channels/lib/email-mime.ts +5 -6
- package/src/modules/communication_channels/lib/oauth-client-config.ts +7 -3
- package/src/modules/communication_channels/lib/send-as-user.ts +4 -1
- package/src/modules/communication_channels/lib/thread-token.ts +5 -2
- package/src/modules/communication_channels/setup.ts +4 -4
- package/src/modules/communication_channels/workers/channel-import-history.ts +5 -8
- package/src/modules/communication_channels/workers/gmail-history-sync.ts +9 -18
- package/src/modules/communication_channels/workers/gmail-renew-watch.ts +6 -9
- package/src/modules/communication_channels/workers/outbound-delivery.ts +7 -12
- package/src/modules/communication_channels/workers/poll-channel.ts +8 -15
- package/src/modules/communication_channels/workers/poll-tick.ts +6 -6
- package/src/modules/communication_channels/workers/reaction-processor.ts +6 -9
- package/src/modules/configs/api/cache/route.ts +5 -2
- package/src/modules/configs/api/system-status/route.ts +5 -2
- package/src/modules/configs/api/upgrade-actions/route.ts +5 -2
- package/src/modules/configs/components/ModuleTelemetryPanel.tsx +4 -1
- package/src/modules/configs/lib/touchGeneratedBarrels.ts +1 -1
- package/src/modules/configs/services/upgradeActionsService.ts +7 -3
- package/src/modules/currencies/components/CurrencyFetchingConfig.tsx +4 -1
- package/src/modules/currencies/lib/exchangeRateFormConfig.ts +4 -1
- package/src/modules/currencies/services/providers/nbp.ts +7 -4
- package/src/modules/currencies/services/providers/raiffeisen.ts +8 -7
- package/src/modules/customer_accounts/api/domain-resolve/all.ts +7 -5
- package/src/modules/customer_accounts/api/signup.ts +5 -2
- package/src/modules/customer_accounts/lib/customerAuthServer.ts +4 -1
- package/src/modules/customer_accounts/subscribers/autoLinkCrm.ts +4 -1
- package/src/modules/customer_accounts/subscribers/autoLinkCrmReverse.ts +4 -1
- package/src/modules/customer_accounts/subscribers/unlinkOnCompanyDelete.ts +4 -1
- package/src/modules/customer_accounts/subscribers/unlinkOnPersonDelete.ts +4 -1
- package/src/modules/customers/ai-agents-context.ts +5 -5
- package/src/modules/customers/api/activities/route.ts +7 -4
- package/src/modules/customers/api/comments/route.ts +4 -1
- package/src/modules/customers/api/companies/[id]/people/route.ts +4 -1
- package/src/modules/customers/api/companies/[id]/route.ts +6 -3
- package/src/modules/customers/api/companies/route.ts +6 -3
- package/src/modules/customers/api/dashboard/widgets/customer-todos/route.ts +4 -1
- package/src/modules/customers/api/dashboard/widgets/new-customers/route.ts +4 -1
- package/src/modules/customers/api/dashboard/widgets/new-deals/route.ts +4 -1
- package/src/modules/customers/api/dashboard/widgets/next-interactions/route.ts +4 -1
- package/src/modules/customers/api/deals/[id]/companies/route.ts +4 -1
- package/src/modules/customers/api/deals/[id]/people/route.ts +4 -1
- package/src/modules/customers/api/deals/aggregate/route.ts +4 -1
- package/src/modules/customers/api/deals/bulk-update-owner/route.ts +8 -5
- package/src/modules/customers/api/deals/bulk-update-stage/route.ts +8 -5
- package/src/modules/customers/api/deals/route.ts +4 -1
- package/src/modules/customers/api/deals/summary/route.ts +4 -1
- package/src/modules/customers/api/dictionaries/[kind]/[id]/route.ts +5 -2
- package/src/modules/customers/api/dictionaries/[kind]/route.ts +6 -3
- package/src/modules/customers/api/dictionaries/cache.ts +4 -1
- package/src/modules/customers/api/dictionaries/context.ts +4 -1
- package/src/modules/customers/api/dictionaries/currency/route.ts +4 -1
- package/src/modules/customers/api/dictionaries/kind-settings/route.ts +5 -2
- package/src/modules/customers/api/entity-roles-factory.ts +8 -5
- package/src/modules/customers/api/interactions/cancel/route.ts +4 -1
- package/src/modules/customers/api/interactions/complete/route.ts +4 -1
- package/src/modules/customers/api/interactions/conflicts/route.ts +4 -1
- package/src/modules/customers/api/interactions/counts/route.ts +4 -1
- package/src/modules/customers/api/interactions/route.ts +8 -4
- package/src/modules/customers/api/interactions/tasks/route.ts +4 -1
- package/src/modules/customers/api/labels/assign/route.ts +4 -1
- package/src/modules/customers/api/labels/route.ts +7 -3
- package/src/modules/customers/api/labels/unassign/route.ts +4 -1
- package/src/modules/customers/api/people/[id]/companies/enriched/route.ts +4 -1
- package/src/modules/customers/api/people/[id]/route.ts +6 -3
- package/src/modules/customers/api/people/route.ts +6 -3
- package/src/modules/customers/api/pipeline-stages/reorder/route.ts +4 -1
- package/src/modules/customers/api/pipeline-stages/route.ts +7 -4
- package/src/modules/customers/api/pipelines/route.ts +7 -4
- package/src/modules/customers/api/settings/address-format/route.ts +5 -2
- package/src/modules/customers/api/settings/dictionary-sort-modes/route.ts +5 -2
- package/src/modules/customers/api/settings/stuck-threshold/route.ts +5 -2
- package/src/modules/customers/api/tags/assign/route.ts +4 -1
- package/src/modules/customers/api/tags/unassign/route.ts +4 -1
- package/src/modules/customers/api/todos/route.ts +7 -4
- package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +6 -3
- package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealActivities.ts +4 -1
- package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealClosure.ts +4 -1
- package/src/modules/customers/backend/customers/deals/map/components/DealsMapCanvasImpl.tsx +5 -3
- package/src/modules/customers/backend/customers/deals/page.tsx +5 -2
- package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +6 -3
- package/src/modules/customers/commands/deals.ts +4 -1
- package/src/modules/customers/commands/dictionaries.ts +4 -1
- package/src/modules/customers/commands/interactions.ts +5 -2
- package/src/modules/customers/commands/shared.ts +5 -2
- package/src/modules/customers/commands/todos.ts +4 -1
- package/src/modules/customers/components/DictionarySettings.tsx +6 -3
- package/src/modules/customers/components/DictionarySortSettings.tsx +4 -1
- package/src/modules/customers/components/detail/ActivitiesCard.tsx +4 -1
- package/src/modules/customers/components/detail/ActivitiesDayStrip.tsx +4 -1
- package/src/modules/customers/components/detail/ActivitiesSection.tsx +7 -4
- package/src/modules/customers/components/detail/ActivityCard.tsx +4 -1
- package/src/modules/customers/components/detail/ChangelogTab.tsx +4 -1
- package/src/modules/customers/components/detail/CompanyCard.tsx +4 -1
- package/src/modules/customers/components/detail/ConfirmDealLostDialog.tsx +4 -1
- package/src/modules/customers/components/detail/EntityTagsDialog.tsx +4 -1
- package/src/modules/customers/components/detail/InlineActivityComposer.tsx +4 -1
- package/src/modules/customers/components/detail/ManageTagsDialog.tsx +4 -1
- package/src/modules/customers/components/detail/RoleAssignmentRow.tsx +6 -3
- package/src/modules/customers/components/detail/RolesSection.tsx +5 -2
- package/src/modules/customers/components/detail/hooks/useInteractionMutations.ts +6 -3
- package/src/modules/customers/components/linking/LinkEntityDialog.tsx +5 -2
- package/src/modules/customers/inbox-actions.ts +4 -1
- package/src/modules/customers/lib/bulkDeals.ts +4 -1
- package/src/modules/customers/lib/dealClosureNotification.ts +5 -2
- package/src/modules/customers/lib/dealStageTransitionTable.ts +4 -1
- package/src/modules/customers/lib/interactionFeatureFlags.ts +5 -1
- package/src/modules/customers/lib/todoCompatibility.ts +4 -1
- package/src/modules/customers/search.ts +15 -7
- package/src/modules/customers/widgets/dashboard/customer-todos/widget.client.tsx +4 -1
- package/src/modules/customers/widgets/dashboard/new-customers/widget.client.tsx +4 -1
- package/src/modules/customers/widgets/dashboard/new-deals/widget.client.tsx +4 -1
- package/src/modules/customers/widgets/dashboard/next-interactions/widget.client.tsx +4 -1
- package/src/modules/dashboards/api/widgets/data/batch/route.ts +4 -1
- package/src/modules/dashboards/api/widgets/data/route.ts +4 -1
- package/src/modules/dashboards/components/WidgetVisibilityEditor.tsx +6 -3
- package/src/modules/dashboards/widgets/dashboard/aov-kpi/widget.client.tsx +4 -1
- package/src/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.client.tsx +4 -1
- package/src/modules/dashboards/widgets/dashboard/orders-by-status/widget.client.tsx +4 -1
- package/src/modules/dashboards/widgets/dashboard/orders-kpi/widget.client.tsx +4 -1
- package/src/modules/dashboards/widgets/dashboard/pipeline-summary/widget.client.tsx +4 -1
- package/src/modules/dashboards/widgets/dashboard/revenue-kpi/widget.client.tsx +4 -1
- package/src/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.tsx +4 -1
- package/src/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.tsx +4 -1
- package/src/modules/dashboards/widgets/dashboard/top-customers/widget.client.tsx +4 -1
- package/src/modules/dashboards/widgets/dashboard/top-products/widget.client.tsx +4 -1
- package/src/modules/data_sync/api/run.ts +4 -1
- package/src/modules/data_sync/backend/data-sync/runs/[id]/page.tsx +3 -1
- package/src/modules/data_sync/lib/adapter-registry.ts +16 -4
- package/src/modules/data_sync/lib/sync-engine.ts +31 -2
- package/src/modules/data_sync/workers/sync-export.ts +4 -1
- package/src/modules/data_sync/workers/sync-import.ts +4 -1
- package/src/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.ts +5 -2
- package/src/modules/dictionaries/api/[dictionaryId]/entries/reorder/route.ts +4 -1
- package/src/modules/dictionaries/api/[dictionaryId]/entries/route.ts +5 -2
- package/src/modules/dictionaries/api/[dictionaryId]/entries/set-default/route.ts +4 -1
- package/src/modules/dictionaries/api/[dictionaryId]/route.ts +6 -3
- package/src/modules/dictionaries/api/context.ts +4 -1
- package/src/modules/dictionaries/api/route.ts +5 -2
- package/src/modules/dictionaries/components/DictionariesManager.tsx +6 -3
- package/src/modules/dictionaries/components/DictionaryEntriesEditor.tsx +5 -2
- package/src/modules/dictionaries/components/DictionaryEntrySelect.tsx +5 -2
- package/src/modules/dictionaries/components/DictionarySelectControl.tsx +4 -1
- package/src/modules/dictionaries/fields/dictionary.tsx +4 -1
- package/src/modules/directory/api/organization-branding/route.ts +4 -1
- package/src/modules/directory/api/organization-switcher/route.ts +4 -1
- package/src/modules/directory/commands/tenants.ts +6 -3
- package/src/modules/directory/utils/organizationScope.ts +7 -4
- package/src/modules/entities/api/definitions.cache.ts +4 -1
- package/src/modules/entities/api/definitions.ts +8 -5
- package/src/modules/entities/api/records.ts +5 -2
- package/src/modules/entities/components/EncryptionManager.tsx +4 -1
- package/src/modules/entities/lib/makeActivityRoute.ts +4 -1
- package/src/modules/feature_toggles/api/overrides/route.ts +4 -1
- package/src/modules/feature_toggles/lib/feature-flag-check.ts +6 -9
- package/src/modules/inbox_ops/api/emails/[id]/reprocess/route.ts +5 -2
- package/src/modules/inbox_ops/api/emails/[id]/route.ts +5 -2
- package/src/modules/inbox_ops/api/emails/route.ts +4 -1
- package/src/modules/inbox_ops/api/extract/route.ts +4 -1
- package/src/modules/inbox_ops/api/proposals/[id]/actions/[actionId]/route.ts +4 -1
- package/src/modules/inbox_ops/api/proposals/[id]/replies/[replyId]/send/route.ts +5 -2
- package/src/modules/inbox_ops/api/proposals/counts/route.ts +5 -2
- package/src/modules/inbox_ops/api/proposals/route.ts +4 -1
- package/src/modules/inbox_ops/api/routeHelpers.ts +4 -1
- package/src/modules/inbox_ops/api/settings/route.ts +4 -1
- package/src/modules/inbox_ops/api/webhook/inbound.ts +8 -5
- package/src/modules/inbox_ops/lib/cache.ts +5 -2
- package/src/modules/inbox_ops/lib/catalogLookup.ts +4 -1
- package/src/modules/inbox_ops/lib/eventBus.ts +4 -4
- package/src/modules/inbox_ops/lib/messagesIntegration.ts +5 -8
- package/src/modules/inbox_ops/subscribers/executionAuditor.ts +5 -1
- package/src/modules/inbox_ops/subscribers/extractionWorker.ts +11 -8
- package/src/modules/inbox_ops/subscribers/proposalNotifier.ts +4 -1
- package/src/modules/messages/api/[id]/route.ts +4 -4
- package/src/modules/messages/commands/actions.ts +4 -1
- package/src/modules/messages/components/MessagesInboxPageClient.tsx +4 -1
- package/src/modules/messages/lib/email-sender.ts +4 -7
- package/src/modules/messages/lib/message-objects-registry.ts +4 -1
- package/src/modules/messages/lib/message-types-registry.ts +4 -1
- package/src/modules/messages/workers/send-email.worker.ts +7 -4
- package/src/modules/notifications/lib/notificationMapper.ts +4 -4
- package/src/modules/notifications/lib/notificationService.ts +4 -5
- package/src/modules/notifications/subscribers/deliver-notification.ts +9 -14
- package/src/modules/payment_gateways/api/webhook/[provider]/route.ts +4 -1
- package/src/modules/perspectives/services/perspectiveService.ts +4 -3
- package/src/modules/planner/api/access.ts +4 -3
- package/src/modules/planner/api/availability-date-specific.ts +4 -1
- package/src/modules/planner/api/availability-weekly.ts +4 -1
- package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +5 -2
- package/src/modules/planner/components/AvailabilityRulesEditor.tsx +4 -1
- package/src/modules/progress/api/jobs/route.ts +4 -1
- package/src/modules/query_index/components/QueryIndexesTable.tsx +6 -3
- package/src/modules/query_index/lib/batch.ts +5 -2
- package/src/modules/query_index/lib/coverage.ts +4 -1
- package/src/modules/query_index/lib/engine.ts +14 -17
- package/src/modules/query_index/lib/reindexer.ts +9 -6
- package/src/modules/query_index/lib/search-tokens.ts +4 -2
- package/src/modules/query_index/subscribers/coverage_refresh.ts +4 -1
- package/src/modules/resources/api/comments.ts +4 -1
- package/src/modules/resources/api/resources/tags/assign/route.ts +4 -1
- package/src/modules/resources/api/resources/tags/unassign/route.ts +4 -1
- package/src/modules/resources/backend/resources/resource-types/[id]/edit/page.tsx +4 -1
- package/src/modules/resources/backend/resources/resource-types/page.tsx +5 -2
- package/src/modules/resources/commands/activities.ts +5 -4
- package/src/modules/resources/commands/comments.ts +6 -4
- package/src/modules/resources/commands/shared.ts +36 -0
- package/src/modules/sales/api/channels/route.ts +4 -1
- package/src/modules/sales/api/document-history/route.ts +4 -1
- package/src/modules/sales/api/document-numbers/route.ts +4 -1
- package/src/modules/sales/api/quotes/accept/route.ts +5 -2
- package/src/modules/sales/api/quotes/convert/route.ts +4 -1
- package/src/modules/sales/api/quotes/public/[token]/route.ts +4 -1
- package/src/modules/sales/api/quotes/send/route.ts +4 -1
- package/src/modules/sales/api/returns/[id]/route.ts +4 -1
- package/src/modules/sales/api/settings/document-numbers/route.ts +5 -2
- package/src/modules/sales/api/settings/order-editing/route.ts +5 -2
- package/src/modules/sales/backend/sales/channels/[channelId]/edit/page.tsx +4 -1
- package/src/modules/sales/backend/sales/channels/offers/page.tsx +7 -4
- package/src/modules/sales/backend/sales/channels/page.tsx +5 -2
- package/src/modules/sales/backend/sales/documents/[id]/page.tsx +21 -18
- package/src/modules/sales/commands/documents.ts +5 -8
- package/src/modules/sales/commands/payments.ts +4 -1
- package/src/modules/sales/commands/shipments.ts +4 -2
- package/src/modules/sales/components/AdjustmentKindSettings.tsx +6 -3
- package/src/modules/sales/components/DocumentNumberSettings.tsx +5 -2
- package/src/modules/sales/components/OrderEditingSettings.tsx +5 -2
- package/src/modules/sales/components/PaymentMethodsSettings.tsx +6 -3
- package/src/modules/sales/components/ShippingMethodsSettings.tsx +6 -3
- package/src/modules/sales/components/StatusSettings.tsx +6 -3
- package/src/modules/sales/components/TaxRatesSettings.tsx +6 -3
- package/src/modules/sales/components/channels/ChannelOfferForm.tsx +17 -14
- package/src/modules/sales/components/channels/SalesChannelOffersPanel.tsx +5 -2
- package/src/modules/sales/components/documents/AddressesSection.tsx +6 -3
- package/src/modules/sales/components/documents/AdjustmentDialog.tsx +4 -1
- package/src/modules/sales/components/documents/AdjustmentsSection.tsx +6 -3
- package/src/modules/sales/components/documents/ItemsSection.tsx +7 -4
- package/src/modules/sales/components/documents/LineItemDialog.tsx +9 -6
- package/src/modules/sales/components/documents/PaymentDialog.tsx +6 -3
- package/src/modules/sales/components/documents/PaymentsSection.tsx +5 -2
- package/src/modules/sales/components/documents/SalesDocumentForm.tsx +15 -12
- package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +6 -3
- package/src/modules/sales/components/documents/ShipmentDialog.tsx +10 -7
- package/src/modules/sales/components/documents/ShipmentsSection.tsx +5 -2
- package/src/modules/sales/frontend/quote/[token]/page.tsx +5 -2
- package/src/modules/sales/seed/examples.ts +8 -9
- package/src/modules/sales/subscribers/quote-expiring-notification.ts +4 -1
- package/src/modules/sales/subscribers/reconcileOnAddressDelete.ts +4 -1
- package/src/modules/sales/subscribers/reconcileOnCompanyDelete.ts +4 -1
- package/src/modules/sales/subscribers/reconcileOnCustomerDelete.ts +4 -1
- package/src/modules/sales/widgets/dashboard/makeDashboardWidgetRoute.ts +6 -3
- package/src/modules/sales/widgets/dashboard/new-orders/widget.client.tsx +274 -271
- package/src/modules/sales/widgets/dashboard/new-quotes/widget.client.tsx +280 -277
- package/src/modules/shipping_carriers/api/tracking/route.ts +5 -1
- package/src/modules/shipping_carriers/api/webhook/[provider]/route.ts +4 -1
- package/src/modules/shipping_carriers/lib/shipping-service.ts +47 -22
- package/src/modules/shipping_carriers/lib/upstream-error-response.ts +4 -1
- package/src/modules/shipping_carriers/workers/webhook-processor.ts +4 -5
- package/src/modules/staff/api/comments.ts +4 -1
- package/src/modules/staff/api/leave-requests/accept/route.ts +4 -1
- package/src/modules/staff/api/leave-requests/reject/route.ts +4 -1
- package/src/modules/staff/api/team-members/assignable/route.ts +4 -1
- package/src/modules/staff/api/team-members/self/route.ts +5 -2
- package/src/modules/staff/api/team-members/tags/assign/route.ts +4 -1
- package/src/modules/staff/api/team-members/tags/unassign/route.ts +4 -1
- package/src/modules/staff/api/timesheets/my-projects/[projectId]/route.ts +4 -1
- package/src/modules/staff/api/timesheets/my-projects/route.ts +4 -1
- package/src/modules/staff/api/timesheets/projects/kpis/route.ts +4 -1
- package/src/modules/staff/api/timesheets/time-entries/[id]/segments/route.ts +4 -1
- package/src/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.ts +5 -2
- package/src/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.ts +5 -2
- package/src/modules/staff/api/timesheets/time-entries/bulk/route.ts +4 -1
- package/src/modules/staff/api/timesheets/time-entries/start-timer/route.ts +4 -1
- package/src/modules/staff/backend/staff/team-members/page.tsx +5 -2
- package/src/modules/staff/backend/staff/team-roles/page.tsx +5 -2
- package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +5 -2
- package/src/modules/staff/backend/staff/teams/page.tsx +5 -2
- package/src/modules/staff/backend/staff/timesheets/page.tsx +8 -5
- package/src/modules/staff/backend/staff/timesheets/projects/[id]/page.tsx +4 -1
- package/src/modules/staff/backend/staff/timesheets/projects/page.tsx +5 -2
- package/src/modules/staff/commands/timesheets-entries.ts +4 -1
- package/src/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.client.tsx +4 -1
- package/src/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.tsx +6 -3
- package/src/modules/sync_excel/api/import/route.ts +4 -1
- package/src/modules/translations/api/[entityType]/[entityId]/route.ts +6 -3
- package/src/modules/translations/api/get/locales.ts +4 -1
- package/src/modules/translations/api/put/locales.ts +4 -1
- package/src/modules/translations/components/TranslationManager.tsx +4 -1
- package/src/modules/translations/subscribers/cleanup.ts +4 -1
- package/src/modules/workflows/api/definitions/[id]/customize/route.ts +5 -2
- package/src/modules/workflows/api/definitions/[id]/reset-to-code/route.ts +5 -2
- package/src/modules/workflows/api/definitions/[id]/route.ts +7 -4
- package/src/modules/workflows/api/definitions/route.ts +5 -2
- package/src/modules/workflows/api/events/[id]/route.ts +4 -1
- package/src/modules/workflows/api/events/route.ts +4 -1
- package/src/modules/workflows/api/instances/[id]/advance/route.ts +4 -1
- package/src/modules/workflows/api/instances/[id]/cancel/route.ts +4 -1
- package/src/modules/workflows/api/instances/[id]/events/route.ts +4 -1
- package/src/modules/workflows/api/instances/[id]/retry/route.ts +4 -1
- package/src/modules/workflows/api/instances/[id]/route.ts +4 -1
- package/src/modules/workflows/api/instances/[id]/signal/route.ts +6 -7
- package/src/modules/workflows/api/instances/route.ts +6 -3
- package/src/modules/workflows/api/instances/validate-start/route.ts +4 -1
- package/src/modules/workflows/api/signals/route.ts +4 -1
- package/src/modules/workflows/api/tasks/[id]/claim/route.ts +4 -1
- package/src/modules/workflows/api/tasks/[id]/complete/route.ts +4 -1
- package/src/modules/workflows/api/tasks/[id]/route.ts +4 -1
- package/src/modules/workflows/api/tasks/route.ts +4 -1
- package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +5 -2
- package/src/modules/workflows/backend/instances/[id]/page.tsx +6 -3
- package/src/modules/workflows/backend/tasks/[id]/page.tsx +4 -1
- package/src/modules/workflows/components/BusinessRulesSelector.tsx +6 -3
- package/src/modules/workflows/components/WorkflowSelector.tsx +6 -3
- package/src/modules/workflows/components/fields/BusinessRuleConditionsEditor.tsx +4 -1
- package/src/modules/workflows/components/fields/StartPreConditionsEditor.tsx +4 -1
- package/src/modules/workflows/components/fields/WorkflowSelectorField.tsx +4 -1
- package/src/modules/workflows/frontend/checkout-demo/page.tsx +9 -7
- package/src/modules/workflows/lib/activity-executor.ts +26 -21
- package/src/modules/workflows/lib/activity-worker-handler.ts +9 -15
- package/src/modules/workflows/lib/code-registry.ts +8 -7
- package/src/modules/workflows/lib/compensation-handler.ts +5 -2
- package/src/modules/workflows/lib/edgeFormTransforms.ts +4 -1
- package/src/modules/workflows/lib/event-trigger-service.ts +6 -3
- package/src/modules/workflows/lib/nodeFormTransforms.ts +4 -1
- package/src/modules/workflows/lib/seeds.ts +17 -2
- package/src/modules/workflows/lib/signal-handler.ts +4 -1
- package/src/modules/workflows/lib/start-validator.ts +10 -3
- package/src/modules/workflows/lib/step-handler.ts +4 -1
- package/src/modules/workflows/lib/task-handler.ts +4 -1
- package/src/modules/workflows/lib/transition-handler.ts +6 -3
- package/src/modules/workflows/lib/workflow-executor.ts +28 -15
- package/src/modules/workflows/subscribers/event-trigger.ts +22 -24
- package/src/modules/workflows/subscribers/task-assigned-notification.ts +4 -1
- package/src/modules/workflows/workers/workflow-activities.worker.ts +31 -20
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/modules/communication_channels/setup.ts"],
|
|
4
|
-
"sourcesContent": ["import { createHash } from 'node:crypto'\nimport type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'\nimport { COMMUNICATION_CHANNELS_QUEUES } from './lib/queue'\n\ntype SchedulerServiceLike = {\n register: (registration: {\n id: string\n name: string\n scopeType: 'system' | 'organization' | 'tenant'\n organizationId?: string\n tenantId?: string\n scheduleType: 'cron' | 'interval'\n scheduleValue: string\n timezone?: string\n targetType: 'queue' | 'command'\n targetQueue?: string\n targetPayload?: unknown\n sourceType?: 'user' | 'module'\n sourceModule?: string\n isEnabled?: boolean\n description?: string\n }) => Promise<void>\n}\n\n/**\n * Tick interval in seconds. Default 60s per email integration spec\n * \u00A7 Hub Deltas \u2192 Delta 6 (scheduler mechanism).\n */\nconst POLL_TICK_INTERVAL_SECONDS = Math.max(\n 10,\n Number.parseInt(process.env.OM_HUB_POLL_SCHEDULER_TICK_SECONDS ?? '60', 10) || 60,\n)\n\n/**\n * `scheduled_jobs.id` is a uuid column, so a module-owned schedule's stable\n * registration key must be hashed into a uuid rather than used verbatim \u2014 this\n * keeps `schedulerService.register()` an idempotent upsert across re-runs of\n * seedDefaults instead of trying to insert a raw string into the uuid PK.\n */\nfunction stableScheduleUuid(stableKey: string): string {\n const hex = createHash('sha256').update(stableKey).digest('hex')\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`\n}\n\nfunction stablePollTickScheduleId(organizationId: string): string {\n return stableScheduleUuid(`communication_channels:poll-tick:${organizationId}`)\n}\n\nexport const setup: ModuleSetupConfig = {\n defaultRoleFeatures: {\n superadmin: [\n 'communication_channels.view',\n 'communication_channels.manage',\n 'communication_channels.react',\n 'communication_channels.assign',\n 'communication_channels.connect_user_channel',\n 'communication_channels.admin',\n 'communication_channels.channel.import_history',\n 'communication_channels.channel.push.manage',\n ],\n admin: [\n 'communication_channels.view',\n 'communication_channels.manage',\n 'communication_channels.react',\n 'communication_channels.assign',\n 'communication_channels.connect_user_channel',\n 'communication_channels.admin',\n 'communication_channels.channel.import_history',\n 'communication_channels.channel.push.manage',\n ],\n manager: [\n 'communication_channels.view',\n 'communication_channels.manage',\n 'communication_channels.react',\n 'communication_channels.assign',\n 'communication_channels.connect_user_channel',\n ],\n employee: [\n 'communication_channels.view',\n 'communication_channels.react',\n 'communication_channels.connect_user_channel',\n ],\n },\n\n async seedDefaults({ container, organizationId, tenantId }) {\n /**\n * Register the per-channel polling tick with `@open-mercato/scheduler`.\n *\n * Per email integration spec \u00A7 Hub Deltas \u2192 Delta 6: every\n * `POLL_TICK_INTERVAL_SECONDS` (default 60s), enqueue a single\n * `communication-channels-poll-tick` job that enumerates due channels and\n * fans out to the `communication-channels-poll` queue.\n *\n * The registration is per-organization (one tick row per org/tenant pair)\n * so multi-tenant deploys schedule independently. Skipped silently when the\n * scheduler module isn't enabled \u2014 keeps the hub usable in scheduler-less\n * test harnesses.\n */\n const cradle = container as { hasRegistration?: (name: string) => boolean }\n if (typeof cradle.hasRegistration !== 'function' || !cradle.hasRegistration('schedulerService')) {\n return\n }\n const schedulerService = container.resolve('schedulerService') as SchedulerServiceLike\n // Best-effort: a scheduler failure must not abort tenant initialization for\n // every other module (mirrors the ai_assistant setup pattern). The schedule\n // ids are deterministic uuids so re-runs upsert idempotently.\n try {\n await schedulerService.register({\n id: stablePollTickScheduleId(organizationId),\n name: 'Communication channels poll tick',\n description:\n `Enumerates active polling channels every ${POLL_TICK_INTERVAL_SECONDS}s and enqueues per-channel poll jobs.`,\n scopeType: 'organization',\n organizationId,\n tenantId,\n scheduleType: 'interval',\n scheduleValue: `${POLL_TICK_INTERVAL_SECONDS}s`,\n timezone: 'UTC',\n targetType: 'queue',\n targetQueue: COMMUNICATION_CHANNELS_QUEUES.pollTick,\n targetPayload: {\n scope: { tenantId, organizationId },\n },\n sourceType: 'module',\n sourceModule: 'communication_channels',\n isEnabled: true,\n })\n\n // Spec C \u00A7 Phase C4 \u2014 Gmail watch renewal cron, per-org so multi-tenant\n // deploys schedule independently.\n await schedulerService.register({\n id: stableScheduleUuid(`communication_channels:gmail-renew-watch:${organizationId}`),\n name: 'Gmail watch renewal',\n description:\n 'Daily 04:00 UTC. Re-issues gmail.users.watch for channels within OM_PUSH_RENEWAL_GMAIL_LEAD_HOURS of expiry.',\n scopeType: 'organization',\n organizationId,\n tenantId,\n scheduleType: 'cron',\n scheduleValue: '0 4 * * *',\n timezone: 'UTC',\n targetType: 'queue',\n targetQueue: COMMUNICATION_CHANNELS_QUEUES.gmailRenewWatch,\n targetPayload: { scope: { tenantId, organizationId } },\n sourceType: 'module',\n sourceModule: 'communication_channels',\n isEnabled: true,\n })\n } catch (error) {\n
|
|
5
|
-
"mappings": "AAAA,SAAS,kBAAkB;AAE3B,SAAS,qCAAqC;
|
|
4
|
+
"sourcesContent": ["import { createHash } from 'node:crypto'\nimport type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'\nimport { COMMUNICATION_CHANNELS_QUEUES } from './lib/queue'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('communication_channels')\n\ntype SchedulerServiceLike = {\n register: (registration: {\n id: string\n name: string\n scopeType: 'system' | 'organization' | 'tenant'\n organizationId?: string\n tenantId?: string\n scheduleType: 'cron' | 'interval'\n scheduleValue: string\n timezone?: string\n targetType: 'queue' | 'command'\n targetQueue?: string\n targetPayload?: unknown\n sourceType?: 'user' | 'module'\n sourceModule?: string\n isEnabled?: boolean\n description?: string\n }) => Promise<void>\n}\n\n/**\n * Tick interval in seconds. Default 60s per email integration spec\n * \u00A7 Hub Deltas \u2192 Delta 6 (scheduler mechanism).\n */\nconst POLL_TICK_INTERVAL_SECONDS = Math.max(\n 10,\n Number.parseInt(process.env.OM_HUB_POLL_SCHEDULER_TICK_SECONDS ?? '60', 10) || 60,\n)\n\n/**\n * `scheduled_jobs.id` is a uuid column, so a module-owned schedule's stable\n * registration key must be hashed into a uuid rather than used verbatim \u2014 this\n * keeps `schedulerService.register()` an idempotent upsert across re-runs of\n * seedDefaults instead of trying to insert a raw string into the uuid PK.\n */\nfunction stableScheduleUuid(stableKey: string): string {\n const hex = createHash('sha256').update(stableKey).digest('hex')\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`\n}\n\nfunction stablePollTickScheduleId(organizationId: string): string {\n return stableScheduleUuid(`communication_channels:poll-tick:${organizationId}`)\n}\n\nexport const setup: ModuleSetupConfig = {\n defaultRoleFeatures: {\n superadmin: [\n 'communication_channels.view',\n 'communication_channels.manage',\n 'communication_channels.react',\n 'communication_channels.assign',\n 'communication_channels.connect_user_channel',\n 'communication_channels.admin',\n 'communication_channels.channel.import_history',\n 'communication_channels.channel.push.manage',\n ],\n admin: [\n 'communication_channels.view',\n 'communication_channels.manage',\n 'communication_channels.react',\n 'communication_channels.assign',\n 'communication_channels.connect_user_channel',\n 'communication_channels.admin',\n 'communication_channels.channel.import_history',\n 'communication_channels.channel.push.manage',\n ],\n manager: [\n 'communication_channels.view',\n 'communication_channels.manage',\n 'communication_channels.react',\n 'communication_channels.assign',\n 'communication_channels.connect_user_channel',\n ],\n employee: [\n 'communication_channels.view',\n 'communication_channels.react',\n 'communication_channels.connect_user_channel',\n ],\n },\n\n async seedDefaults({ container, organizationId, tenantId }) {\n /**\n * Register the per-channel polling tick with `@open-mercato/scheduler`.\n *\n * Per email integration spec \u00A7 Hub Deltas \u2192 Delta 6: every\n * `POLL_TICK_INTERVAL_SECONDS` (default 60s), enqueue a single\n * `communication-channels-poll-tick` job that enumerates due channels and\n * fans out to the `communication-channels-poll` queue.\n *\n * The registration is per-organization (one tick row per org/tenant pair)\n * so multi-tenant deploys schedule independently. Skipped silently when the\n * scheduler module isn't enabled \u2014 keeps the hub usable in scheduler-less\n * test harnesses.\n */\n const cradle = container as { hasRegistration?: (name: string) => boolean }\n if (typeof cradle.hasRegistration !== 'function' || !cradle.hasRegistration('schedulerService')) {\n return\n }\n const schedulerService = container.resolve('schedulerService') as SchedulerServiceLike\n // Best-effort: a scheduler failure must not abort tenant initialization for\n // every other module (mirrors the ai_assistant setup pattern). The schedule\n // ids are deterministic uuids so re-runs upsert idempotently.\n try {\n await schedulerService.register({\n id: stablePollTickScheduleId(organizationId),\n name: 'Communication channels poll tick',\n description:\n `Enumerates active polling channels every ${POLL_TICK_INTERVAL_SECONDS}s and enqueues per-channel poll jobs.`,\n scopeType: 'organization',\n organizationId,\n tenantId,\n scheduleType: 'interval',\n scheduleValue: `${POLL_TICK_INTERVAL_SECONDS}s`,\n timezone: 'UTC',\n targetType: 'queue',\n targetQueue: COMMUNICATION_CHANNELS_QUEUES.pollTick,\n targetPayload: {\n scope: { tenantId, organizationId },\n },\n sourceType: 'module',\n sourceModule: 'communication_channels',\n isEnabled: true,\n })\n\n // Spec C \u00A7 Phase C4 \u2014 Gmail watch renewal cron, per-org so multi-tenant\n // deploys schedule independently.\n await schedulerService.register({\n id: stableScheduleUuid(`communication_channels:gmail-renew-watch:${organizationId}`),\n name: 'Gmail watch renewal',\n description:\n 'Daily 04:00 UTC. Re-issues gmail.users.watch for channels within OM_PUSH_RENEWAL_GMAIL_LEAD_HOURS of expiry.',\n scopeType: 'organization',\n organizationId,\n tenantId,\n scheduleType: 'cron',\n scheduleValue: '0 4 * * *',\n timezone: 'UTC',\n targetType: 'queue',\n targetQueue: COMMUNICATION_CHANNELS_QUEUES.gmailRenewWatch,\n targetPayload: { scope: { tenantId, organizationId } },\n sourceType: 'module',\n sourceModule: 'communication_channels',\n isEnabled: true,\n })\n } catch (error) {\n logger.warn('Failed to register module schedules', { err: error })\n }\n },\n}\n\nexport default setup\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,kBAAkB;AAE3B,SAAS,qCAAqC;AAC9C,SAAS,oBAAoB;AAE7B,MAAM,SAAS,aAAa,wBAAwB;AA0BpD,MAAM,6BAA6B,KAAK;AAAA,EACtC;AAAA,EACA,OAAO,SAAS,QAAQ,IAAI,sCAAsC,MAAM,EAAE,KAAK;AACjF;AAQA,SAAS,mBAAmB,WAA2B;AACrD,QAAM,MAAM,WAAW,QAAQ,EAAE,OAAO,SAAS,EAAE,OAAO,KAAK;AAC/D,SAAO,GAAG,IAAI,MAAM,GAAG,CAAC,CAAC,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC;AAC9G;AAEA,SAAS,yBAAyB,gBAAgC;AAChE,SAAO,mBAAmB,oCAAoC,cAAc,EAAE;AAChF;AAEO,MAAM,QAA2B;AAAA,EACtC,qBAAqB;AAAA,IACnB,YAAY;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,UAAU;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,aAAa,EAAE,WAAW,gBAAgB,SAAS,GAAG;AAc1D,UAAM,SAAS;AACf,QAAI,OAAO,OAAO,oBAAoB,cAAc,CAAC,OAAO,gBAAgB,kBAAkB,GAAG;AAC/F;AAAA,IACF;AACA,UAAM,mBAAmB,UAAU,QAAQ,kBAAkB;AAI7D,QAAI;AACF,YAAM,iBAAiB,SAAS;AAAA,QAC9B,IAAI,yBAAyB,cAAc;AAAA,QAC3C,MAAM;AAAA,QACN,aACE,4CAA4C,0BAA0B;AAAA,QACxE,WAAW;AAAA,QACX;AAAA,QACA;AAAA,QACA,cAAc;AAAA,QACd,eAAe,GAAG,0BAA0B;AAAA,QAC5C,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,aAAa,8BAA8B;AAAA,QAC3C,eAAe;AAAA,UACb,OAAO,EAAE,UAAU,eAAe;AAAA,QACpC;AAAA,QACA,YAAY;AAAA,QACZ,cAAc;AAAA,QACd,WAAW;AAAA,MACb,CAAC;AAID,YAAM,iBAAiB,SAAS;AAAA,QAC9B,IAAI,mBAAmB,4CAA4C,cAAc,EAAE;AAAA,QACnF,MAAM;AAAA,QACN,aACE;AAAA,QACF,WAAW;AAAA,QACX;AAAA,QACA;AAAA,QACA,cAAc;AAAA,QACd,eAAe;AAAA,QACf,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,aAAa,8BAA8B;AAAA,QAC3C,eAAe,EAAE,OAAO,EAAE,UAAU,eAAe,EAAE;AAAA,QACrD,YAAY;AAAA,QACZ,cAAc;AAAA,QACd,WAAW;AAAA,MACb,CAAC;AAAA,IACH,SAAS,OAAO;AACd,aAAO,KAAK,uCAAuC,EAAE,KAAK,MAAM,CAAC;AAAA,IACnE;AAAA,EACF;AACF;AAEA,IAAO,gBAAQ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -6,6 +6,8 @@ import {
|
|
|
6
6
|
import { COMMUNICATION_CHANNELS_QUEUES } from "../lib/queue.js";
|
|
7
7
|
import { refreshCredentialsIfNeeded } from "../lib/credential-refresh.js";
|
|
8
8
|
import { classifyOutboundError } from "../lib/error-classification.js";
|
|
9
|
+
import { createLogger } from "@open-mercato/shared/lib/logger";
|
|
10
|
+
const logger = createLogger("communication_channels").child({ component: "channel-import-history" });
|
|
9
11
|
const metadata = {
|
|
10
12
|
queue: COMMUNICATION_CHANNELS_QUEUES.importHistory,
|
|
11
13
|
id: "communication_channels:channel-import-history",
|
|
@@ -141,9 +143,7 @@ async function handle(job, ctx) {
|
|
|
141
143
|
if (classification.transient) {
|
|
142
144
|
throw err;
|
|
143
145
|
}
|
|
144
|
-
|
|
145
|
-
`[communication_channels:channel-import-history] permanent ingest failure on channel ${channel.id}; skipping message ${message.externalMessageId}. Reason: ${classification.message}`
|
|
146
|
-
);
|
|
146
|
+
logger.warn("permanent ingest failure; skipping message", { channelId: channel.id, externalMessageId: message.externalMessageId, reason: classification.message });
|
|
147
147
|
}
|
|
148
148
|
processedCount += 1;
|
|
149
149
|
}
|
|
@@ -171,9 +171,7 @@ async function handle(job, ctx) {
|
|
|
171
171
|
progressContext
|
|
172
172
|
);
|
|
173
173
|
} catch (failErr) {
|
|
174
|
-
|
|
175
|
-
`[communication_channels:channel-import-history] failed to mark progress job ${progressJobId} as failed: ${failErr instanceof Error ? failErr.message : String(failErr)}`
|
|
176
|
-
);
|
|
174
|
+
logger.error("failed to mark progress job as failed", { progressJobId, err: failErr });
|
|
177
175
|
}
|
|
178
176
|
throw err;
|
|
179
177
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/communication_channels/workers/channel-import-history.ts"],
|
|
4
|
-
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport type { JobContext, QueuedJob, WorkerMeta } from '@open-mercato/queue'\nimport type { CommandBus } from '@open-mercato/shared/lib/commands'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { CommunicationChannel } from '../data/entities'\nimport {\n COMMUNICATION_CHANNELS_INGEST_INBOUND_COMMAND_ID,\n type IngestInboundMessageInput,\n} from '../commands/ingest-inbound-message'\nimport { COMMUNICATION_CHANNELS_QUEUES } from '../lib/queue'\nimport { refreshCredentialsIfNeeded } from '../lib/credential-refresh'\nimport { classifyOutboundError } from '../lib/error-classification'\nimport type { ChannelAdapterRegistry } from '../lib/registry'\nimport type {\n ChannelImportHistoryJobPayload,\n} from '../commands/queue-import-history'\nimport type {\n ProgressService,\n ProgressServiceContext,\n} from '../../progress/lib/progressService'\n\n/**\n * Spec B \u00A7 Phase B6 \u2014 operator-triggered backlog import worker.\n *\n * Distinct from `poll-channel` (which runs every scheduler tick and ingests\n * *new* mail since the channel cursor). This worker reaches backward in time\n * by calling `adapter.importHistory` with explicit `sinceDays` / `contactEmails`\n * filters, paginating until the adapter signals `hasMore: false` or the\n * `maxMessages` cap is reached.\n *\n * Runs with `concurrency: 1` to avoid hammering the provider with multiple\n * historical sweeps in parallel; per-channel concurrency is additionally\n * enforced at enqueue time by `queueImportHistory`.\n */\nexport const metadata: WorkerMeta = {\n queue: COMMUNICATION_CHANNELS_QUEUES.importHistory,\n id: 'communication_channels:channel-import-history',\n concurrency: 1,\n}\n\ntype HandlerContext = JobContext & {\n resolve: <T = unknown>(name: string) => T\n}\n\ntype CredentialsServiceLike = {\n resolve: (\n integrationId: string,\n scope: { organizationId: string; tenantId: string; userId?: string | null },\n ) => Promise<Record<string, unknown> | null>\n save?: (\n integrationId: string,\n credentials: Record<string, unknown>,\n scope: { organizationId: string; tenantId: string; userId?: string | null },\n ) => Promise<void>\n}\n\nexport default async function handle(\n job: QueuedJob<ChannelImportHistoryJobPayload>,\n ctx: HandlerContext,\n): Promise<void> {\n const payload = job.payload\n const { progressJobId, channelId, sinceDays, contactEmails, maxMessages, scope } = payload\n\n const progressService = ctx.resolve<ProgressService>('progressService')\n const progressContext: ProgressServiceContext = {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n }\n\n const em = (ctx.resolve('em') as EntityManager).fork()\n const adapterRegistry = ctx.resolve<ChannelAdapterRegistry>('channelAdapterRegistry')\n\n try {\n await progressService.startJob(progressJobId, progressContext)\n\n const channel = await findOneWithDecryption(\n em,\n CommunicationChannel,\n {\n id: channelId,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n if (!channel) {\n await progressService.failJob(\n progressJobId,\n { errorMessage: 'Channel not found' },\n progressContext,\n )\n return\n }\n if (!channel.isActive || channel.status !== 'connected') {\n await progressService.failJob(\n progressJobId,\n { errorMessage: `Channel is not connected (status=${channel.status})` },\n progressContext,\n )\n return\n }\n\n const adapter = adapterRegistry?.get(channel.providerKey)\n if (!adapter || typeof adapter.importHistory !== 'function') {\n await progressService.failJob(\n progressJobId,\n {\n errorMessage: `Provider \"${channel.providerKey}\" does not support history import`,\n },\n progressContext,\n )\n return\n }\n\n // Resolve + refresh credentials. Same flow as poll-channel.\n let credentialsService: CredentialsServiceLike | null = null\n try {\n credentialsService = ctx.resolve<CredentialsServiceLike>('integrationCredentialsService')\n } catch {\n credentialsService = null\n }\n const credentialsScope = {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n userId: channel.userId ?? null,\n }\n let credentials: Record<string, unknown> = {}\n if (channel.credentialsRef && credentialsService) {\n try {\n credentials =\n (await credentialsService.resolve(`channel_${channel.providerKey}`, credentialsScope)) ?? {}\n } catch {\n credentials = {}\n }\n }\n const refreshed = await refreshCredentialsIfNeeded(\n { adapter, channelId: channel.id, credentials, scope: credentialsScope },\n { credentialsService },\n )\n credentials = refreshed.credentials\n\n const commandBus = ctx.resolve<CommandBus>('commandBus')\n const containerProxy = { resolve: ctx.resolve.bind(ctx) }\n const commandCtx = {\n container: containerProxy as never,\n auth: null,\n organizationScope: null,\n selectedOrganizationId: scope.organizationId,\n organizationIds: [scope.organizationId],\n }\n\n let cursor: string | undefined\n let processedCount = 0\n let totalCount = maxMessages\n let firstPage = true\n\n // Bounded loop guards against a misbehaving adapter (infinite hasMore).\n // 100 pages * HARD_CAP (default 200) = 20k messages \u2014 far above the 5k cap\n // enforced by the schema, so this only trips on adapter bugs.\n const MAX_PAGES = 100\n for (let pageIndex = 0; pageIndex < MAX_PAGES; pageIndex += 1) {\n if (await progressService.isCancellationRequested(progressJobId, scope.tenantId, scope.organizationId)) {\n await progressService.markCancelled(progressJobId, progressContext)\n return\n }\n\n const page = await adapter.importHistory!({\n credentials,\n scope: { tenantId: scope.tenantId, organizationId: scope.organizationId },\n sinceDays,\n contactEmails,\n maxMessages,\n cursor,\n })\n\n if (firstPage && typeof page.totalCandidates === 'number') {\n totalCount = Math.min(maxMessages, page.totalCandidates)\n await progressService.updateProgress(\n progressJobId,\n { totalCount, processedCount: 0 },\n progressContext,\n )\n firstPage = false\n }\n\n for (const message of page.messages) {\n if (processedCount >= maxMessages) break\n try {\n const input: IngestInboundMessageInput = {\n channelId: channel.id,\n providerKey: channel.providerKey,\n channelType: channel.channelType,\n scope: { tenantId: scope.tenantId, organizationId: scope.organizationId },\n message,\n }\n await commandBus.execute(COMMUNICATION_CHANNELS_INGEST_INBOUND_COMMAND_ID, {\n input,\n ctx: commandCtx as never,\n })\n } catch (err) {\n // Import-history is best-effort per-message. Same classification\n // logic as poll-channel: a transient failure aborts the whole job\n // (the operator can retry), permanent failures are logged and\n // skipped (the bad message would loop forever otherwise).\n const classification = classifyOutboundError(err)\n if (classification.transient) {\n throw err\n }\n
|
|
5
|
-
"mappings": "AAGA,SAAS,6BAA6B;AACtC,SAAS,4BAA4B;AACrC;AAAA,EACE;AAAA,OAEK;AACP,SAAS,qCAAqC;AAC9C,SAAS,kCAAkC;AAC3C,SAAS,6BAA6B;
|
|
4
|
+
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport type { JobContext, QueuedJob, WorkerMeta } from '@open-mercato/queue'\nimport type { CommandBus } from '@open-mercato/shared/lib/commands'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { CommunicationChannel } from '../data/entities'\nimport {\n COMMUNICATION_CHANNELS_INGEST_INBOUND_COMMAND_ID,\n type IngestInboundMessageInput,\n} from '../commands/ingest-inbound-message'\nimport { COMMUNICATION_CHANNELS_QUEUES } from '../lib/queue'\nimport { refreshCredentialsIfNeeded } from '../lib/credential-refresh'\nimport { classifyOutboundError } from '../lib/error-classification'\nimport type { ChannelAdapterRegistry } from '../lib/registry'\nimport type {\n ChannelImportHistoryJobPayload,\n} from '../commands/queue-import-history'\nimport type {\n ProgressService,\n ProgressServiceContext,\n} from '../../progress/lib/progressService'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('communication_channels').child({ component: 'channel-import-history' })\n\n/**\n * Spec B \u00A7 Phase B6 \u2014 operator-triggered backlog import worker.\n *\n * Distinct from `poll-channel` (which runs every scheduler tick and ingests\n * *new* mail since the channel cursor). This worker reaches backward in time\n * by calling `adapter.importHistory` with explicit `sinceDays` / `contactEmails`\n * filters, paginating until the adapter signals `hasMore: false` or the\n * `maxMessages` cap is reached.\n *\n * Runs with `concurrency: 1` to avoid hammering the provider with multiple\n * historical sweeps in parallel; per-channel concurrency is additionally\n * enforced at enqueue time by `queueImportHistory`.\n */\nexport const metadata: WorkerMeta = {\n queue: COMMUNICATION_CHANNELS_QUEUES.importHistory,\n id: 'communication_channels:channel-import-history',\n concurrency: 1,\n}\n\ntype HandlerContext = JobContext & {\n resolve: <T = unknown>(name: string) => T\n}\n\ntype CredentialsServiceLike = {\n resolve: (\n integrationId: string,\n scope: { organizationId: string; tenantId: string; userId?: string | null },\n ) => Promise<Record<string, unknown> | null>\n save?: (\n integrationId: string,\n credentials: Record<string, unknown>,\n scope: { organizationId: string; tenantId: string; userId?: string | null },\n ) => Promise<void>\n}\n\nexport default async function handle(\n job: QueuedJob<ChannelImportHistoryJobPayload>,\n ctx: HandlerContext,\n): Promise<void> {\n const payload = job.payload\n const { progressJobId, channelId, sinceDays, contactEmails, maxMessages, scope } = payload\n\n const progressService = ctx.resolve<ProgressService>('progressService')\n const progressContext: ProgressServiceContext = {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n }\n\n const em = (ctx.resolve('em') as EntityManager).fork()\n const adapterRegistry = ctx.resolve<ChannelAdapterRegistry>('channelAdapterRegistry')\n\n try {\n await progressService.startJob(progressJobId, progressContext)\n\n const channel = await findOneWithDecryption(\n em,\n CommunicationChannel,\n {\n id: channelId,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n if (!channel) {\n await progressService.failJob(\n progressJobId,\n { errorMessage: 'Channel not found' },\n progressContext,\n )\n return\n }\n if (!channel.isActive || channel.status !== 'connected') {\n await progressService.failJob(\n progressJobId,\n { errorMessage: `Channel is not connected (status=${channel.status})` },\n progressContext,\n )\n return\n }\n\n const adapter = adapterRegistry?.get(channel.providerKey)\n if (!adapter || typeof adapter.importHistory !== 'function') {\n await progressService.failJob(\n progressJobId,\n {\n errorMessage: `Provider \"${channel.providerKey}\" does not support history import`,\n },\n progressContext,\n )\n return\n }\n\n // Resolve + refresh credentials. Same flow as poll-channel.\n let credentialsService: CredentialsServiceLike | null = null\n try {\n credentialsService = ctx.resolve<CredentialsServiceLike>('integrationCredentialsService')\n } catch {\n credentialsService = null\n }\n const credentialsScope = {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n userId: channel.userId ?? null,\n }\n let credentials: Record<string, unknown> = {}\n if (channel.credentialsRef && credentialsService) {\n try {\n credentials =\n (await credentialsService.resolve(`channel_${channel.providerKey}`, credentialsScope)) ?? {}\n } catch {\n credentials = {}\n }\n }\n const refreshed = await refreshCredentialsIfNeeded(\n { adapter, channelId: channel.id, credentials, scope: credentialsScope },\n { credentialsService },\n )\n credentials = refreshed.credentials\n\n const commandBus = ctx.resolve<CommandBus>('commandBus')\n const containerProxy = { resolve: ctx.resolve.bind(ctx) }\n const commandCtx = {\n container: containerProxy as never,\n auth: null,\n organizationScope: null,\n selectedOrganizationId: scope.organizationId,\n organizationIds: [scope.organizationId],\n }\n\n let cursor: string | undefined\n let processedCount = 0\n let totalCount = maxMessages\n let firstPage = true\n\n // Bounded loop guards against a misbehaving adapter (infinite hasMore).\n // 100 pages * HARD_CAP (default 200) = 20k messages \u2014 far above the 5k cap\n // enforced by the schema, so this only trips on adapter bugs.\n const MAX_PAGES = 100\n for (let pageIndex = 0; pageIndex < MAX_PAGES; pageIndex += 1) {\n if (await progressService.isCancellationRequested(progressJobId, scope.tenantId, scope.organizationId)) {\n await progressService.markCancelled(progressJobId, progressContext)\n return\n }\n\n const page = await adapter.importHistory!({\n credentials,\n scope: { tenantId: scope.tenantId, organizationId: scope.organizationId },\n sinceDays,\n contactEmails,\n maxMessages,\n cursor,\n })\n\n if (firstPage && typeof page.totalCandidates === 'number') {\n totalCount = Math.min(maxMessages, page.totalCandidates)\n await progressService.updateProgress(\n progressJobId,\n { totalCount, processedCount: 0 },\n progressContext,\n )\n firstPage = false\n }\n\n for (const message of page.messages) {\n if (processedCount >= maxMessages) break\n try {\n const input: IngestInboundMessageInput = {\n channelId: channel.id,\n providerKey: channel.providerKey,\n channelType: channel.channelType,\n scope: { tenantId: scope.tenantId, organizationId: scope.organizationId },\n message,\n }\n await commandBus.execute(COMMUNICATION_CHANNELS_INGEST_INBOUND_COMMAND_ID, {\n input,\n ctx: commandCtx as never,\n })\n } catch (err) {\n // Import-history is best-effort per-message. Same classification\n // logic as poll-channel: a transient failure aborts the whole job\n // (the operator can retry), permanent failures are logged and\n // skipped (the bad message would loop forever otherwise).\n const classification = classifyOutboundError(err)\n if (classification.transient) {\n throw err\n }\n logger.warn('permanent ingest failure; skipping message', { channelId: channel.id, externalMessageId: message.externalMessageId, reason: classification.message })\n }\n processedCount += 1\n }\n\n await progressService.updateProgress(\n progressJobId,\n { processedCount, totalCount },\n progressContext,\n )\n\n if (processedCount >= maxMessages) break\n if (!page.hasMore || !page.nextCursor) break\n cursor = page.nextCursor\n }\n\n await progressService.completeJob(\n progressJobId,\n { resultSummary: { importedCount: processedCount, channelId } },\n progressContext,\n )\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Import history job failed'\n const stack = err instanceof Error ? err.stack : undefined\n try {\n await progressService.failJob(\n progressJobId,\n { errorMessage: message.slice(0, 2000), errorStack: stack?.slice(0, 10000) },\n progressContext,\n )\n } catch (failErr) {\n logger.error('failed to mark progress job as failed', { progressJobId, err: failErr })\n }\n throw err\n }\n}\n"],
|
|
5
|
+
"mappings": "AAGA,SAAS,6BAA6B;AACtC,SAAS,4BAA4B;AACrC;AAAA,EACE;AAAA,OAEK;AACP,SAAS,qCAAqC;AAC9C,SAAS,kCAAkC;AAC3C,SAAS,6BAA6B;AAStC,SAAS,oBAAoB;AAE7B,MAAM,SAAS,aAAa,wBAAwB,EAAE,MAAM,EAAE,WAAW,yBAAyB,CAAC;AAe5F,MAAM,WAAuB;AAAA,EAClC,OAAO,8BAA8B;AAAA,EACrC,IAAI;AAAA,EACJ,aAAa;AACf;AAkBA,eAAO,OACL,KACA,KACe;AACf,QAAM,UAAU,IAAI;AACpB,QAAM,EAAE,eAAe,WAAW,WAAW,eAAe,aAAa,MAAM,IAAI;AAEnF,QAAM,kBAAkB,IAAI,QAAyB,iBAAiB;AACtE,QAAM,kBAA0C;AAAA,IAC9C,UAAU,MAAM;AAAA,IAChB,gBAAgB,MAAM;AAAA,EACxB;AAEA,QAAM,KAAM,IAAI,QAAQ,IAAI,EAAoB,KAAK;AACrD,QAAM,kBAAkB,IAAI,QAAgC,wBAAwB;AAEpF,MAAI;AACF,UAAM,gBAAgB,SAAS,eAAe,eAAe;AAE7D,UAAM,UAAU,MAAM;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,UAAU,MAAM;AAAA,QAChB,gBAAgB,MAAM;AAAA,QACtB,WAAW;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,QAAI,CAAC,SAAS;AACZ,YAAM,gBAAgB;AAAA,QACpB;AAAA,QACA,EAAE,cAAc,oBAAoB;AAAA,QACpC;AAAA,MACF;AACA;AAAA,IACF;AACA,QAAI,CAAC,QAAQ,YAAY,QAAQ,WAAW,aAAa;AACvD,YAAM,gBAAgB;AAAA,QACpB;AAAA,QACA,EAAE,cAAc,oCAAoC,QAAQ,MAAM,IAAI;AAAA,QACtE;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,UAAU,iBAAiB,IAAI,QAAQ,WAAW;AACxD,QAAI,CAAC,WAAW,OAAO,QAAQ,kBAAkB,YAAY;AAC3D,YAAM,gBAAgB;AAAA,QACpB;AAAA,QACA;AAAA,UACE,cAAc,aAAa,QAAQ,WAAW;AAAA,QAChD;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAGA,QAAI,qBAAoD;AACxD,QAAI;AACF,2BAAqB,IAAI,QAAgC,+BAA+B;AAAA,IAC1F,QAAQ;AACN,2BAAqB;AAAA,IACvB;AACA,UAAM,mBAAmB;AAAA,MACvB,UAAU,MAAM;AAAA,MAChB,gBAAgB,MAAM;AAAA,MACtB,QAAQ,QAAQ,UAAU;AAAA,IAC5B;AACA,QAAI,cAAuC,CAAC;AAC5C,QAAI,QAAQ,kBAAkB,oBAAoB;AAChD,UAAI;AACF,sBACG,MAAM,mBAAmB,QAAQ,WAAW,QAAQ,WAAW,IAAI,gBAAgB,KAAM,CAAC;AAAA,MAC/F,QAAQ;AACN,sBAAc,CAAC;AAAA,MACjB;AAAA,IACF;AACA,UAAM,YAAY,MAAM;AAAA,MACtB,EAAE,SAAS,WAAW,QAAQ,IAAI,aAAa,OAAO,iBAAiB;AAAA,MACvE,EAAE,mBAAmB;AAAA,IACvB;AACA,kBAAc,UAAU;AAExB,UAAM,aAAa,IAAI,QAAoB,YAAY;AACvD,UAAM,iBAAiB,EAAE,SAAS,IAAI,QAAQ,KAAK,GAAG,EAAE;AACxD,UAAM,aAAa;AAAA,MACjB,WAAW;AAAA,MACX,MAAM;AAAA,MACN,mBAAmB;AAAA,MACnB,wBAAwB,MAAM;AAAA,MAC9B,iBAAiB,CAAC,MAAM,cAAc;AAAA,IACxC;AAEA,QAAI;AACJ,QAAI,iBAAiB;AACrB,QAAI,aAAa;AACjB,QAAI,YAAY;AAKhB,UAAM,YAAY;AAClB,aAAS,YAAY,GAAG,YAAY,WAAW,aAAa,GAAG;AAC7D,UAAI,MAAM,gBAAgB,wBAAwB,eAAe,MAAM,UAAU,MAAM,cAAc,GAAG;AACtG,cAAM,gBAAgB,cAAc,eAAe,eAAe;AAClE;AAAA,MACF;AAEA,YAAM,OAAO,MAAM,QAAQ,cAAe;AAAA,QACxC;AAAA,QACA,OAAO,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,eAAe;AAAA,QACxE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAED,UAAI,aAAa,OAAO,KAAK,oBAAoB,UAAU;AACzD,qBAAa,KAAK,IAAI,aAAa,KAAK,eAAe;AACvD,cAAM,gBAAgB;AAAA,UACpB;AAAA,UACA,EAAE,YAAY,gBAAgB,EAAE;AAAA,UAChC;AAAA,QACF;AACA,oBAAY;AAAA,MACd;AAEA,iBAAW,WAAW,KAAK,UAAU;AACnC,YAAI,kBAAkB,YAAa;AACnC,YAAI;AACF,gBAAM,QAAmC;AAAA,YACvC,WAAW,QAAQ;AAAA,YACnB,aAAa,QAAQ;AAAA,YACrB,aAAa,QAAQ;AAAA,YACrB,OAAO,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,eAAe;AAAA,YACxE;AAAA,UACF;AACA,gBAAM,WAAW,QAAQ,kDAAkD;AAAA,YACzE;AAAA,YACA,KAAK;AAAA,UACP,CAAC;AAAA,QACH,SAAS,KAAK;AAKZ,gBAAM,iBAAiB,sBAAsB,GAAG;AAChD,cAAI,eAAe,WAAW;AAC5B,kBAAM;AAAA,UACR;AACA,iBAAO,KAAK,8CAA8C,EAAE,WAAW,QAAQ,IAAI,mBAAmB,QAAQ,mBAAmB,QAAQ,eAAe,QAAQ,CAAC;AAAA,QACnK;AACA,0BAAkB;AAAA,MACpB;AAEA,YAAM,gBAAgB;AAAA,QACpB;AAAA,QACA,EAAE,gBAAgB,WAAW;AAAA,QAC7B;AAAA,MACF;AAEA,UAAI,kBAAkB,YAAa;AACnC,UAAI,CAAC,KAAK,WAAW,CAAC,KAAK,WAAY;AACvC,eAAS,KAAK;AAAA,IAChB;AAEA,UAAM,gBAAgB;AAAA,MACpB;AAAA,MACA,EAAE,eAAe,EAAE,eAAe,gBAAgB,UAAU,EAAE;AAAA,MAC9D;AAAA,IACF;AAAA,EACF,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU;AACrD,UAAM,QAAQ,eAAe,QAAQ,IAAI,QAAQ;AACjD,QAAI;AACF,YAAM,gBAAgB;AAAA,QACpB;AAAA,QACA,EAAE,cAAc,QAAQ,MAAM,GAAG,GAAI,GAAG,YAAY,OAAO,MAAM,GAAG,GAAK,EAAE;AAAA,QAC3E;AAAA,MACF;AAAA,IACF,SAAS,SAAS;AAChB,aAAO,MAAM,yCAAyC,EAAE,eAAe,KAAK,QAAQ,CAAC;AAAA,IACvF;AACA,UAAM;AAAA,EACR;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -8,6 +8,8 @@ import { preservePushState } from "../lib/push-state.js";
|
|
|
8
8
|
import { refreshCredentialsIfNeeded } from "../lib/credential-refresh.js";
|
|
9
9
|
import { classifyOutboundError } from "../lib/error-classification.js";
|
|
10
10
|
import { writeIngestDeadLetter } from "../lib/dead-letter.js";
|
|
11
|
+
import { createLogger } from "@open-mercato/shared/lib/logger";
|
|
12
|
+
const logger = createLogger("communication_channels").child({ component: "gmail-history-sync" });
|
|
11
13
|
const MAX_DRAIN_PAGES = 100;
|
|
12
14
|
const metadata = {
|
|
13
15
|
queue: COMMUNICATION_CHANNELS_QUEUES.gmailHistorySync,
|
|
@@ -31,15 +33,13 @@ async function handle(job, ctx) {
|
|
|
31
33
|
scope
|
|
32
34
|
);
|
|
33
35
|
if (!channel) {
|
|
34
|
-
|
|
36
|
+
logger.warn("channel not found (skip)", { channelId });
|
|
35
37
|
return;
|
|
36
38
|
}
|
|
37
39
|
if (!channel.isActive || channel.status !== "connected") return;
|
|
38
40
|
const adapter = adapterRegistry?.get(channel.providerKey);
|
|
39
41
|
if (!adapter || typeof adapter.applyPushNotification !== "function") {
|
|
40
|
-
|
|
41
|
-
`[gmail-history-sync] adapter for '${channel.providerKey}' does not support applyPushNotification`
|
|
42
|
-
);
|
|
42
|
+
logger.warn("adapter does not support applyPushNotification", { providerKey: channel.providerKey });
|
|
43
43
|
return;
|
|
44
44
|
}
|
|
45
45
|
let credentialsService = null;
|
|
@@ -77,9 +77,7 @@ async function handle(job, ctx) {
|
|
|
77
77
|
} catch (err) {
|
|
78
78
|
const classification = classifyOutboundError(err);
|
|
79
79
|
if (classification.transient) throw err;
|
|
80
|
-
|
|
81
|
-
`[gmail-history-sync] permanent failure applying push for channel ${channel.id}: ${classification.message}`
|
|
82
|
-
);
|
|
80
|
+
logger.warn("permanent failure applying push for channel", { channelId: channel.id, reason: classification.message });
|
|
83
81
|
return;
|
|
84
82
|
}
|
|
85
83
|
const messages = Array.isArray(page?.messages) ? page.messages : [];
|
|
@@ -111,9 +109,7 @@ async function handle(job, ctx) {
|
|
|
111
109
|
if (classification.transient) {
|
|
112
110
|
throw err;
|
|
113
111
|
}
|
|
114
|
-
|
|
115
|
-
`[gmail-history-sync] permanent ingest failure for channel ${channel.id}: ${classification.message}`
|
|
116
|
-
);
|
|
112
|
+
logger.warn("permanent ingest failure for channel", { channelId: channel.id, reason: classification.message });
|
|
117
113
|
await writeIngestDeadLetter({ em, scope, channel, message, err, errorMessage: classification.message });
|
|
118
114
|
}
|
|
119
115
|
}
|
|
@@ -125,9 +121,7 @@ async function handle(job, ctx) {
|
|
|
125
121
|
channel.lastPolledAt = /* @__PURE__ */ new Date();
|
|
126
122
|
await em.flush();
|
|
127
123
|
} catch (err) {
|
|
128
|
-
|
|
129
|
-
`[gmail-history-sync] failed to persist next cursor for channel ${channel.id}: ${err instanceof Error ? err.message : String(err)}`
|
|
130
|
-
);
|
|
124
|
+
logger.warn("failed to persist next cursor for channel", { channelId: channel.id, err });
|
|
131
125
|
}
|
|
132
126
|
}
|
|
133
127
|
if (page?.hasMore && page?.nextCursor) {
|
|
@@ -141,9 +135,7 @@ async function handle(job, ctx) {
|
|
|
141
135
|
{ delayMs: 250 }
|
|
142
136
|
);
|
|
143
137
|
} else {
|
|
144
|
-
|
|
145
|
-
`[gmail-history-sync] drain page cap (${MAX_DRAIN_PAGES}) reached for channel ${channelId}; stopping re-enqueue`
|
|
146
|
-
);
|
|
138
|
+
logger.warn("drain page cap reached; stopping re-enqueue", { maxDrainPages: MAX_DRAIN_PAGES, channelId });
|
|
147
139
|
}
|
|
148
140
|
}
|
|
149
141
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/communication_channels/workers/gmail-history-sync.ts"],
|
|
4
|
-
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport type { JobContext, QueuedJob, WorkerMeta } from '@open-mercato/queue'\nimport type { CommandBus } from '@open-mercato/shared/lib/commands'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { CommunicationChannel } from '../data/entities'\nimport {\n COMMUNICATION_CHANNELS_INGEST_INBOUND_COMMAND_ID,\n type IngestInboundMessageInput,\n} from '../commands/ingest-inbound-message'\nimport { COMMUNICATION_CHANNELS_QUEUES } from '../lib/queue'\nimport { preservePushState } from '../lib/push-state'\nimport { refreshCredentialsIfNeeded } from '../lib/credential-refresh'\nimport { classifyOutboundError } from '../lib/error-classification'\nimport { writeIngestDeadLetter } from '../lib/dead-letter'\nimport type { ChannelAdapterRegistry } from '../lib/registry'\n\n/**\n * Spec C \u00A7 Phase C2 \u2014 Gmail Pub/Sub push delivery worker.\n *\n * One job per verified webhook notification. Calls\n * `adapter.applyPushNotification(...)` to walk `users.history.list` from the\n * channel's stored `historyId`, then dispatches each message through\n * `ingest-inbound-message` (same path as the polling worker).\n *\n * Concurrency: bounded by the queue's default (10). Per-channel ordering is\n * NOT guaranteed across notifications \u2014 but the ingest command is idempotent\n * on `(channel_id, external_message_id)`, and Gmail's history cursor advances\n * monotonically per channel, so out-of-order replay is safe.\n */\nexport type GmailHistorySyncJobPayload = {\n channelId: string\n scope: { tenantId: string; organizationId: string | null }\n notification: { emailAddress: string; historyId: string }\n /** Self-re-enqueue drain counter (bounds the multi-page drain loop). */\n drainPage?: number\n}\n\n/** Hard cap on self-re-enqueue drain pages \u2014 guards against an adapter that\n * returns `hasMore` with a non-advancing cursor (a tight, unbounded loop). */\nconst MAX_DRAIN_PAGES = 100\n\nexport const metadata: WorkerMeta = {\n queue: COMMUNICATION_CHANNELS_QUEUES.gmailHistorySync,\n id: 'communication_channels:gmail-history-sync',\n concurrency: 5,\n}\n\ntype HandlerContext = JobContext & {\n resolve: <T = unknown>(name: string) => T\n}\n\ntype CredentialsServiceLike = {\n resolve: (\n integrationId: string,\n scope: { organizationId: string; tenantId: string; userId?: string | null },\n ) => Promise<Record<string, unknown> | null>\n save?: (\n integrationId: string,\n credentials: Record<string, unknown>,\n scope: { organizationId: string; tenantId: string; userId?: string | null },\n ) => Promise<void>\n}\n\nexport default async function handle(\n job: QueuedJob<GmailHistorySyncJobPayload>,\n ctx: HandlerContext,\n): Promise<void> {\n const { channelId, scope } = job.payload\n const em = (ctx.resolve('em') as EntityManager).fork()\n const adapterRegistry = ctx.resolve<ChannelAdapterRegistry>('channelAdapterRegistry')\n\n const channel = await findOneWithDecryption(\n em,\n CommunicationChannel,\n {\n id: channelId,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId ?? null,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n if (!channel) {\n
|
|
5
|
-
"mappings": "AAGA,SAAS,6BAA6B;AACtC,SAAS,4BAA4B;AACrC;AAAA,EACE;AAAA,OAEK;AACP,SAAS,qCAAqC;AAC9C,SAAS,yBAAyB;AAClC,SAAS,kCAAkC;AAC3C,SAAS,6BAA6B;AACtC,SAAS,6BAA6B;
|
|
4
|
+
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport type { JobContext, QueuedJob, WorkerMeta } from '@open-mercato/queue'\nimport type { CommandBus } from '@open-mercato/shared/lib/commands'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { CommunicationChannel } from '../data/entities'\nimport {\n COMMUNICATION_CHANNELS_INGEST_INBOUND_COMMAND_ID,\n type IngestInboundMessageInput,\n} from '../commands/ingest-inbound-message'\nimport { COMMUNICATION_CHANNELS_QUEUES } from '../lib/queue'\nimport { preservePushState } from '../lib/push-state'\nimport { refreshCredentialsIfNeeded } from '../lib/credential-refresh'\nimport { classifyOutboundError } from '../lib/error-classification'\nimport { writeIngestDeadLetter } from '../lib/dead-letter'\nimport type { ChannelAdapterRegistry } from '../lib/registry'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('communication_channels').child({ component: 'gmail-history-sync' })\n\n/**\n * Spec C \u00A7 Phase C2 \u2014 Gmail Pub/Sub push delivery worker.\n *\n * One job per verified webhook notification. Calls\n * `adapter.applyPushNotification(...)` to walk `users.history.list` from the\n * channel's stored `historyId`, then dispatches each message through\n * `ingest-inbound-message` (same path as the polling worker).\n *\n * Concurrency: bounded by the queue's default (10). Per-channel ordering is\n * NOT guaranteed across notifications \u2014 but the ingest command is idempotent\n * on `(channel_id, external_message_id)`, and Gmail's history cursor advances\n * monotonically per channel, so out-of-order replay is safe.\n */\nexport type GmailHistorySyncJobPayload = {\n channelId: string\n scope: { tenantId: string; organizationId: string | null }\n notification: { emailAddress: string; historyId: string }\n /** Self-re-enqueue drain counter (bounds the multi-page drain loop). */\n drainPage?: number\n}\n\n/** Hard cap on self-re-enqueue drain pages \u2014 guards against an adapter that\n * returns `hasMore` with a non-advancing cursor (a tight, unbounded loop). */\nconst MAX_DRAIN_PAGES = 100\n\nexport const metadata: WorkerMeta = {\n queue: COMMUNICATION_CHANNELS_QUEUES.gmailHistorySync,\n id: 'communication_channels:gmail-history-sync',\n concurrency: 5,\n}\n\ntype HandlerContext = JobContext & {\n resolve: <T = unknown>(name: string) => T\n}\n\ntype CredentialsServiceLike = {\n resolve: (\n integrationId: string,\n scope: { organizationId: string; tenantId: string; userId?: string | null },\n ) => Promise<Record<string, unknown> | null>\n save?: (\n integrationId: string,\n credentials: Record<string, unknown>,\n scope: { organizationId: string; tenantId: string; userId?: string | null },\n ) => Promise<void>\n}\n\nexport default async function handle(\n job: QueuedJob<GmailHistorySyncJobPayload>,\n ctx: HandlerContext,\n): Promise<void> {\n const { channelId, scope } = job.payload\n const em = (ctx.resolve('em') as EntityManager).fork()\n const adapterRegistry = ctx.resolve<ChannelAdapterRegistry>('channelAdapterRegistry')\n\n const channel = await findOneWithDecryption(\n em,\n CommunicationChannel,\n {\n id: channelId,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId ?? null,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n if (!channel) {\n logger.warn('channel not found (skip)', { channelId })\n return\n }\n if (!channel.isActive || channel.status !== 'connected') return\n\n const adapter = adapterRegistry?.get(channel.providerKey)\n if (!adapter || typeof adapter.applyPushNotification !== 'function') {\n logger.warn('adapter does not support applyPushNotification', { providerKey: channel.providerKey })\n return\n }\n\n let credentialsService: CredentialsServiceLike | null = null\n try {\n credentialsService = ctx.resolve<CredentialsServiceLike>('integrationCredentialsService')\n } catch {\n credentialsService = null\n }\n const credentialsScope = {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId ?? scope.tenantId,\n userId: channel.userId ?? null,\n }\n let credentials: Record<string, unknown> = {}\n if (channel.credentialsRef && credentialsService) {\n try {\n credentials =\n (await credentialsService.resolve(`channel_${channel.providerKey}`, credentialsScope)) ?? {}\n } catch {\n credentials = {}\n }\n }\n const refreshed = await refreshCredentialsIfNeeded(\n { adapter, channelId: channel.id, credentials, scope: credentialsScope },\n { credentialsService },\n )\n credentials = refreshed.credentials\n\n let page\n try {\n page = await adapter.applyPushNotification({\n credentials,\n scope: { tenantId: scope.tenantId, organizationId: scope.organizationId ?? scope.tenantId },\n channelState: (channel.channelState as Record<string, unknown> | null) ?? {},\n notification: job.payload.notification as unknown as Record<string, unknown>,\n })\n } catch (err) {\n const classification = classifyOutboundError(err)\n if (classification.transient) throw err\n logger.warn('permanent failure applying push for channel', { channelId: channel.id, reason: classification.message })\n return\n }\n\n const messages = Array.isArray(page?.messages) ? page.messages : []\n if (messages.length > 0) {\n const commandBus = ctx.resolve<CommandBus>('commandBus')\n const containerProxy = { resolve: ctx.resolve.bind(ctx) }\n const commandCtx = {\n container: containerProxy as never,\n auth: null,\n organizationScope: null,\n selectedOrganizationId: scope.organizationId ?? null,\n organizationIds: scope.organizationId ? [scope.organizationId] : null,\n }\n for (const message of messages) {\n try {\n const input: IngestInboundMessageInput = {\n channelId: channel.id,\n providerKey: channel.providerKey,\n channelType: channel.channelType,\n scope: { tenantId: scope.tenantId, organizationId: scope.organizationId ?? null },\n message,\n }\n await commandBus.execute(COMMUNICATION_CHANNELS_INGEST_INBOUND_COMMAND_ID, {\n input,\n ctx: commandCtx as never,\n })\n } catch (err) {\n const classification = classifyOutboundError(err)\n if (classification.transient) {\n // Per-message commit semantics from Spec B: re-throw so queue\n // retry re-runs from a safe point.\n throw err\n }\n logger.warn('permanent ingest failure for channel', { channelId: channel.id, reason: classification.message })\n await writeIngestDeadLetter({ em, scope, channel, message, err, errorMessage: classification.message })\n }\n }\n }\n\n // Persist the adapter's advanced cursor (encoded in nextCursor) back to\n // channel.channelState. fetchHistory's nextCursor is a base64-JSON blob\n // mirroring the new GmailChannelState \u2014 same as the polling worker writes.\n if (page?.nextCursor) {\n try {\n const decoded = JSON.parse(Buffer.from(page.nextCursor, 'base64').toString('utf-8')) as Record<string, unknown>\n // Carry the push keys forward via preservePushState rather than spreading\n // the decoded cursor wholesale: a blind spread would retain a stale\n // `pendingHistoryPageToken` after a completed drain and mis-route the next\n // push notification.\n channel.channelState = preservePushState(channel.channelState, decoded)\n channel.lastPolledAt = new Date()\n await em.flush()\n } catch (err) {\n logger.warn('failed to persist next cursor for channel', { channelId: channel.id, err })\n }\n }\n\n if (page?.hasMore && page?.nextCursor) {\n // Re-enqueue self so the drain continues. The Pub/Sub notification fired\n // once, but `history.list` may need multiple pages on a busy mailbox.\n // Bound the drain and add a small delay so an adapter that returns\n // `hasMore: true` with a non-advancing cursor cannot spin a tight,\n // unthrottled re-enqueue loop against the provider/queue.\n const drainPage = job.payload.drainPage ?? 0\n if (drainPage < MAX_DRAIN_PAGES) {\n const queue = (await import('../lib/queue')).getCommunicationChannelsQueue(\n COMMUNICATION_CHANNELS_QUEUES.gmailHistorySync,\n )\n await queue.enqueue(\n { ...job.payload, drainPage: drainPage + 1 } as unknown as Record<string, unknown>,\n { delayMs: 250 },\n )\n } else {\n logger.warn('drain page cap reached; stopping re-enqueue', { maxDrainPages: MAX_DRAIN_PAGES, channelId })\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "AAGA,SAAS,6BAA6B;AACtC,SAAS,4BAA4B;AACrC;AAAA,EACE;AAAA,OAEK;AACP,SAAS,qCAAqC;AAC9C,SAAS,yBAAyB;AAClC,SAAS,kCAAkC;AAC3C,SAAS,6BAA6B;AACtC,SAAS,6BAA6B;AAEtC,SAAS,oBAAoB;AAE7B,MAAM,SAAS,aAAa,wBAAwB,EAAE,MAAM,EAAE,WAAW,qBAAqB,CAAC;AAyB/F,MAAM,kBAAkB;AAEjB,MAAM,WAAuB;AAAA,EAClC,OAAO,8BAA8B;AAAA,EACrC,IAAI;AAAA,EACJ,aAAa;AACf;AAkBA,eAAO,OACL,KACA,KACe;AACf,QAAM,EAAE,WAAW,MAAM,IAAI,IAAI;AACjC,QAAM,KAAM,IAAI,QAAQ,IAAI,EAAoB,KAAK;AACrD,QAAM,kBAAkB,IAAI,QAAgC,wBAAwB;AAEpF,QAAM,UAAU,MAAM;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,UAAU,MAAM;AAAA,MAChB,gBAAgB,MAAM,kBAAkB;AAAA,MACxC,WAAW;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,MAAI,CAAC,SAAS;AACZ,WAAO,KAAK,4BAA4B,EAAE,UAAU,CAAC;AACrD;AAAA,EACF;AACA,MAAI,CAAC,QAAQ,YAAY,QAAQ,WAAW,YAAa;AAEzD,QAAM,UAAU,iBAAiB,IAAI,QAAQ,WAAW;AACxD,MAAI,CAAC,WAAW,OAAO,QAAQ,0BAA0B,YAAY;AACnE,WAAO,KAAK,kDAAkD,EAAE,aAAa,QAAQ,YAAY,CAAC;AAClG;AAAA,EACF;AAEA,MAAI,qBAAoD;AACxD,MAAI;AACF,yBAAqB,IAAI,QAAgC,+BAA+B;AAAA,EAC1F,QAAQ;AACN,yBAAqB;AAAA,EACvB;AACA,QAAM,mBAAmB;AAAA,IACvB,UAAU,MAAM;AAAA,IAChB,gBAAgB,MAAM,kBAAkB,MAAM;AAAA,IAC9C,QAAQ,QAAQ,UAAU;AAAA,EAC5B;AACA,MAAI,cAAuC,CAAC;AAC5C,MAAI,QAAQ,kBAAkB,oBAAoB;AAChD,QAAI;AACF,oBACG,MAAM,mBAAmB,QAAQ,WAAW,QAAQ,WAAW,IAAI,gBAAgB,KAAM,CAAC;AAAA,IAC/F,QAAQ;AACN,oBAAc,CAAC;AAAA,IACjB;AAAA,EACF;AACA,QAAM,YAAY,MAAM;AAAA,IACtB,EAAE,SAAS,WAAW,QAAQ,IAAI,aAAa,OAAO,iBAAiB;AAAA,IACvE,EAAE,mBAAmB;AAAA,EACvB;AACA,gBAAc,UAAU;AAExB,MAAI;AACJ,MAAI;AACF,WAAO,MAAM,QAAQ,sBAAsB;AAAA,MACzC;AAAA,MACA,OAAO,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,kBAAkB,MAAM,SAAS;AAAA,MAC1F,cAAe,QAAQ,gBAAmD,CAAC;AAAA,MAC3E,cAAc,IAAI,QAAQ;AAAA,IAC5B,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,UAAM,iBAAiB,sBAAsB,GAAG;AAChD,QAAI,eAAe,UAAW,OAAM;AACpC,WAAO,KAAK,+CAA+C,EAAE,WAAW,QAAQ,IAAI,QAAQ,eAAe,QAAQ,CAAC;AACpH;AAAA,EACF;AAEA,QAAM,WAAW,MAAM,QAAQ,MAAM,QAAQ,IAAI,KAAK,WAAW,CAAC;AAClE,MAAI,SAAS,SAAS,GAAG;AACvB,UAAM,aAAa,IAAI,QAAoB,YAAY;AACvD,UAAM,iBAAiB,EAAE,SAAS,IAAI,QAAQ,KAAK,GAAG,EAAE;AACxD,UAAM,aAAa;AAAA,MACjB,WAAW;AAAA,MACX,MAAM;AAAA,MACN,mBAAmB;AAAA,MACnB,wBAAwB,MAAM,kBAAkB;AAAA,MAChD,iBAAiB,MAAM,iBAAiB,CAAC,MAAM,cAAc,IAAI;AAAA,IACnE;AACA,eAAW,WAAW,UAAU;AAC9B,UAAI;AACF,cAAM,QAAmC;AAAA,UACvC,WAAW,QAAQ;AAAA,UACnB,aAAa,QAAQ;AAAA,UACrB,aAAa,QAAQ;AAAA,UACrB,OAAO,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,kBAAkB,KAAK;AAAA,UAChF;AAAA,QACF;AACA,cAAM,WAAW,QAAQ,kDAAkD;AAAA,UACzE;AAAA,UACA,KAAK;AAAA,QACP,CAAC;AAAA,MACH,SAAS,KAAK;AACZ,cAAM,iBAAiB,sBAAsB,GAAG;AAChD,YAAI,eAAe,WAAW;AAG5B,gBAAM;AAAA,QACR;AACA,eAAO,KAAK,wCAAwC,EAAE,WAAW,QAAQ,IAAI,QAAQ,eAAe,QAAQ,CAAC;AAC7G,cAAM,sBAAsB,EAAE,IAAI,OAAO,SAAS,SAAS,KAAK,cAAc,eAAe,QAAQ,CAAC;AAAA,MACxG;AAAA,IACF;AAAA,EACF;AAKA,MAAI,MAAM,YAAY;AACpB,QAAI;AACF,YAAM,UAAU,KAAK,MAAM,OAAO,KAAK,KAAK,YAAY,QAAQ,EAAE,SAAS,OAAO,CAAC;AAKnF,cAAQ,eAAe,kBAAkB,QAAQ,cAAc,OAAO;AACtE,cAAQ,eAAe,oBAAI,KAAK;AAChC,YAAM,GAAG,MAAM;AAAA,IACjB,SAAS,KAAK;AACZ,aAAO,KAAK,6CAA6C,EAAE,WAAW,QAAQ,IAAI,IAAI,CAAC;AAAA,IACzF;AAAA,EACF;AAEA,MAAI,MAAM,WAAW,MAAM,YAAY;AAMrC,UAAM,YAAY,IAAI,QAAQ,aAAa;AAC3C,QAAI,YAAY,iBAAiB;AAC/B,YAAM,SAAS,MAAM,OAAO,cAAc,GAAG;AAAA,QAC3C,8BAA8B;AAAA,MAChC;AACA,YAAM,MAAM;AAAA,QACV,EAAE,GAAG,IAAI,SAAS,WAAW,YAAY,EAAE;AAAA,QAC3C,EAAE,SAAS,IAAI;AAAA,MACjB;AAAA,IACF,OAAO;AACL,aAAO,KAAK,+CAA+C,EAAE,eAAe,iBAAiB,UAAU,CAAC;AAAA,IAC1G;AAAA,EACF;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -3,6 +3,8 @@ import { CommunicationChannel } from "../data/entities.js";
|
|
|
3
3
|
import { COMMUNICATION_CHANNELS_QUEUES } from "../lib/queue.js";
|
|
4
4
|
import { pushRenew } from "../commands/push-renew.js";
|
|
5
5
|
import { emitCommunicationChannelsEvent } from "../events.js";
|
|
6
|
+
import { createLogger } from "@open-mercato/shared/lib/logger";
|
|
7
|
+
const logger = createLogger("communication_channels").child({ component: "gmail-renew-watch" });
|
|
6
8
|
const metadata = {
|
|
7
9
|
queue: COMMUNICATION_CHANNELS_QUEUES.gmailRenewWatch,
|
|
8
10
|
id: "communication_channels:gmail-renew-watch",
|
|
@@ -40,9 +42,7 @@ async function handle(job, ctx) {
|
|
|
40
42
|
if (state.watchExpirationMs > cutoffMs) continue;
|
|
41
43
|
const organizationId = channel.organizationId;
|
|
42
44
|
if (!organizationId) {
|
|
43
|
-
|
|
44
|
-
`[gmail-renew-watch] skipping channel ${channel.id} \u2014 no organizationId on row`
|
|
45
|
-
);
|
|
45
|
+
logger.warn("skipping channel \u2014 no organizationId on row", { channelId: channel.id });
|
|
46
46
|
continue;
|
|
47
47
|
}
|
|
48
48
|
try {
|
|
@@ -73,13 +73,11 @@ async function handle(job, ctx) {
|
|
|
73
73
|
}
|
|
74
74
|
} catch (err) {
|
|
75
75
|
failed += 1;
|
|
76
|
-
|
|
77
|
-
`[gmail-renew-watch] failed to renew channel ${channel.id}: ${err instanceof Error ? err.message : String(err)}`
|
|
78
|
-
);
|
|
76
|
+
logger.warn("failed to renew channel watch", { channelId: channel.id, err });
|
|
79
77
|
}
|
|
80
78
|
}
|
|
81
79
|
if (renewed > 0 || failed > 0) {
|
|
82
|
-
|
|
80
|
+
logger.info("gmail watch renewal summary", { renewed, failed });
|
|
83
81
|
}
|
|
84
82
|
}
|
|
85
83
|
function resolveContainer(containerProxy, ctx) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/communication_channels/workers/gmail-renew-watch.ts"],
|
|
4
|
-
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport type { JobContext, QueuedJob, WorkerMeta } from '@open-mercato/queue'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { CommunicationChannel } from '../data/entities'\nimport { COMMUNICATION_CHANNELS_QUEUES } from '../lib/queue'\nimport { pushRenew } from '../commands/push-renew'\nimport { emitCommunicationChannelsEvent } from '../events'\n\n/**\n * Spec C \u00A7 Phase C4 \u2014 Daily cron that re-issues `gmail.users.watch` for\n * channels whose `watchExpirationMs` is within the renewal lead window.\n *\n * Gmail watch expires after ~7 days. We renew with a lead time of\n * `OM_PUSH_RENEWAL_GMAIL_LEAD_HOURS` (default 24h) so a missed cron tick\n * doesn't drop us into the polling fallback.\n *\n * The actual renewal is delegated to `pushRenew` (which in turn calls\n * `pushRegister`) \u2014 Gmail's `users.watch` is idempotent, so re-calling it\n * just returns a fresh `historyId` + `expiration` and persists them.\n *\n * Scoped to `job.payload.scope` (the cron is registered per-org in\n * `setup.ts`); each per-org cron tick only walks channels for its own\n * `(tenantId, organizationId)`. A missing scope means the legacy global\n * sweep variant \u2014 supported for backwards compatibility, but new\n * registrations always carry a scope.\n */\nexport type GmailRenewWatchPayload = {\n scope?: { tenantId: string; organizationId: string | null }\n}\n\nexport const metadata: WorkerMeta = {\n queue: COMMUNICATION_CHANNELS_QUEUES.gmailRenewWatch,\n id: 'communication_channels:gmail-renew-watch',\n concurrency: 1,\n}\n\ntype HandlerContext = JobContext & { resolve: <T = unknown>(name: string) => T }\n\nconst LEAD_HOURS = Math.max(\n 1,\n Number.parseInt(process.env.OM_PUSH_RENEWAL_GMAIL_LEAD_HOURS ?? '24', 10) || 24,\n)\n\nexport default async function handle(\n job: QueuedJob<GmailRenewWatchPayload>,\n ctx: HandlerContext,\n): Promise<void> {\n const em = (ctx.resolve('em') as EntityManager).fork()\n const cutoffMs = Date.now() + LEAD_HOURS * 60 * 60 * 1000\n const scope = job?.payload?.scope ?? null\n\n // Per-org cron: filter by the scope embedded in the payload. The unscoped\n // fallback is preserved so a deploy that hand-enqueues a renewal sweep\n // (e.g. an operator-triggered backfill) still works.\n const where: Record<string, unknown> = {\n providerKey: 'gmail',\n isActive: true,\n deletedAt: null,\n }\n if (scope?.tenantId) where.tenantId = scope.tenantId\n if (scope?.organizationId) where.organizationId = scope.organizationId\n const channels = await findWithDecryption(\n em,\n CommunicationChannel,\n where,\n undefined,\n scope ? { tenantId: scope.tenantId, organizationId: scope.organizationId ?? null } : undefined,\n )\n\n const containerProxy = (ctx as unknown as { container?: unknown }).container\n let renewed = 0\n let failed = 0\n for (const channel of channels) {\n const state =\n (channel.channelState as { watchExpirationMs?: number; pushStatus?: string } | null) ?? null\n if (!state || state.pushStatus !== 'active') continue\n if (typeof state.watchExpirationMs !== 'number') continue\n if (state.watchExpirationMs > cutoffMs) continue\n\n const organizationId = channel.organizationId\n if (!organizationId) {\n
|
|
5
|
-
"mappings": "AAEA,SAAS,0BAA0B;AACnC,SAAS,4BAA4B;AACrC,SAAS,qCAAqC;AAC9C,SAAS,iBAAiB;AAC1B,SAAS,sCAAsC;
|
|
4
|
+
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport type { JobContext, QueuedJob, WorkerMeta } from '@open-mercato/queue'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { CommunicationChannel } from '../data/entities'\nimport { COMMUNICATION_CHANNELS_QUEUES } from '../lib/queue'\nimport { pushRenew } from '../commands/push-renew'\nimport { emitCommunicationChannelsEvent } from '../events'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('communication_channels').child({ component: 'gmail-renew-watch' })\n\n/**\n * Spec C \u00A7 Phase C4 \u2014 Daily cron that re-issues `gmail.users.watch` for\n * channels whose `watchExpirationMs` is within the renewal lead window.\n *\n * Gmail watch expires after ~7 days. We renew with a lead time of\n * `OM_PUSH_RENEWAL_GMAIL_LEAD_HOURS` (default 24h) so a missed cron tick\n * doesn't drop us into the polling fallback.\n *\n * The actual renewal is delegated to `pushRenew` (which in turn calls\n * `pushRegister`) \u2014 Gmail's `users.watch` is idempotent, so re-calling it\n * just returns a fresh `historyId` + `expiration` and persists them.\n *\n * Scoped to `job.payload.scope` (the cron is registered per-org in\n * `setup.ts`); each per-org cron tick only walks channels for its own\n * `(tenantId, organizationId)`. A missing scope means the legacy global\n * sweep variant \u2014 supported for backwards compatibility, but new\n * registrations always carry a scope.\n */\nexport type GmailRenewWatchPayload = {\n scope?: { tenantId: string; organizationId: string | null }\n}\n\nexport const metadata: WorkerMeta = {\n queue: COMMUNICATION_CHANNELS_QUEUES.gmailRenewWatch,\n id: 'communication_channels:gmail-renew-watch',\n concurrency: 1,\n}\n\ntype HandlerContext = JobContext & { resolve: <T = unknown>(name: string) => T }\n\nconst LEAD_HOURS = Math.max(\n 1,\n Number.parseInt(process.env.OM_PUSH_RENEWAL_GMAIL_LEAD_HOURS ?? '24', 10) || 24,\n)\n\nexport default async function handle(\n job: QueuedJob<GmailRenewWatchPayload>,\n ctx: HandlerContext,\n): Promise<void> {\n const em = (ctx.resolve('em') as EntityManager).fork()\n const cutoffMs = Date.now() + LEAD_HOURS * 60 * 60 * 1000\n const scope = job?.payload?.scope ?? null\n\n // Per-org cron: filter by the scope embedded in the payload. The unscoped\n // fallback is preserved so a deploy that hand-enqueues a renewal sweep\n // (e.g. an operator-triggered backfill) still works.\n const where: Record<string, unknown> = {\n providerKey: 'gmail',\n isActive: true,\n deletedAt: null,\n }\n if (scope?.tenantId) where.tenantId = scope.tenantId\n if (scope?.organizationId) where.organizationId = scope.organizationId\n const channels = await findWithDecryption(\n em,\n CommunicationChannel,\n where,\n undefined,\n scope ? { tenantId: scope.tenantId, organizationId: scope.organizationId ?? null } : undefined,\n )\n\n const containerProxy = (ctx as unknown as { container?: unknown }).container\n let renewed = 0\n let failed = 0\n for (const channel of channels) {\n const state =\n (channel.channelState as { watchExpirationMs?: number; pushStatus?: string } | null) ?? null\n if (!state || state.pushStatus !== 'active') continue\n if (typeof state.watchExpirationMs !== 'number') continue\n if (state.watchExpirationMs > cutoffMs) continue\n\n const organizationId = channel.organizationId\n if (!organizationId) {\n logger.warn('skipping channel \u2014 no organizationId on row', { channelId: channel.id })\n continue\n }\n\n try {\n const container = resolveContainer(containerProxy, ctx)\n const result = await pushRenew({\n container,\n scope: {\n tenantId: channel.tenantId,\n organizationId,\n userId: channel.userId ?? null,\n },\n input: { channelId: channel.id },\n })\n if (result.pushStatus === 'active') {\n renewed += 1\n await emitCommunicationChannelsEvent(\n 'communication_channels.push.renewed',\n {\n channelId: channel.id,\n providerKey: channel.providerKey,\n tenantId: channel.tenantId,\n organizationId,\n },\n { persistent: false },\n )\n } else {\n failed += 1\n }\n } catch (err) {\n failed += 1\n logger.warn('failed to renew channel watch', { channelId: channel.id, err })\n }\n }\n if (renewed > 0 || failed > 0) {\n logger.info('gmail watch renewal summary', { renewed, failed })\n }\n}\n\nfunction resolveContainer(\n containerProxy: unknown,\n ctx: { resolve: <T = unknown>(name: string) => T },\n): import('awilix').AwilixContainer {\n // The queue runtime exposes container access via `ctx.container` in\n // dedicated worker harnesses, but the bare-worker contract only provides\n // `ctx.resolve(name)`. Both shapes appear in production (test harness,\n // AUTO_SPAWN_WORKERS) so we accept either.\n if (containerProxy && typeof containerProxy === 'object' && 'resolve' in containerProxy) {\n return containerProxy as import('awilix').AwilixContainer\n }\n // Synthesize a minimal container shape from `resolve`.\n return { resolve: ctx.resolve.bind(ctx) } as unknown as import('awilix').AwilixContainer\n}\n"],
|
|
5
|
+
"mappings": "AAEA,SAAS,0BAA0B;AACnC,SAAS,4BAA4B;AACrC,SAAS,qCAAqC;AAC9C,SAAS,iBAAiB;AAC1B,SAAS,sCAAsC;AAC/C,SAAS,oBAAoB;AAE7B,MAAM,SAAS,aAAa,wBAAwB,EAAE,MAAM,EAAE,WAAW,oBAAoB,CAAC;AAwBvF,MAAM,WAAuB;AAAA,EAClC,OAAO,8BAA8B;AAAA,EACrC,IAAI;AAAA,EACJ,aAAa;AACf;AAIA,MAAM,aAAa,KAAK;AAAA,EACtB;AAAA,EACA,OAAO,SAAS,QAAQ,IAAI,oCAAoC,MAAM,EAAE,KAAK;AAC/E;AAEA,eAAO,OACL,KACA,KACe;AACf,QAAM,KAAM,IAAI,QAAQ,IAAI,EAAoB,KAAK;AACrD,QAAM,WAAW,KAAK,IAAI,IAAI,aAAa,KAAK,KAAK;AACrD,QAAM,QAAQ,KAAK,SAAS,SAAS;AAKrC,QAAM,QAAiC;AAAA,IACrC,aAAa;AAAA,IACb,UAAU;AAAA,IACV,WAAW;AAAA,EACb;AACA,MAAI,OAAO,SAAU,OAAM,WAAW,MAAM;AAC5C,MAAI,OAAO,eAAgB,OAAM,iBAAiB,MAAM;AACxD,QAAM,WAAW,MAAM;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,kBAAkB,KAAK,IAAI;AAAA,EACvF;AAEA,QAAM,iBAAkB,IAA2C;AACnE,MAAI,UAAU;AACd,MAAI,SAAS;AACb,aAAW,WAAW,UAAU;AAC9B,UAAM,QACH,QAAQ,gBAA+E;AAC1F,QAAI,CAAC,SAAS,MAAM,eAAe,SAAU;AAC7C,QAAI,OAAO,MAAM,sBAAsB,SAAU;AACjD,QAAI,MAAM,oBAAoB,SAAU;AAExC,UAAM,iBAAiB,QAAQ;AAC/B,QAAI,CAAC,gBAAgB;AACnB,aAAO,KAAK,oDAA+C,EAAE,WAAW,QAAQ,GAAG,CAAC;AACpF;AAAA,IACF;AAEA,QAAI;AACF,YAAM,YAAY,iBAAiB,gBAAgB,GAAG;AACtD,YAAM,SAAS,MAAM,UAAU;AAAA,QAC7B;AAAA,QACA,OAAO;AAAA,UACL,UAAU,QAAQ;AAAA,UAClB;AAAA,UACA,QAAQ,QAAQ,UAAU;AAAA,QAC5B;AAAA,QACA,OAAO,EAAE,WAAW,QAAQ,GAAG;AAAA,MACjC,CAAC;AACD,UAAI,OAAO,eAAe,UAAU;AAClC,mBAAW;AACX,cAAM;AAAA,UACJ;AAAA,UACA;AAAA,YACE,WAAW,QAAQ;AAAA,YACnB,aAAa,QAAQ;AAAA,YACrB,UAAU,QAAQ;AAAA,YAClB;AAAA,UACF;AAAA,UACA,EAAE,YAAY,MAAM;AAAA,QACtB;AAAA,MACF,OAAO;AACL,kBAAU;AAAA,MACZ;AAAA,IACF,SAAS,KAAK;AACZ,gBAAU;AACV,aAAO,KAAK,iCAAiC,EAAE,WAAW,QAAQ,IAAI,IAAI,CAAC;AAAA,IAC7E;AAAA,EACF;AACA,MAAI,UAAU,KAAK,SAAS,GAAG;AAC7B,WAAO,KAAK,+BAA+B,EAAE,SAAS,OAAO,CAAC;AAAA,EAChE;AACF;AAEA,SAAS,iBACP,gBACA,KACkC;AAKlC,MAAI,kBAAkB,OAAO,mBAAmB,YAAY,aAAa,gBAAgB;AACvF,WAAO;AAAA,EACT;AAEA,SAAO,EAAE,SAAS,IAAI,QAAQ,KAAK,GAAG,EAAE;AAC1C;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -3,6 +3,8 @@ import {
|
|
|
3
3
|
} from "../commands/deliver-outbound-message.js";
|
|
4
4
|
import { computeBackoffMs } from "../lib/error-classification.js";
|
|
5
5
|
import { COMMUNICATION_CHANNELS_QUEUES, getCommunicationChannelsQueue } from "../lib/queue.js";
|
|
6
|
+
import { createLogger } from "@open-mercato/shared/lib/logger";
|
|
7
|
+
const logger = createLogger("communication_channels").child({ component: "outbound-delivery" });
|
|
6
8
|
const OUTBOUND_DELIVERY_MAX_ATTEMPTS = 3;
|
|
7
9
|
const metadata = {
|
|
8
10
|
queue: COMMUNICATION_CHANNELS_QUEUES.outbound,
|
|
@@ -32,9 +34,7 @@ async function handle(job, ctx) {
|
|
|
32
34
|
outcome = result;
|
|
33
35
|
} catch (err) {
|
|
34
36
|
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
35
|
-
|
|
36
|
-
`[communication_channels:outbound-delivery] command threw on attempt ${attempt} for message ${messageId}: ${errorMessage}`
|
|
37
|
-
);
|
|
37
|
+
logger.warn("command threw during delivery attempt", { attempt, messageId, reason: errorMessage });
|
|
38
38
|
if (attempt < OUTBOUND_DELIVERY_MAX_ATTEMPTS) {
|
|
39
39
|
await reenqueue(job.payload, attempt);
|
|
40
40
|
return;
|
|
@@ -48,22 +48,16 @@ async function handle(job, ctx) {
|
|
|
48
48
|
return;
|
|
49
49
|
case "failed": {
|
|
50
50
|
if (outcome.requiresReauth && !forceCredentialRefresh && attempt < OUTBOUND_DELIVERY_MAX_ATTEMPTS) {
|
|
51
|
-
|
|
52
|
-
`[communication_channels:outbound-delivery] reauth failure on attempt ${attempt} for message ${messageId} (${outcome.providerKey}): ${outcome.error}. Retrying once with a forced credential refresh.`
|
|
53
|
-
);
|
|
51
|
+
logger.warn("reauth failure; retrying once with a forced credential refresh", { attempt, messageId, providerKey: outcome.providerKey, reason: outcome.error });
|
|
54
52
|
await reenqueue({ ...job.payload, forceCredentialRefresh: true }, attempt);
|
|
55
53
|
return;
|
|
56
54
|
}
|
|
57
55
|
if (outcome.transient && attempt < OUTBOUND_DELIVERY_MAX_ATTEMPTS) {
|
|
58
|
-
|
|
59
|
-
`[communication_channels:outbound-delivery] transient failure on attempt ${attempt} for message ${messageId} (${outcome.providerKey}): ${outcome.error}. Re-enqueueing.`
|
|
60
|
-
);
|
|
56
|
+
logger.warn("transient delivery failure; re-enqueueing", { attempt, messageId, providerKey: outcome.providerKey, reason: outcome.error });
|
|
61
57
|
await reenqueue(job.payload, attempt);
|
|
62
58
|
return;
|
|
63
59
|
}
|
|
64
|
-
|
|
65
|
-
`[communication_channels:outbound-delivery] giving up on message ${messageId} after attempt ${attempt} (${outcome.providerKey}): ${outcome.error}`
|
|
66
|
-
);
|
|
60
|
+
logger.error("giving up on message delivery", { messageId, attempt, providerKey: outcome.providerKey, reason: outcome.error });
|
|
67
61
|
return;
|
|
68
62
|
}
|
|
69
63
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/communication_channels/workers/outbound-delivery.ts"],
|
|
4
|
-
"sourcesContent": ["import type { JobContext, QueuedJob, WorkerMeta } from '@open-mercato/queue'\nimport type { CommandBus } from '@open-mercato/shared/lib/commands'\nimport {\n COMMUNICATION_CHANNELS_DELIVER_OUTBOUND_COMMAND_ID,\n type DeliverOutboundMessageInput,\n type DeliverOutboundMessageResult,\n} from '../commands/deliver-outbound-message'\nimport { computeBackoffMs } from '../lib/error-classification'\nimport { COMMUNICATION_CHANNELS_QUEUES, getCommunicationChannelsQueue } from '../lib/queue'\n\n/**\n * Worker payload \u2014 the subscriber enqueues `{ messageId, scope, attempt? }`.\n *\n * `attempt` starts at 1 on first enqueue. The worker increments it when\n * re-enqueueing for retry, until `MAX_ATTEMPTS` is reached.\n */\nexport type OutboundDeliveryPayload = {\n messageId: string\n scope: {\n tenantId: string\n organizationId: string | null\n }\n /** Attempt number, 1-based. Set by the subscriber for the first try; the worker increments on retry. */\n attempt?: number\n /** Force credential refresh on this attempt \u2014 used after a 401 from the provider. */\n forceCredentialRefresh?: boolean\n}\n\nexport const OUTBOUND_DELIVERY_MAX_ATTEMPTS = 3\n\nexport const metadata: WorkerMeta = {\n queue: COMMUNICATION_CHANNELS_QUEUES.outbound,\n id: 'communication_channels:outbound-delivery',\n concurrency: 10,\n}\n\ntype HandlerContext = JobContext & {\n resolve: <T = unknown>(name: string) => T\n}\n\n/**\n * Outbound delivery worker.\n *\n * Dispatches the `deliver_outbound_message` command which performs the actual\n * send. The command returns a classified result:\n * - `delivered` / `already_delivered` / `no_channel_link` \u2192 success, return.\n * - `failed` with `transient: true` \u2192 re-enqueue with exponential backoff,\n * incremented attempt, up to `OUTBOUND_DELIVERY_MAX_ATTEMPTS`.\n * - `failed` with `transient: false` \u2192 permanent failure, no retry.\n *\n * The command already wrote the failure record + emitted `.delivery_failed`,\n * so the worker just decides whether to schedule another attempt.\n *\n * We DO NOT throw on a recorded delivery-failure outcome \u2014 that would let the\n * queue apply its own retry policy on top of ours, double-retrying. Explicit\n * re-enqueue with delayMs is the portable, controllable pattern. The one\n * exception is an *unexpected* exception from the command itself (e.g. a DB blip\n * that stopped it from recording anything): we re-enqueue up to our max and then\n * rethrow so the infrastructure failure surfaces to the queue's dead-letter\n * instead of vanishing. The command's idempotency prevents a double-send.\n */\nexport default async function handle(\n job: QueuedJob<OutboundDeliveryPayload>,\n ctx: HandlerContext,\n): Promise<void> {\n const { messageId, scope, attempt = 1, forceCredentialRefresh } = job.payload\n\n const commandBus = ctx.resolve<CommandBus>('commandBus')\n const containerProxy = { resolve: ctx.resolve.bind(ctx) }\n const commandCtx = {\n container: containerProxy as never,\n auth: null,\n organizationScope: null,\n selectedOrganizationId: scope.organizationId ?? null,\n organizationIds: scope.organizationId ? [scope.organizationId] : null,\n }\n\n let outcome: DeliverOutboundMessageResult\n try {\n const { result } = await commandBus.execute<\n DeliverOutboundMessageInput,\n DeliverOutboundMessageResult\n >(\n COMMUNICATION_CHANNELS_DELIVER_OUTBOUND_COMMAND_ID,\n {\n input: { messageId, scope, forceCredentialRefresh },\n ctx: commandCtx as never,\n },\n )\n outcome = result\n } catch (err) {\n // Unexpected error inside the command itself (e.g. DB blip). Re-enqueue\n // up to MAX_ATTEMPTS so we don't lose deliveries due to infrastructure flakes.\n const errorMessage = err instanceof Error ? err.message : String(err)\n
|
|
5
|
-
"mappings": "AAEA;AAAA,EACE;AAAA,OAGK;AACP,SAAS,wBAAwB;AACjC,SAAS,+BAA+B,qCAAqC;
|
|
4
|
+
"sourcesContent": ["import type { JobContext, QueuedJob, WorkerMeta } from '@open-mercato/queue'\nimport type { CommandBus } from '@open-mercato/shared/lib/commands'\nimport {\n COMMUNICATION_CHANNELS_DELIVER_OUTBOUND_COMMAND_ID,\n type DeliverOutboundMessageInput,\n type DeliverOutboundMessageResult,\n} from '../commands/deliver-outbound-message'\nimport { computeBackoffMs } from '../lib/error-classification'\nimport { COMMUNICATION_CHANNELS_QUEUES, getCommunicationChannelsQueue } from '../lib/queue'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('communication_channels').child({ component: 'outbound-delivery' })\n\n/**\n * Worker payload \u2014 the subscriber enqueues `{ messageId, scope, attempt? }`.\n *\n * `attempt` starts at 1 on first enqueue. The worker increments it when\n * re-enqueueing for retry, until `MAX_ATTEMPTS` is reached.\n */\nexport type OutboundDeliveryPayload = {\n messageId: string\n scope: {\n tenantId: string\n organizationId: string | null\n }\n /** Attempt number, 1-based. Set by the subscriber for the first try; the worker increments on retry. */\n attempt?: number\n /** Force credential refresh on this attempt \u2014 used after a 401 from the provider. */\n forceCredentialRefresh?: boolean\n}\n\nexport const OUTBOUND_DELIVERY_MAX_ATTEMPTS = 3\n\nexport const metadata: WorkerMeta = {\n queue: COMMUNICATION_CHANNELS_QUEUES.outbound,\n id: 'communication_channels:outbound-delivery',\n concurrency: 10,\n}\n\ntype HandlerContext = JobContext & {\n resolve: <T = unknown>(name: string) => T\n}\n\n/**\n * Outbound delivery worker.\n *\n * Dispatches the `deliver_outbound_message` command which performs the actual\n * send. The command returns a classified result:\n * - `delivered` / `already_delivered` / `no_channel_link` \u2192 success, return.\n * - `failed` with `transient: true` \u2192 re-enqueue with exponential backoff,\n * incremented attempt, up to `OUTBOUND_DELIVERY_MAX_ATTEMPTS`.\n * - `failed` with `transient: false` \u2192 permanent failure, no retry.\n *\n * The command already wrote the failure record + emitted `.delivery_failed`,\n * so the worker just decides whether to schedule another attempt.\n *\n * We DO NOT throw on a recorded delivery-failure outcome \u2014 that would let the\n * queue apply its own retry policy on top of ours, double-retrying. Explicit\n * re-enqueue with delayMs is the portable, controllable pattern. The one\n * exception is an *unexpected* exception from the command itself (e.g. a DB blip\n * that stopped it from recording anything): we re-enqueue up to our max and then\n * rethrow so the infrastructure failure surfaces to the queue's dead-letter\n * instead of vanishing. The command's idempotency prevents a double-send.\n */\nexport default async function handle(\n job: QueuedJob<OutboundDeliveryPayload>,\n ctx: HandlerContext,\n): Promise<void> {\n const { messageId, scope, attempt = 1, forceCredentialRefresh } = job.payload\n\n const commandBus = ctx.resolve<CommandBus>('commandBus')\n const containerProxy = { resolve: ctx.resolve.bind(ctx) }\n const commandCtx = {\n container: containerProxy as never,\n auth: null,\n organizationScope: null,\n selectedOrganizationId: scope.organizationId ?? null,\n organizationIds: scope.organizationId ? [scope.organizationId] : null,\n }\n\n let outcome: DeliverOutboundMessageResult\n try {\n const { result } = await commandBus.execute<\n DeliverOutboundMessageInput,\n DeliverOutboundMessageResult\n >(\n COMMUNICATION_CHANNELS_DELIVER_OUTBOUND_COMMAND_ID,\n {\n input: { messageId, scope, forceCredentialRefresh },\n ctx: commandCtx as never,\n },\n )\n outcome = result\n } catch (err) {\n // Unexpected error inside the command itself (e.g. DB blip). Re-enqueue\n // up to MAX_ATTEMPTS so we don't lose deliveries due to infrastructure flakes.\n const errorMessage = err instanceof Error ? err.message : String(err)\n logger.warn('command threw during delivery attempt', { attempt, messageId, reason: errorMessage })\n if (attempt < OUTBOUND_DELIVERY_MAX_ATTEMPTS) {\n await reenqueue(job.payload, attempt)\n return\n }\n // Attempts exhausted on an unexpected command exception \u2014 rethrow so the\n // failure reaches the queue's dead-letter / observability (see header note).\n throw err\n }\n\n switch (outcome.status) {\n case 'delivered':\n case 'already_delivered':\n case 'no_channel_link':\n return\n case 'failed': {\n // Reauth (401 / invalid_grant): the command already flipped the channel to\n // `requires_reauth`. Give the credentials exactly one forced-refresh retry\n // before giving up \u2014 a near-expiry access token whose proactive refresh\n // was skipped can still recover here. If we already forced a refresh and\n // still got a reauth error, the token is unrecoverable: stop (the operator\n // must reconnect).\n if (\n outcome.requiresReauth &&\n !forceCredentialRefresh &&\n attempt < OUTBOUND_DELIVERY_MAX_ATTEMPTS\n ) {\n logger.warn('reauth failure; retrying once with a forced credential refresh', { attempt, messageId, providerKey: outcome.providerKey, reason: outcome.error })\n await reenqueue({ ...job.payload, forceCredentialRefresh: true }, attempt)\n return\n }\n if (outcome.transient && attempt < OUTBOUND_DELIVERY_MAX_ATTEMPTS) {\n logger.warn('transient delivery failure; re-enqueueing', { attempt, messageId, providerKey: outcome.providerKey, reason: outcome.error })\n await reenqueue(job.payload, attempt)\n return\n }\n // Permanent or attempts exhausted \u2014 `.delivery_failed` was already emitted\n // by the command, so we stop here.\n logger.error('giving up on message delivery', { messageId, attempt, providerKey: outcome.providerKey, reason: outcome.error })\n return\n }\n }\n}\n\nasync function reenqueue(payload: OutboundDeliveryPayload, attempt: number): Promise<void> {\n const next: OutboundDeliveryPayload = {\n ...payload,\n attempt: attempt + 1,\n }\n const delayMs = computeBackoffMs(attempt)\n const queue = getCommunicationChannelsQueue(COMMUNICATION_CHANNELS_QUEUES.outbound)\n await queue.enqueue(next as unknown as Record<string, unknown>, { delayMs })\n}\n"],
|
|
5
|
+
"mappings": "AAEA;AAAA,EACE;AAAA,OAGK;AACP,SAAS,wBAAwB;AACjC,SAAS,+BAA+B,qCAAqC;AAC7E,SAAS,oBAAoB;AAE7B,MAAM,SAAS,aAAa,wBAAwB,EAAE,MAAM,EAAE,WAAW,oBAAoB,CAAC;AAoBvF,MAAM,iCAAiC;AAEvC,MAAM,WAAuB;AAAA,EAClC,OAAO,8BAA8B;AAAA,EACrC,IAAI;AAAA,EACJ,aAAa;AACf;AA2BA,eAAO,OACL,KACA,KACe;AACf,QAAM,EAAE,WAAW,OAAO,UAAU,GAAG,uBAAuB,IAAI,IAAI;AAEtE,QAAM,aAAa,IAAI,QAAoB,YAAY;AACvD,QAAM,iBAAiB,EAAE,SAAS,IAAI,QAAQ,KAAK,GAAG,EAAE;AACxD,QAAM,aAAa;AAAA,IACjB,WAAW;AAAA,IACX,MAAM;AAAA,IACN,mBAAmB;AAAA,IACnB,wBAAwB,MAAM,kBAAkB;AAAA,IAChD,iBAAiB,MAAM,iBAAiB,CAAC,MAAM,cAAc,IAAI;AAAA,EACnE;AAEA,MAAI;AACJ,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAM,WAAW;AAAA,MAIlC;AAAA,MACA;AAAA,QACE,OAAO,EAAE,WAAW,OAAO,uBAAuB;AAAA,QAClD,KAAK;AAAA,MACP;AAAA,IACF;AACA,cAAU;AAAA,EACZ,SAAS,KAAK;AAGZ,UAAM,eAAe,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AACpE,WAAO,KAAK,yCAAyC,EAAE,SAAS,WAAW,QAAQ,aAAa,CAAC;AACjG,QAAI,UAAU,gCAAgC;AAC5C,YAAM,UAAU,IAAI,SAAS,OAAO;AACpC;AAAA,IACF;AAGA,UAAM;AAAA,EACR;AAEA,UAAQ,QAAQ,QAAQ;AAAA,IACtB,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH;AAAA,IACF,KAAK,UAAU;AAOb,UACE,QAAQ,kBACR,CAAC,0BACD,UAAU,gCACV;AACA,eAAO,KAAK,kEAAkE,EAAE,SAAS,WAAW,aAAa,QAAQ,aAAa,QAAQ,QAAQ,MAAM,CAAC;AAC7J,cAAM,UAAU,EAAE,GAAG,IAAI,SAAS,wBAAwB,KAAK,GAAG,OAAO;AACzE;AAAA,MACF;AACA,UAAI,QAAQ,aAAa,UAAU,gCAAgC;AACjE,eAAO,KAAK,6CAA6C,EAAE,SAAS,WAAW,aAAa,QAAQ,aAAa,QAAQ,QAAQ,MAAM,CAAC;AACxI,cAAM,UAAU,IAAI,SAAS,OAAO;AACpC;AAAA,MACF;AAGA,aAAO,MAAM,iCAAiC,EAAE,WAAW,SAAS,aAAa,QAAQ,aAAa,QAAQ,QAAQ,MAAM,CAAC;AAC7H;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAe,UAAU,SAAkC,SAAgC;AACzF,QAAM,OAAgC;AAAA,IACpC,GAAG;AAAA,IACH,SAAS,UAAU;AAAA,EACrB;AACA,QAAM,UAAU,iBAAiB,OAAO;AACxC,QAAM,QAAQ,8BAA8B,8BAA8B,QAAQ;AAClF,QAAM,MAAM,QAAQ,MAA4C,EAAE,QAAQ,CAAC;AAC7E;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -9,6 +9,8 @@ import { writeIngestDeadLetter } from "../lib/dead-letter.js";
|
|
|
9
9
|
import { classifyOutboundError, computeBackoffMs, isReauthError } from "../lib/error-classification.js";
|
|
10
10
|
import { refreshCredentialsIfNeeded } from "../lib/credential-refresh.js";
|
|
11
11
|
import { emitCommunicationChannelsEvent } from "../events.js";
|
|
12
|
+
import { createLogger } from "@open-mercato/shared/lib/logger";
|
|
13
|
+
const logger = createLogger("communication_channels").child({ component: "poll-channel" });
|
|
12
14
|
const POLL_CHANNEL_MAX_ATTEMPTS = 3;
|
|
13
15
|
const MAX_DRAIN_PAGES = 100;
|
|
14
16
|
const metadata = {
|
|
@@ -33,18 +35,14 @@ async function handle(job, ctx) {
|
|
|
33
35
|
scope
|
|
34
36
|
);
|
|
35
37
|
if (!channel) {
|
|
36
|
-
|
|
37
|
-
`[communication_channels:poll-channel] channel ${channelId} not found (skipping)`
|
|
38
|
-
);
|
|
38
|
+
logger.warn("channel not found (skipping)", { channelId });
|
|
39
39
|
return;
|
|
40
40
|
}
|
|
41
41
|
if (!channel.isActive) return;
|
|
42
42
|
if (channel.status !== "connected" && channel.status !== "error") return;
|
|
43
43
|
const adapter = adapterRegistry?.get(channel.providerKey);
|
|
44
44
|
if (!adapter) {
|
|
45
|
-
|
|
46
|
-
`[communication_channels:poll-channel] no adapter for provider '${channel.providerKey}' (channel ${channelId})`
|
|
47
|
-
);
|
|
45
|
+
logger.warn("no adapter for provider", { providerKey: channel.providerKey, channelId });
|
|
48
46
|
return;
|
|
49
47
|
}
|
|
50
48
|
const capabilities = channel.capabilities ?? null;
|
|
@@ -138,9 +136,7 @@ async function handle(job, ctx) {
|
|
|
138
136
|
} catch (err) {
|
|
139
137
|
const classification = classifyOutboundError(err);
|
|
140
138
|
if (classification.transient) {
|
|
141
|
-
|
|
142
|
-
`[communication_channels:poll-channel] transient ingest failure for channel ${channel.id}; aborting page so cursor is NOT advanced. Reason: ${classification.message}`
|
|
143
|
-
);
|
|
139
|
+
logger.warn("transient ingest failure; aborting page so cursor is not advanced", { channelId: channel.id, reason: classification.message });
|
|
144
140
|
transientIngestAbort = true;
|
|
145
141
|
break;
|
|
146
142
|
}
|
|
@@ -152,9 +148,7 @@ async function handle(job, ctx) {
|
|
|
152
148
|
err,
|
|
153
149
|
errorMessage: classification.message
|
|
154
150
|
});
|
|
155
|
-
|
|
156
|
-
`[communication_channels:poll-channel] permanent ingest failure for channel ${channel.id}; recorded in dead-letter and advancing cursor past message ${message.externalMessageId}. Reason: ${classification.message}`
|
|
157
|
-
);
|
|
151
|
+
logger.warn("permanent ingest failure; recorded in dead-letter and advancing cursor", { channelId: channel.id, externalMessageId: message.externalMessageId, reason: classification.message });
|
|
158
152
|
}
|
|
159
153
|
}
|
|
160
154
|
if (transientIngestAbort) {
|
|
@@ -182,9 +176,7 @@ async function handle(job, ctx) {
|
|
|
182
176
|
{ delayMs: 250 }
|
|
183
177
|
);
|
|
184
178
|
} else {
|
|
185
|
-
|
|
186
|
-
`[communication_channels:poll-channel] drain page cap (${MAX_DRAIN_PAGES}) reached for channel ${channel.id}; stopping re-enqueue until the next scheduled tick`
|
|
187
|
-
);
|
|
179
|
+
logger.warn("drain page cap reached; stopping re-enqueue until the next scheduled tick", { maxDrainPages: MAX_DRAIN_PAGES, channelId: channel.id });
|
|
188
180
|
}
|
|
189
181
|
}
|
|
190
182
|
}
|