@open-mercato/core 0.6.6-develop.6465.1.019f0fb26f → 0.6.6-develop.6472.1.1673e7e66b
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/currencies/components/CurrencyFetchingConfig.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client'\n\nimport { useState, useEffect, useCallback, useMemo } from 'react'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { apiCall, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader, extractOptimisticLockConflict } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { Switch } from '@open-mercato/ui/primitives/switch'\nimport { StatusBadge, type StatusBadgeVariant } from '@open-mercato/ui/primitives/status-badge'\nimport { Alert } from '@open-mercato/ui/primitives/alert'\nimport { TimeInput } from '@open-mercato/ui/backend/inputs/TimeInput'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\ninterface FetchConfig {\n id: string\n provider: string\n isEnabled: boolean\n syncTime: string | null\n lastSyncAt: string | null\n lastSyncStatus: string | null\n lastSyncMessage: string | null\n lastSyncCount: number | null\n updatedAt?: string | null\n}\n\nconst STATUS_BADGE_VARIANT: Record<string, StatusBadgeVariant> = {\n success: 'success',\n error: 'error',\n partial: 'warning',\n}\n\nexport default function CurrencyFetchingConfig() {\n const t = useT()\n const [configs, setConfigs] = useState<FetchConfig[]>([])\n const [loading, setLoading] = useState(true)\n const [fetching, setFetching] = useState<string | null>(null)\n const [initializing, setInitializing] = useState(false)\n\n // Available providers that should be configured\n const availableProviders = useMemo(() => ['NBP', 'Raiffeisen Bank Polska'], [])\n\n const mutationContextId = 'currencies-fetch-configs:mutation'\n const { runMutation, retryLastMutation } = useGuardedMutation<{\n formId: string\n resourceKind: string\n resourceId?: string\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: mutationContextId,\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n\n const createProviderConfig = useCallback(async (provider: string) => {\n try {\n await runMutation({\n operation: () => apiCall('/api/currencies/fetch-configs', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n provider,\n isEnabled: false,\n syncTime: '09:00',\n }),\n }),\n context: {\n formId: mutationContextId,\n resourceKind: 'currencies.fetch_config',\n retryLastMutation,\n },\n mutationPayload: { provider, isEnabled: false, syncTime: '09:00' },\n })\n } catch (err: any) {\n // Ignore errors for duplicate providers\n if (!err.message?.includes('already configured')) {\n throw err\n }\n }\n }, [mutationContextId, retryLastMutation, runMutation])\n\n const initializeMissingProviders = useCallback(async (providers: string[]) => {\n setInitializing(true)\n try {\n for (const provider of providers) {\n await createProviderConfig(provider)\n }\n // Reload configs after initialization\n const { result } = await apiCall('/api/currencies/fetch-configs')\n if (result?.configs) {\n setConfigs(result.configs as FetchConfig[])\n }\n } catch (err: any) {\n console.error('Failed to initialize providers:', err)\n } finally {\n setInitializing(false)\n }\n }, [createProviderConfig])\n\n const loadConfigs = useCallback(async () => {\n try {\n const { result } = await apiCall('/api/currencies/fetch-configs')\n\n if (result?.configs) {\n const existingConfigs = result.configs as FetchConfig[]\n setConfigs(existingConfigs)\n\n // Check if we need to initialize any missing providers\n const existingProviders = existingConfigs.map((c) => c.provider)\n const missingProviders = availableProviders.filter(\n (p) => !existingProviders.includes(p)\n )\n\n // Auto-initialize missing providers\n if (missingProviders.length > 0) {\n await initializeMissingProviders(missingProviders)\n }\n }\n } catch (err: any) {\n flash(err.message || t('currencies.fetch.error_load_configs'), 'error')\n } finally {\n setLoading(false)\n }\n }, [availableProviders, initializeMissingProviders, t])\n\n const toggleEnabled = useCallback(async (configId: string, currentValue: boolean, updatedAt?: string | null) => {\n try {\n const call = await runMutation({\n operation: async () => {\n const response = await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(updatedAt),\n () =>\n apiCall('/api/currencies/fetch-configs', {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n id: configId,\n isEnabled: !currentValue,\n }),\n }),\n )\n if (!response.ok) {\n throw Object.assign(new Error('[internal] currencies.fetchConfig.toggle failed'), {\n status: response.status,\n ...((response.result as Record<string, unknown> | null) ?? {}),\n })\n }\n return response\n },\n context: {\n formId: mutationContextId,\n resourceKind: 'currencies.fetch_config',\n resourceId: configId,\n retryLastMutation,\n },\n mutationPayload: { id: configId, isEnabled: !currentValue },\n })\n\n const result = call.result as { config?: FetchConfig } | null\n if (result?.config) {\n setConfigs((prev) =>\n prev.map((c) => (c.id === configId ? (result.config as FetchConfig) : c))\n )\n flash(\n currentValue\n ? t('currencies.fetch.provider_disabled')\n : t('currencies.fetch.provider_enabled'),\n 'success'\n )\n }\n } catch (err: any) {\n if (extractOptimisticLockConflict(err)) return\n flash(err.message || t('currencies.fetch.error_update_config'), 'error')\n }\n }, [mutationContextId, retryLastMutation, runMutation, t])\n\n const updateSyncTime = useCallback(async (configId: string, syncTime: string, updatedAt?: string | null) => {\n try {\n const call = await runMutation({\n operation: async () => {\n const response = await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(updatedAt),\n () =>\n apiCall('/api/currencies/fetch-configs', {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n id: configId,\n syncTime: syncTime || null,\n }),\n }),\n )\n if (!response.ok) {\n throw Object.assign(new Error('[internal] currencies.fetchConfig.updateSyncTime failed'), {\n status: response.status,\n ...((response.result as Record<string, unknown> | null) ?? {}),\n })\n }\n return response\n },\n context: {\n formId: mutationContextId,\n resourceKind: 'currencies.fetch_config',\n resourceId: configId,\n retryLastMutation,\n },\n mutationPayload: { id: configId, syncTime: syncTime || null },\n })\n\n const result = call.result as { config?: FetchConfig } | null\n if (result?.config) {\n setConfigs((prev) =>\n prev.map((c) => (c.id === configId ? (result.config as FetchConfig) : c))\n )\n }\n } catch (err: any) {\n if (extractOptimisticLockConflict(err)) return\n flash(err.message || t('currencies.fetch.error_update_sync_time'), 'error')\n }\n }, [mutationContextId, retryLastMutation, runMutation, t])\n\n const fetchNow = useCallback(async (provider: string) => {\n setFetching(provider)\n\n try {\n const call = await runMutation({\n operation: () => apiCall('/api/currencies/fetch-rates', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n providers: [provider],\n }),\n }),\n context: {\n formId: mutationContextId,\n resourceKind: 'currencies.fetch_rates',\n retryLastMutation,\n },\n mutationPayload: { providers: [provider] },\n })\n\n const result = call.result as { byProvider?: Record<string, { count: number; errors?: string[] }> } | null\n if (result) {\n const byProvider = result.byProvider as Record<string, { count: number; errors?: string[] }>\n const count = byProvider?.[provider]?.count || 0\n\n if (count === 0) {\n flash(t('currencies.fetch.sync_no_rates'), 'warning')\n } else {\n flash(t('currencies.fetch.sync_success', { count }), 'success')\n }\n await loadConfigs()\n }\n } catch (err: any) {\n flash(err.message || t('currencies.fetch.sync_error'), 'error')\n } finally {\n setFetching(null)\n }\n }, [mutationContextId, retryLastMutation, runMutation, t, loadConfigs])\n\n useEffect(() => {\n loadConfigs()\n }, [loadConfigs])\n\n function formatLastSync(date: string | null): string {\n if (!date) return t('currencies.fetch.last_sync_never')\n return new Date(date).toLocaleString()\n }\n\n function getStatusBadge(status: string | null) {\n if (!status) return null\n\n return (\n <StatusBadge variant={STATUS_BADGE_VARIANT[status] ?? 'neutral'}>\n {status}\n </StatusBadge>\n )\n }\n\n function getProviderName(provider: string): string {\n if (provider === 'NBP') return t('currencies.fetch.provider_nbp')\n if (provider === 'Raiffeisen Bank Polska') return t('currencies.fetch.provider_raiffeisen')\n return provider\n }\n\n function getProviderDescription(provider: string): string {\n if (provider === 'NBP') {\n return t('currencies.fetch.provider_nbp_description')\n }\n if (provider === 'Raiffeisen Bank Polska') {\n return t('currencies.fetch.provider_raiffeisen_description')\n }\n return ''\n }\n\n if (loading || initializing) {\n return (\n <section className=\"space-y-3 rounded-lg border bg-background p-4\">\n <header className=\"space-y-2\">\n <h2 className=\"text-xl font-semibold\">{t('currencies.fetch.title')}</h2>\n <p className=\"text-sm text-muted-foreground\">\n {t('currencies.fetch.description')}\n </p>\n </header>\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <Spinner className=\"h-4 w-4\" />\n {initializing ? t('currencies.fetch.initializing_providers') : t('currencies.fetch.loading')}\n </div>\n </section>\n )\n }\n\n return (\n <section className=\"space-y-6 rounded-lg border bg-background p-4\">\n <header className=\"space-y-2\">\n <h2 className=\"text-xl font-semibold\">{t('currencies.fetch.title')}</h2>\n <p className=\"text-sm text-muted-foreground\">\n {t('currencies.fetch.description')}\n </p>\n </header>\n\n <div className=\"space-y-3\">\n {configs.map((config) => (\n <div\n key={config.id}\n className=\"rounded-lg border bg-card p-4\"\n >\n <div className=\"flex items-start justify-between gap-4\">\n <div className=\"flex-1\">\n <h3 className=\"text-sm font-medium\">\n {getProviderName(config.provider)}\n </h3>\n <p className=\"text-xs text-muted-foreground mt-0.5\">\n {getProviderDescription(config.provider)}\n </p>\n </div>\n\n <Switch\n checked={config.isEnabled}\n onCheckedChange={() => toggleEnabled(config.id, config.isEnabled, config.updatedAt)}\n />\n </div>\n\n {config.isEnabled && (\n <>\n <div className=\"flex items-baseline gap-3 flex-wrap mt-3\">\n <div className=\"flex items-baseline gap-2\">\n <label className=\"text-xs text-muted-foreground whitespace-nowrap\">\n {t('currencies.fetch.sync_time')}:\n </label>\n <TimeInput\n value={config.syncTime || '09:00'}\n onChange={(time) => updateSyncTime(config.id, time, config.updatedAt)}\n />\n </div>\n\n <div className=\"flex items-baseline gap-2\">\n <label className=\"text-xs text-muted-foreground whitespace-nowrap\">\n {t('currencies.fetch.last_sync')}:\n </label>\n <span className=\"text-xs text-muted-foreground\">\n {formatLastSync(config.lastSyncAt)}\n </span>\n {getStatusBadge(config.lastSyncStatus)}\n </div>\n\n <Button\n type=\"button\"\n onClick={() => fetchNow(config.provider)}\n disabled={fetching === config.provider}\n size=\"default\"\n className=\"ml-auto min-w-32\"\n >\n {fetching === config.provider ? (\n <div>\n <Spinner className=\"mr-1.5\" size='sm' />\n {t('currencies.fetch.fetching')}\n </div>\n ) : (\n t('currencies.fetch.fetch_now')\n )}\n </Button>\n </div>\n\n {config.lastSyncCount !== null && (\n <div className=\"text-xs text-muted-foreground mt-2\">\n {t('currencies.fetch.last_sync_count')}: <span className=\"font-medium\">{config.lastSyncCount}</span>\n </div>\n )}\n\n {config.lastSyncMessage && config.lastSyncStatus === 'error' && (\n <Alert status=\"error\" style=\"lighter\" size=\"xs\" className=\"mt-2\">\n {config.lastSyncMessage}\n </Alert>\n )}\n </>\n )}\n </div>\n ))}\n\n {configs.length === 0 && (\n <div className=\"rounded border bg-background/80 p-6 text-center\">\n <p className=\"text-sm text-muted-foreground\">\n {t('currencies.fetch.no_providers')}\n </p>\n <Button\n type=\"button\"\n onClick={() => initializeMissingProviders(availableProviders)}\n >\n {t('currencies.fetch.initialize_providers')}\n </Button>\n </div>\n )}\n </div>\n </section>\n )\n}\n"],
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport { useState, useEffect, useCallback, useMemo } from 'react'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { apiCall, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader, extractOptimisticLockConflict } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { Switch } from '@open-mercato/ui/primitives/switch'\nimport { StatusBadge, type StatusBadgeVariant } from '@open-mercato/ui/primitives/status-badge'\nimport { Alert } from '@open-mercato/ui/primitives/alert'\nimport { TimeInput } from '@open-mercato/ui/backend/inputs/TimeInput'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('currencies').child({ component: 'CurrencyFetchingConfig' })\n\ninterface FetchConfig {\n id: string\n provider: string\n isEnabled: boolean\n syncTime: string | null\n lastSyncAt: string | null\n lastSyncStatus: string | null\n lastSyncMessage: string | null\n lastSyncCount: number | null\n updatedAt?: string | null\n}\n\nconst STATUS_BADGE_VARIANT: Record<string, StatusBadgeVariant> = {\n success: 'success',\n error: 'error',\n partial: 'warning',\n}\n\nexport default function CurrencyFetchingConfig() {\n const t = useT()\n const [configs, setConfigs] = useState<FetchConfig[]>([])\n const [loading, setLoading] = useState(true)\n const [fetching, setFetching] = useState<string | null>(null)\n const [initializing, setInitializing] = useState(false)\n\n // Available providers that should be configured\n const availableProviders = useMemo(() => ['NBP', 'Raiffeisen Bank Polska'], [])\n\n const mutationContextId = 'currencies-fetch-configs:mutation'\n const { runMutation, retryLastMutation } = useGuardedMutation<{\n formId: string\n resourceKind: string\n resourceId?: string\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: mutationContextId,\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n\n const createProviderConfig = useCallback(async (provider: string) => {\n try {\n await runMutation({\n operation: () => apiCall('/api/currencies/fetch-configs', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n provider,\n isEnabled: false,\n syncTime: '09:00',\n }),\n }),\n context: {\n formId: mutationContextId,\n resourceKind: 'currencies.fetch_config',\n retryLastMutation,\n },\n mutationPayload: { provider, isEnabled: false, syncTime: '09:00' },\n })\n } catch (err: any) {\n // Ignore errors for duplicate providers\n if (!err.message?.includes('already configured')) {\n throw err\n }\n }\n }, [mutationContextId, retryLastMutation, runMutation])\n\n const initializeMissingProviders = useCallback(async (providers: string[]) => {\n setInitializing(true)\n try {\n for (const provider of providers) {\n await createProviderConfig(provider)\n }\n // Reload configs after initialization\n const { result } = await apiCall('/api/currencies/fetch-configs')\n if (result?.configs) {\n setConfigs(result.configs as FetchConfig[])\n }\n } catch (err: any) {\n logger.error('Failed to initialize providers', { err })\n } finally {\n setInitializing(false)\n }\n }, [createProviderConfig])\n\n const loadConfigs = useCallback(async () => {\n try {\n const { result } = await apiCall('/api/currencies/fetch-configs')\n\n if (result?.configs) {\n const existingConfigs = result.configs as FetchConfig[]\n setConfigs(existingConfigs)\n\n // Check if we need to initialize any missing providers\n const existingProviders = existingConfigs.map((c) => c.provider)\n const missingProviders = availableProviders.filter(\n (p) => !existingProviders.includes(p)\n )\n\n // Auto-initialize missing providers\n if (missingProviders.length > 0) {\n await initializeMissingProviders(missingProviders)\n }\n }\n } catch (err: any) {\n flash(err.message || t('currencies.fetch.error_load_configs'), 'error')\n } finally {\n setLoading(false)\n }\n }, [availableProviders, initializeMissingProviders, t])\n\n const toggleEnabled = useCallback(async (configId: string, currentValue: boolean, updatedAt?: string | null) => {\n try {\n const call = await runMutation({\n operation: async () => {\n const response = await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(updatedAt),\n () =>\n apiCall('/api/currencies/fetch-configs', {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n id: configId,\n isEnabled: !currentValue,\n }),\n }),\n )\n if (!response.ok) {\n throw Object.assign(new Error('[internal] currencies.fetchConfig.toggle failed'), {\n status: response.status,\n ...((response.result as Record<string, unknown> | null) ?? {}),\n })\n }\n return response\n },\n context: {\n formId: mutationContextId,\n resourceKind: 'currencies.fetch_config',\n resourceId: configId,\n retryLastMutation,\n },\n mutationPayload: { id: configId, isEnabled: !currentValue },\n })\n\n const result = call.result as { config?: FetchConfig } | null\n if (result?.config) {\n setConfigs((prev) =>\n prev.map((c) => (c.id === configId ? (result.config as FetchConfig) : c))\n )\n flash(\n currentValue\n ? t('currencies.fetch.provider_disabled')\n : t('currencies.fetch.provider_enabled'),\n 'success'\n )\n }\n } catch (err: any) {\n if (extractOptimisticLockConflict(err)) return\n flash(err.message || t('currencies.fetch.error_update_config'), 'error')\n }\n }, [mutationContextId, retryLastMutation, runMutation, t])\n\n const updateSyncTime = useCallback(async (configId: string, syncTime: string, updatedAt?: string | null) => {\n try {\n const call = await runMutation({\n operation: async () => {\n const response = await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(updatedAt),\n () =>\n apiCall('/api/currencies/fetch-configs', {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n id: configId,\n syncTime: syncTime || null,\n }),\n }),\n )\n if (!response.ok) {\n throw Object.assign(new Error('[internal] currencies.fetchConfig.updateSyncTime failed'), {\n status: response.status,\n ...((response.result as Record<string, unknown> | null) ?? {}),\n })\n }\n return response\n },\n context: {\n formId: mutationContextId,\n resourceKind: 'currencies.fetch_config',\n resourceId: configId,\n retryLastMutation,\n },\n mutationPayload: { id: configId, syncTime: syncTime || null },\n })\n\n const result = call.result as { config?: FetchConfig } | null\n if (result?.config) {\n setConfigs((prev) =>\n prev.map((c) => (c.id === configId ? (result.config as FetchConfig) : c))\n )\n }\n } catch (err: any) {\n if (extractOptimisticLockConflict(err)) return\n flash(err.message || t('currencies.fetch.error_update_sync_time'), 'error')\n }\n }, [mutationContextId, retryLastMutation, runMutation, t])\n\n const fetchNow = useCallback(async (provider: string) => {\n setFetching(provider)\n\n try {\n const call = await runMutation({\n operation: () => apiCall('/api/currencies/fetch-rates', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n providers: [provider],\n }),\n }),\n context: {\n formId: mutationContextId,\n resourceKind: 'currencies.fetch_rates',\n retryLastMutation,\n },\n mutationPayload: { providers: [provider] },\n })\n\n const result = call.result as { byProvider?: Record<string, { count: number; errors?: string[] }> } | null\n if (result) {\n const byProvider = result.byProvider as Record<string, { count: number; errors?: string[] }>\n const count = byProvider?.[provider]?.count || 0\n\n if (count === 0) {\n flash(t('currencies.fetch.sync_no_rates'), 'warning')\n } else {\n flash(t('currencies.fetch.sync_success', { count }), 'success')\n }\n await loadConfigs()\n }\n } catch (err: any) {\n flash(err.message || t('currencies.fetch.sync_error'), 'error')\n } finally {\n setFetching(null)\n }\n }, [mutationContextId, retryLastMutation, runMutation, t, loadConfigs])\n\n useEffect(() => {\n loadConfigs()\n }, [loadConfigs])\n\n function formatLastSync(date: string | null): string {\n if (!date) return t('currencies.fetch.last_sync_never')\n return new Date(date).toLocaleString()\n }\n\n function getStatusBadge(status: string | null) {\n if (!status) return null\n\n return (\n <StatusBadge variant={STATUS_BADGE_VARIANT[status] ?? 'neutral'}>\n {status}\n </StatusBadge>\n )\n }\n\n function getProviderName(provider: string): string {\n if (provider === 'NBP') return t('currencies.fetch.provider_nbp')\n if (provider === 'Raiffeisen Bank Polska') return t('currencies.fetch.provider_raiffeisen')\n return provider\n }\n\n function getProviderDescription(provider: string): string {\n if (provider === 'NBP') {\n return t('currencies.fetch.provider_nbp_description')\n }\n if (provider === 'Raiffeisen Bank Polska') {\n return t('currencies.fetch.provider_raiffeisen_description')\n }\n return ''\n }\n\n if (loading || initializing) {\n return (\n <section className=\"space-y-3 rounded-lg border bg-background p-4\">\n <header className=\"space-y-2\">\n <h2 className=\"text-xl font-semibold\">{t('currencies.fetch.title')}</h2>\n <p className=\"text-sm text-muted-foreground\">\n {t('currencies.fetch.description')}\n </p>\n </header>\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <Spinner className=\"h-4 w-4\" />\n {initializing ? t('currencies.fetch.initializing_providers') : t('currencies.fetch.loading')}\n </div>\n </section>\n )\n }\n\n return (\n <section className=\"space-y-6 rounded-lg border bg-background p-4\">\n <header className=\"space-y-2\">\n <h2 className=\"text-xl font-semibold\">{t('currencies.fetch.title')}</h2>\n <p className=\"text-sm text-muted-foreground\">\n {t('currencies.fetch.description')}\n </p>\n </header>\n\n <div className=\"space-y-3\">\n {configs.map((config) => (\n <div\n key={config.id}\n className=\"rounded-lg border bg-card p-4\"\n >\n <div className=\"flex items-start justify-between gap-4\">\n <div className=\"flex-1\">\n <h3 className=\"text-sm font-medium\">\n {getProviderName(config.provider)}\n </h3>\n <p className=\"text-xs text-muted-foreground mt-0.5\">\n {getProviderDescription(config.provider)}\n </p>\n </div>\n\n <Switch\n checked={config.isEnabled}\n onCheckedChange={() => toggleEnabled(config.id, config.isEnabled, config.updatedAt)}\n />\n </div>\n\n {config.isEnabled && (\n <>\n <div className=\"flex items-baseline gap-3 flex-wrap mt-3\">\n <div className=\"flex items-baseline gap-2\">\n <label className=\"text-xs text-muted-foreground whitespace-nowrap\">\n {t('currencies.fetch.sync_time')}:\n </label>\n <TimeInput\n value={config.syncTime || '09:00'}\n onChange={(time) => updateSyncTime(config.id, time, config.updatedAt)}\n />\n </div>\n\n <div className=\"flex items-baseline gap-2\">\n <label className=\"text-xs text-muted-foreground whitespace-nowrap\">\n {t('currencies.fetch.last_sync')}:\n </label>\n <span className=\"text-xs text-muted-foreground\">\n {formatLastSync(config.lastSyncAt)}\n </span>\n {getStatusBadge(config.lastSyncStatus)}\n </div>\n\n <Button\n type=\"button\"\n onClick={() => fetchNow(config.provider)}\n disabled={fetching === config.provider}\n size=\"default\"\n className=\"ml-auto min-w-32\"\n >\n {fetching === config.provider ? (\n <div>\n <Spinner className=\"mr-1.5\" size='sm' />\n {t('currencies.fetch.fetching')}\n </div>\n ) : (\n t('currencies.fetch.fetch_now')\n )}\n </Button>\n </div>\n\n {config.lastSyncCount !== null && (\n <div className=\"text-xs text-muted-foreground mt-2\">\n {t('currencies.fetch.last_sync_count')}: <span className=\"font-medium\">{config.lastSyncCount}</span>\n </div>\n )}\n\n {config.lastSyncMessage && config.lastSyncStatus === 'error' && (\n <Alert status=\"error\" style=\"lighter\" size=\"xs\" className=\"mt-2\">\n {config.lastSyncMessage}\n </Alert>\n )}\n </>\n )}\n </div>\n ))}\n\n {configs.length === 0 && (\n <div className=\"rounded border bg-background/80 p-6 text-center\">\n <p className=\"text-sm text-muted-foreground\">\n {t('currencies.fetch.no_providers')}\n </p>\n <Button\n type=\"button\"\n onClick={() => initializeMissingProviders(availableProviders)}\n >\n {t('currencies.fetch.initialize_providers')}\n </Button>\n </div>\n )}\n </div>\n </section>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { createCrudFormError } from "@open-mercato/ui/backend/utils/serverErrors";
|
|
2
|
+
import { createLogger } from "@open-mercato/shared/lib/logger";
|
|
3
|
+
const logger = createLogger("currencies").child({ component: "exchange-rate-form" });
|
|
2
4
|
async function loadCurrencyOptions(apiCallFn, query) {
|
|
3
5
|
try {
|
|
4
6
|
const params = new URLSearchParams();
|
|
@@ -17,7 +19,7 @@ async function loadCurrencyOptions(apiCallFn, query) {
|
|
|
17
19
|
}));
|
|
18
20
|
}
|
|
19
21
|
} catch (error) {
|
|
20
|
-
|
|
22
|
+
logger.error("Failed to load currencies", { err: error });
|
|
21
23
|
}
|
|
22
24
|
return [];
|
|
23
25
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/currencies/lib/exchangeRateFormConfig.ts"],
|
|
4
|
-
"sourcesContent": ["import type { CrudFormGroup, CrudFieldOption } from '@open-mercato/ui/backend/CrudForm'\nimport type { ApiCallResult } from '@open-mercato/ui/backend/utils/apiCall'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\n\nexport type CurrencyOption = {\n id: string\n code: string\n name: string\n isActive: boolean\n}\n\ntype ApiCallFn = <T>(input: RequestInfo | URL, init?: RequestInit) => Promise<ApiCallResult<T>>\n\nexport async function loadCurrencyOptions(\n apiCallFn: ApiCallFn,\n query?: string,\n): Promise<CrudFieldOption[]> {\n try {\n const params = new URLSearchParams()\n if (query) {\n params.set('search', query)\n }\n params.set('isActive', 'true')\n params.set('pageSize', '100')\n\n const call = await apiCallFn<{ items: CurrencyOption[] }>(\n `/api/currencies/currencies?${params.toString()}`\n )\n\n if (call.ok && call.result?.items) {\n return call.result.items.map((c) => ({\n value: c.code,\n label: c.code,\n }))\n }\n } catch (error) {\n
|
|
5
|
-
"mappings": "AAEA,SAAS,2BAA2B;
|
|
4
|
+
"sourcesContent": ["import type { CrudFormGroup, CrudFieldOption } from '@open-mercato/ui/backend/CrudForm'\nimport type { ApiCallResult } from '@open-mercato/ui/backend/utils/apiCall'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('currencies').child({ component: 'exchange-rate-form' })\n\nexport type CurrencyOption = {\n id: string\n code: string\n name: string\n isActive: boolean\n}\n\ntype ApiCallFn = <T>(input: RequestInfo | URL, init?: RequestInit) => Promise<ApiCallResult<T>>\n\nexport async function loadCurrencyOptions(\n apiCallFn: ApiCallFn,\n query?: string,\n): Promise<CrudFieldOption[]> {\n try {\n const params = new URLSearchParams()\n if (query) {\n params.set('search', query)\n }\n params.set('isActive', 'true')\n params.set('pageSize', '100')\n\n const call = await apiCallFn<{ items: CurrencyOption[] }>(\n `/api/currencies/currencies?${params.toString()}`\n )\n\n if (call.ok && call.result?.items) {\n return call.result.items.map((c) => ({\n value: c.code,\n label: c.code,\n }))\n }\n } catch (error) {\n logger.error('Failed to load currencies', { err: error })\n }\n return []\n}\n\nexport function exchangeRateGroups(\n t: (key: string) => string,\n loadOptions: (query?: string) => Promise<CrudFieldOption[]>,\n): CrudFormGroup[] {\n return [\n {\n id: 'rate-details',\n column: 1,\n fields: [\n {\n id: 'fromCurrencyCode',\n type: 'combobox',\n label: t('exchangeRates.form.field.fromCurrency'),\n placeholder: t('exchangeRates.form.field.fromCurrencyPlaceholder'),\n required: true,\n loadOptions,\n allowCustomValues: false,\n description: t('exchangeRates.form.field.fromCurrencyHelp'),\n },\n {\n id: 'toCurrencyCode',\n type: 'combobox',\n label: t('exchangeRates.form.field.toCurrency'),\n placeholder: t('exchangeRates.form.field.toCurrencyPlaceholder'),\n required: true,\n loadOptions,\n allowCustomValues: false,\n description: t('exchangeRates.form.field.toCurrencyHelp'),\n },\n {\n id: 'rate',\n type: 'number',\n label: t('exchangeRates.form.field.rate'),\n placeholder: '1.00000000',\n required: true,\n description: t('exchangeRates.form.field.rateHelp'),\n },\n {\n id: 'date',\n type: 'datetime-local',\n label: t('exchangeRates.form.field.date'),\n required: true,\n description: t('exchangeRates.form.field.dateHelp'),\n },\n ],\n },\n {\n id: 'metadata',\n column: 2,\n title: t('exchangeRates.form.group.metadata'),\n fields: [\n {\n id: 'source',\n type: 'text',\n label: t('exchangeRates.form.field.source'),\n placeholder: t('exchangeRates.form.field.sourcePlaceholder'),\n required: true,\n description: t('exchangeRates.form.field.sourceHelp'),\n },\n {\n id: 'type',\n type: 'select',\n label: t('exchangeRates.form.field.type'),\n placeholder: t('exchangeRates.form.field.typePlaceholder'),\n required: false,\n description: t('exchangeRates.form.field.typeHelp'),\n options: [\n { value: 'buy', label: t('exchangeRates.form.field.typeBuy') },\n { value: 'sell', label: t('exchangeRates.form.field.typeSell') },\n ],\n },\n {\n id: 'isActive',\n type: 'checkbox',\n label: t('exchangeRates.form.field.isActive'),\n },\n ],\n },\n ]\n}\n\nexport function validateExchangeRateForm(\n values: Record<string, unknown>,\n t: (key: string) => string,\n): { fromCode: string; toCode: string; rate: number; date: Date; source: string } {\n const fromCode = String(values.fromCurrencyCode || '').trim().toUpperCase()\n const toCode = String(values.toCurrencyCode || '').trim().toUpperCase()\n\n if (!/^[A-Z]{3}$/.test(fromCode)) {\n throw createCrudFormError(t('exchangeRates.form.errors.fromCurrencyFormat'), {\n fromCurrencyCode: t('exchangeRates.form.errors.currencyCodeFormat'),\n })\n }\n\n if (!/^[A-Z]{3}$/.test(toCode)) {\n throw createCrudFormError(t('exchangeRates.form.errors.toCurrencyFormat'), {\n toCurrencyCode: t('exchangeRates.form.errors.currencyCodeFormat'),\n })\n }\n\n if (fromCode === toCode) {\n throw createCrudFormError(t('exchangeRates.form.errors.sameCurrency'), {\n toCurrencyCode: t('exchangeRates.form.errors.sameCurrency'),\n })\n }\n\n const rate = parseFloat(String(values.rate || '0'))\n if (isNaN(rate) || rate <= 0) {\n throw createCrudFormError(t('exchangeRates.form.errors.invalidRate'), {\n rate: t('exchangeRates.form.errors.invalidRate'),\n })\n }\n\n const date = values.date ? new Date(String(values.date)) : null\n\n if (!date || isNaN(date.getTime())) {\n throw createCrudFormError(t('exchangeRates.form.errors.invalidDate'), {\n date: t('exchangeRates.form.errors.invalidDate'),\n })\n }\n\n const source = String(values.source || '').trim()\n if (!source || source.length < 2) {\n throw createCrudFormError(t('exchangeRates.form.errors.sourceTooShort'), {\n source: t('exchangeRates.form.errors.sourceTooShort'),\n })\n }\n if (source.length > 50) {\n throw createCrudFormError(t('exchangeRates.form.errors.sourceTooLong'), {\n source: t('exchangeRates.form.errors.sourceTooLong'),\n })\n }\n if (!/^[a-zA-Z0-9\\s\\-_]+$/.test(source)) {\n throw createCrudFormError(t('exchangeRates.form.errors.sourceInvalidFormat'), {\n source: t('exchangeRates.form.errors.sourceInvalidFormat'),\n })\n }\n\n return { fromCode, toCode, rate, date, source }\n}\n\nexport function buildExchangeRatePayload(values: Record<string, unknown>, validated: {\n fromCode: string\n toCode: string\n rate: number\n date: Date\n source: string\n}) {\n return {\n fromCurrencyCode: validated.fromCode,\n toCurrencyCode: validated.toCode,\n rate: validated.rate.toFixed(8),\n date: validated.date.toISOString(),\n source: validated.source,\n type: values.type && values.type !== '' ? values.type : null,\n isActive: values.isActive !== false,\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { fromZonedTime } from "date-fns-tz";
|
|
2
2
|
import { fetchWithTimeout, resolveTimeoutMs } from "@open-mercato/shared/lib/http/fetchWithTimeout";
|
|
3
|
+
import { createLogger } from "@open-mercato/shared/lib/logger";
|
|
4
|
+
const logger = createLogger("currencies").child({ component: "nbp" });
|
|
3
5
|
const DEFAULT_RATE_FETCH_TIMEOUT_MS = 15e3;
|
|
4
6
|
function resolveRateFetchTimeoutMs() {
|
|
5
7
|
const raw = process.env.CURRENCY_RATE_FETCH_TIMEOUT_MS;
|
|
@@ -18,7 +20,7 @@ class NBPProvider {
|
|
|
18
20
|
}
|
|
19
21
|
async fetchRates(date, scope, availableCurrencies) {
|
|
20
22
|
if (!availableCurrencies.has(this.providerBaseCurrency)) {
|
|
21
|
-
|
|
23
|
+
logger.debug("Skipping: PLN not found in available currencies");
|
|
22
24
|
return [];
|
|
23
25
|
}
|
|
24
26
|
const dateStr = this.formatDate(date);
|
|
@@ -26,7 +28,7 @@ class NBPProvider {
|
|
|
26
28
|
try {
|
|
27
29
|
const response = await fetchWithTimeout(url, { timeoutMs: resolveRateFetchTimeoutMs() });
|
|
28
30
|
if (response.status === 404) {
|
|
29
|
-
|
|
31
|
+
logger.debug("No data available", { date: dateStr });
|
|
30
32
|
return [];
|
|
31
33
|
}
|
|
32
34
|
if (!response.ok) {
|
|
@@ -62,10 +64,10 @@ class NBPProvider {
|
|
|
62
64
|
// Bank buys foreign currency (from their perspective)
|
|
63
65
|
});
|
|
64
66
|
}
|
|
65
|
-
|
|
67
|
+
logger.info("Fetched rates", { count: results.length, date: dateStr });
|
|
66
68
|
return results;
|
|
67
69
|
} catch (err) {
|
|
68
|
-
|
|
70
|
+
logger.error("Fetch error", { date: dateStr, err });
|
|
69
71
|
throw new Error(`Failed to fetch NBP rates: ${err.message}`);
|
|
70
72
|
}
|
|
71
73
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/modules/currencies/services/providers/nbp.ts"],
|
|
4
|
-
"sourcesContent": ["import { RateProvider, RateProviderResult } from './base'\nimport { fromZonedTime } from 'date-fns-tz'\nimport { fetchWithTimeout, resolveTimeoutMs } from '@open-mercato/shared/lib/http/fetchWithTimeout'\n\nconst DEFAULT_RATE_FETCH_TIMEOUT_MS = 15_000\n\nfunction resolveRateFetchTimeoutMs(): number {\n const raw = process.env.CURRENCY_RATE_FETCH_TIMEOUT_MS\n const parsed = raw ? Number.parseInt(raw, 10) : undefined\n return resolveTimeoutMs(parsed, DEFAULT_RATE_FETCH_TIMEOUT_MS)\n}\n\ninterface NBPTableCResponse {\n table: string\n no: string\n tradingDate: string\n effectiveDate: string\n rates: Array<{\n currency: string\n code: string\n bid: number\n ask: number\n }>\n}\n\nexport class NBPProvider implements RateProvider {\n readonly name = 'NBP (National Bank of Poland)'\n readonly source = 'NBP'\n readonly providerBaseCurrency = 'PLN'\n\n private readonly baseUrl = 'https://api.nbp.pl/api'\n\n isAvailable(): boolean {\n return true // Public API, always available\n }\n\n async fetchRates(\n date: Date,\n scope: { tenantId: string; organizationId: string },\n availableCurrencies: Set<string>\n ): Promise<RateProviderResult[]> {\n // Check if PLN is available (required as base currency for NBP)\n if (!availableCurrencies.has(this.providerBaseCurrency)) {\n
|
|
5
|
-
"mappings": "AACA,SAAS,qBAAqB;AAC9B,SAAS,kBAAkB,wBAAwB;
|
|
4
|
+
"sourcesContent": ["import { RateProvider, RateProviderResult } from './base'\nimport { fromZonedTime } from 'date-fns-tz'\nimport { fetchWithTimeout, resolveTimeoutMs } from '@open-mercato/shared/lib/http/fetchWithTimeout'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('currencies').child({ component: 'nbp' })\n\nconst DEFAULT_RATE_FETCH_TIMEOUT_MS = 15_000\n\nfunction resolveRateFetchTimeoutMs(): number {\n const raw = process.env.CURRENCY_RATE_FETCH_TIMEOUT_MS\n const parsed = raw ? Number.parseInt(raw, 10) : undefined\n return resolveTimeoutMs(parsed, DEFAULT_RATE_FETCH_TIMEOUT_MS)\n}\n\ninterface NBPTableCResponse {\n table: string\n no: string\n tradingDate: string\n effectiveDate: string\n rates: Array<{\n currency: string\n code: string\n bid: number\n ask: number\n }>\n}\n\nexport class NBPProvider implements RateProvider {\n readonly name = 'NBP (National Bank of Poland)'\n readonly source = 'NBP'\n readonly providerBaseCurrency = 'PLN'\n\n private readonly baseUrl = 'https://api.nbp.pl/api'\n\n isAvailable(): boolean {\n return true // Public API, always available\n }\n\n async fetchRates(\n date: Date,\n scope: { tenantId: string; organizationId: string },\n availableCurrencies: Set<string>\n ): Promise<RateProviderResult[]> {\n // Check if PLN is available (required as base currency for NBP)\n if (!availableCurrencies.has(this.providerBaseCurrency)) {\n logger.debug('Skipping: PLN not found in available currencies')\n return []\n }\n\n const dateStr = this.formatDate(date)\n const url = `${this.baseUrl}/exchangerates/tables/c/${dateStr}/?format=json`\n\n try {\n const response = await fetchWithTimeout(url, { timeoutMs: resolveRateFetchTimeoutMs() })\n\n if (response.status === 404) {\n // No data for this date (weekend/holiday)\n logger.debug('No data available', { date: dateStr })\n return []\n }\n\n if (!response.ok) {\n throw new Error(`NBP API error: ${response.status} ${response.statusText}`)\n }\n\n const data: NBPTableCResponse[] = await response.json()\n\n if (!data || data.length === 0) {\n return []\n }\n\n const table = data[0]\n const results: RateProviderResult[] = []\n \n // Parse as midnight Europe/Warsaw, then convert to UTC for DB storage\n const effectiveDate = fromZonedTime(\n `${table.effectiveDate} 00:00:00`,\n 'Europe/Warsaw'\n )\n\n for (const rate of table.rates) {\n // NBP rates are from bank's perspective:\n // - ASK (sprzeda\u017C): bank sells XXX for PLN \u2192 1 XXX = ask PLN\n // - BID (kupno): bank buys XXX for PLN \u2192 1 XXX = bid PLN\n \n // Rate 1: PLN \u2192 XXX (inverse of ASK) - this is when bank SELLS foreign currency\n // If ask = 4.5 (1 EUR costs 4.5 PLN), then 1 PLN = 1/4.5 EUR\n results.push({\n fromCurrencyCode: this.providerBaseCurrency,\n toCurrencyCode: rate.code,\n rate: (1 / rate.ask).toString(),\n source: this.source,\n date: effectiveDate,\n type: 'sell', // Bank sells foreign currency (from their perspective)\n })\n\n // Rate 2: XXX \u2192 PLN (using BID) - this is when bank BUYS foreign currency\n // If bid = 4.3 (1 EUR gives 4.3 PLN), then 1 EUR = 4.3 PLN\n results.push({\n fromCurrencyCode: rate.code,\n toCurrencyCode: this.providerBaseCurrency,\n rate: rate.bid.toString(),\n source: this.source,\n date: effectiveDate,\n type: 'buy', // Bank buys foreign currency (from their perspective)\n })\n }\n\n logger.info('Fetched rates', { count: results.length, date: dateStr })\n return results\n } catch (err: any) {\n logger.error('Fetch error', { date: dateStr, err })\n throw new Error(`Failed to fetch NBP rates: ${err.message}`)\n }\n }\n\n private formatDate(date: Date): string {\n return date.toISOString().split('T')[0] // YYYY-MM-DD\n }\n}\n"],
|
|
5
|
+
"mappings": "AACA,SAAS,qBAAqB;AAC9B,SAAS,kBAAkB,wBAAwB;AACnD,SAAS,oBAAoB;AAE7B,MAAM,SAAS,aAAa,YAAY,EAAE,MAAM,EAAE,WAAW,MAAM,CAAC;AAEpE,MAAM,gCAAgC;AAEtC,SAAS,4BAAoC;AAC3C,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,SAAS,MAAM,OAAO,SAAS,KAAK,EAAE,IAAI;AAChD,SAAO,iBAAiB,QAAQ,6BAA6B;AAC/D;AAeO,MAAM,YAAoC;AAAA,EAA1C;AACL,SAAS,OAAO;AAChB,SAAS,SAAS;AAClB,SAAS,uBAAuB;AAEhC,SAAiB,UAAU;AAAA;AAAA,EAE3B,cAAuB;AACrB,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,WACJ,MACA,OACA,qBAC+B;AAE/B,QAAI,CAAC,oBAAoB,IAAI,KAAK,oBAAoB,GAAG;AACvD,aAAO,MAAM,iDAAiD;AAC9D,aAAO,CAAC;AAAA,IACV;AAEA,UAAM,UAAU,KAAK,WAAW,IAAI;AACpC,UAAM,MAAM,GAAG,KAAK,OAAO,2BAA2B,OAAO;AAE7D,QAAI;AACF,YAAM,WAAW,MAAM,iBAAiB,KAAK,EAAE,WAAW,0BAA0B,EAAE,CAAC;AAEvF,UAAI,SAAS,WAAW,KAAK;AAE3B,eAAO,MAAM,qBAAqB,EAAE,MAAM,QAAQ,CAAC;AACnD,eAAO,CAAC;AAAA,MACV;AAEA,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI,MAAM,kBAAkB,SAAS,MAAM,IAAI,SAAS,UAAU,EAAE;AAAA,MAC5E;AAEA,YAAM,OAA4B,MAAM,SAAS,KAAK;AAEtD,UAAI,CAAC,QAAQ,KAAK,WAAW,GAAG;AAC9B,eAAO,CAAC;AAAA,MACV;AAEA,YAAM,QAAQ,KAAK,CAAC;AACpB,YAAM,UAAgC,CAAC;AAGvC,YAAM,gBAAgB;AAAA,QACpB,GAAG,MAAM,aAAa;AAAA,QACtB;AAAA,MACF;AAEA,iBAAW,QAAQ,MAAM,OAAO;AAO9B,gBAAQ,KAAK;AAAA,UACX,kBAAkB,KAAK;AAAA,UACvB,gBAAgB,KAAK;AAAA,UACrB,OAAO,IAAI,KAAK,KAAK,SAAS;AAAA,UAC9B,QAAQ,KAAK;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA;AAAA,QACR,CAAC;AAID,gBAAQ,KAAK;AAAA,UACX,kBAAkB,KAAK;AAAA,UACvB,gBAAgB,KAAK;AAAA,UACrB,MAAM,KAAK,IAAI,SAAS;AAAA,UACxB,QAAQ,KAAK;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA;AAAA,QACR,CAAC;AAAA,MACH;AAEA,aAAO,KAAK,iBAAiB,EAAE,OAAO,QAAQ,QAAQ,MAAM,QAAQ,CAAC;AACrE,aAAO;AAAA,IACT,SAAS,KAAU;AACjB,aAAO,MAAM,eAAe,EAAE,MAAM,SAAS,IAAI,CAAC;AAClD,YAAM,IAAI,MAAM,8BAA8B,IAAI,OAAO,EAAE;AAAA,IAC7D;AAAA,EACF;AAAA,EAEQ,WAAW,MAAoB;AACrC,WAAO,KAAK,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC;AAAA,EACxC;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { fromZonedTime } from "date-fns-tz";
|
|
2
2
|
import { fetchWithTimeout, resolveTimeoutMs } from "@open-mercato/shared/lib/http/fetchWithTimeout";
|
|
3
|
+
import { createLogger } from "@open-mercato/shared/lib/logger";
|
|
4
|
+
const logger = createLogger("currencies").child({ component: "raiffeisen" });
|
|
3
5
|
const DEFAULT_RATE_FETCH_TIMEOUT_MS = 15e3;
|
|
4
6
|
function resolveRateFetchTimeoutMs() {
|
|
5
7
|
const raw = process.env.CURRENCY_RATE_FETCH_TIMEOUT_MS;
|
|
@@ -18,7 +20,7 @@ class RaiffeisenPolandProvider {
|
|
|
18
20
|
}
|
|
19
21
|
async fetchRates(date, scope, availableCurrencies) {
|
|
20
22
|
if (!availableCurrencies.has(this.providerBaseCurrency)) {
|
|
21
|
-
|
|
23
|
+
logger.debug("Skipping: PLN not found in available currencies");
|
|
22
24
|
return [];
|
|
23
25
|
}
|
|
24
26
|
const dateStr = this.formatDate(date);
|
|
@@ -27,7 +29,7 @@ class RaiffeisenPolandProvider {
|
|
|
27
29
|
const response = await fetchWithTimeout(url, { timeoutMs: resolveRateFetchTimeoutMs() });
|
|
28
30
|
if (!response.ok) {
|
|
29
31
|
if (response.status === 404) {
|
|
30
|
-
|
|
32
|
+
logger.debug("No data available", { date: dateStr });
|
|
31
33
|
return [];
|
|
32
34
|
}
|
|
33
35
|
throw new Error(
|
|
@@ -44,7 +46,7 @@ class RaiffeisenPolandProvider {
|
|
|
44
46
|
const results = [];
|
|
45
47
|
const firstRate = rates[0];
|
|
46
48
|
if (!firstRate) {
|
|
47
|
-
|
|
49
|
+
logger.debug("No rates available in time slot", { timeSlot: firstTime });
|
|
48
50
|
return [];
|
|
49
51
|
}
|
|
50
52
|
const rateDate = fromZonedTime(
|
|
@@ -72,12 +74,10 @@ class RaiffeisenPolandProvider {
|
|
|
72
74
|
// Bank buys foreign currency (from their perspective)
|
|
73
75
|
});
|
|
74
76
|
}
|
|
75
|
-
|
|
76
|
-
`[Raiffeisen] Fetched ${results.length} rates for ${dateStr} at ${firstRate.time} Warsaw time (${rateDate.toISOString()})`
|
|
77
|
-
);
|
|
77
|
+
logger.info("Fetched rates", { count: results.length, date: dateStr, time: firstRate.time, rateDate: rateDate.toISOString() });
|
|
78
78
|
return results;
|
|
79
79
|
} catch (err) {
|
|
80
|
-
|
|
80
|
+
logger.error("Fetch error", { date: dateStr, err });
|
|
81
81
|
throw new Error(`Failed to fetch Raiffeisen rates: ${err.message}`);
|
|
82
82
|
}
|
|
83
83
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/modules/currencies/services/providers/raiffeisen.ts"],
|
|
4
|
-
"sourcesContent": ["import { RateProvider, RateProviderResult } from './base'\nimport { fromZonedTime } from 'date-fns-tz'\nimport { fetchWithTimeout, resolveTimeoutMs } from '@open-mercato/shared/lib/http/fetchWithTimeout'\n\nconst DEFAULT_RATE_FETCH_TIMEOUT_MS = 15_000\n\nfunction resolveRateFetchTimeoutMs(): number {\n const raw = process.env.CURRENCY_RATE_FETCH_TIMEOUT_MS\n const parsed = raw ? Number.parseInt(raw, 10) : undefined\n return resolveTimeoutMs(parsed, DEFAULT_RATE_FETCH_TIMEOUT_MS)\n}\n\ninterface RaiffeisenResponse {\n date: string\n rates: Record<\n string,\n Array<{\n code: string\n units: number\n buy: string\n sell: string\n spread: string\n date: string\n time: string\n }>\n >\n range: {\n minRateDate: string\n maxRateDate: string\n }\n}\n\n// \nexport class RaiffeisenPolandProvider implements RateProvider {\n readonly name = 'Raiffeisen Bank Polska'\n readonly source = 'Raiffeisen Bank Polska'\n readonly providerBaseCurrency = 'PLN'\n\n private readonly baseUrl = 'https://www.rbinternational.com.pl/rest/rates/'\n\n isAvailable(): boolean {\n return true\n }\n\n async fetchRates(\n date: Date,\n scope: { tenantId: string; organizationId: string },\n availableCurrencies: Set<string>\n ): Promise<RateProviderResult[]> {\n // Check if PLN is available (required as base currency for Raiffeisen)\n if (!availableCurrencies.has(this.providerBaseCurrency)) {\n
|
|
5
|
-
"mappings": "AACA,SAAS,qBAAqB;AAC9B,SAAS,kBAAkB,wBAAwB;
|
|
4
|
+
"sourcesContent": ["import { RateProvider, RateProviderResult } from './base'\nimport { fromZonedTime } from 'date-fns-tz'\nimport { fetchWithTimeout, resolveTimeoutMs } from '@open-mercato/shared/lib/http/fetchWithTimeout'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('currencies').child({ component: 'raiffeisen' })\n\nconst DEFAULT_RATE_FETCH_TIMEOUT_MS = 15_000\n\nfunction resolveRateFetchTimeoutMs(): number {\n const raw = process.env.CURRENCY_RATE_FETCH_TIMEOUT_MS\n const parsed = raw ? Number.parseInt(raw, 10) : undefined\n return resolveTimeoutMs(parsed, DEFAULT_RATE_FETCH_TIMEOUT_MS)\n}\n\ninterface RaiffeisenResponse {\n date: string\n rates: Record<\n string,\n Array<{\n code: string\n units: number\n buy: string\n sell: string\n spread: string\n date: string\n time: string\n }>\n >\n range: {\n minRateDate: string\n maxRateDate: string\n }\n}\n\n// \nexport class RaiffeisenPolandProvider implements RateProvider {\n readonly name = 'Raiffeisen Bank Polska'\n readonly source = 'Raiffeisen Bank Polska'\n readonly providerBaseCurrency = 'PLN'\n\n private readonly baseUrl = 'https://www.rbinternational.com.pl/rest/rates/'\n\n isAvailable(): boolean {\n return true\n }\n\n async fetchRates(\n date: Date,\n scope: { tenantId: string; organizationId: string },\n availableCurrencies: Set<string>\n ): Promise<RateProviderResult[]> {\n // Check if PLN is available (required as base currency for Raiffeisen)\n if (!availableCurrencies.has(this.providerBaseCurrency)) {\n logger.debug('Skipping: PLN not found in available currencies')\n return []\n }\n\n const dateStr = this.formatDate(date)\n const url = `${this.baseUrl}?type=kursywalut&range=all&date=${dateStr}`\n\n try {\n const response = await fetchWithTimeout(url, { timeoutMs: resolveRateFetchTimeoutMs() })\n\n if (!response.ok) {\n if (response.status === 404) {\n logger.debug('No data available', { date: dateStr })\n return []\n }\n throw new Error(\n `Raiffeisen API error: ${response.status} ${response.statusText}`\n )\n }\n\n const data: RaiffeisenResponse = await response.json()\n\n if (!data.rates || Object.keys(data.rates).length === 0) {\n return []\n }\n\n // Get FIRST time slot (opening rates)\n const times = Object.keys(data.rates).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))\n const firstTime = times[0]\n const rates = data.rates[firstTime]\n\n const results: RateProviderResult[] = []\n \n // Extract time from first rate entry (all rates in same time slot have same time)\n const firstRate = rates[0]\n if (!firstRate) {\n logger.debug('No rates available in time slot', { timeSlot: firstTime })\n return []\n }\n\n // Combine date + time and parse as Europe/Warsaw timezone\n const rateDate = fromZonedTime(\n `${data.date} ${firstRate.time}`,\n 'Europe/Warsaw'\n )\n\n for (const rateData of rates) {\n // Raiffeisen rates are from bank's perspective:\n // - SELL: bank sells XXX for PLN \u2192 1 XXX = sell PLN\n // - BUY: bank buys XXX for PLN \u2192 1 XXX = buy PLN\n \n // Rate 1: PLN \u2192 XXX (inverse of SELL) - this is when bank SELLS foreign currency\n // If sell = 4.5 (1 EUR costs 4.5 PLN), then 1 PLN = 1/4.5 EUR\n const sellRate = parseFloat(rateData.sell)\n results.push({\n fromCurrencyCode: this.providerBaseCurrency,\n toCurrencyCode: rateData.code,\n rate: (1 / sellRate).toString(),\n source: this.source,\n date: rateDate,\n type: 'sell', // Bank sells foreign currency (from their perspective)\n })\n\n // Rate 2: XXX \u2192 PLN (using BUY) - this is when bank BUYS foreign currency\n // If buy = 4.3 (1 EUR gives 4.3 PLN), then 1 EUR = 4.3 PLN\n results.push({\n fromCurrencyCode: rateData.code,\n toCurrencyCode: this.providerBaseCurrency,\n rate: rateData.buy,\n source: this.source,\n date: rateDate,\n type: 'buy', // Bank buys foreign currency (from their perspective)\n })\n }\n\n logger.info('Fetched rates', { count: results.length, date: dateStr, time: firstRate.time, rateDate: rateDate.toISOString() })\n return results\n } catch (err: any) {\n logger.error('Fetch error', { date: dateStr, err })\n throw new Error(`Failed to fetch Raiffeisen rates: ${err.message}`)\n }\n }\n\n private formatDate(date: Date): string {\n return date.toISOString().split('T')[0] // YYYY-MM-DD\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -7,8 +7,9 @@ import {
|
|
|
7
7
|
checkAuthRateLimit,
|
|
8
8
|
domainResolveAllIpRateLimitConfig
|
|
9
9
|
} from "@open-mercato/core/modules/customer_accounts/lib/rateLimiter";
|
|
10
|
+
import { createLogger } from "@open-mercato/shared/lib/logger";
|
|
11
|
+
const logger = createLogger("customer_accounts").child({ component: "domain-resolve-all" });
|
|
10
12
|
const ORIGIN_HEADER_NAME = process.env.CUSTOMER_DOMAIN_ORIGIN_HEADER ?? "X-Open-Mercato-Origin";
|
|
11
|
-
const LOG_PREFIX = "[domain-resolve/all]";
|
|
12
13
|
const ENDPOINT_PATH = "/api/customer_accounts/domain-resolve/all";
|
|
13
14
|
const metadata = {
|
|
14
15
|
GET: { requireAuth: false }
|
|
@@ -31,7 +32,7 @@ async function GET(req) {
|
|
|
31
32
|
const callerIp = readCallerIp(req);
|
|
32
33
|
const expected = process.env.DOMAIN_RESOLVE_SECRET;
|
|
33
34
|
if (!expected) {
|
|
34
|
-
|
|
35
|
+
logger.warn("Rejected request \u2014 secret not configured", {
|
|
35
36
|
endpoint: ENDPOINT_PATH,
|
|
36
37
|
ip: callerIp,
|
|
37
38
|
outcome: "misconfigured"
|
|
@@ -48,7 +49,7 @@ async function GET(req) {
|
|
|
48
49
|
ipConfig: domainResolveAllIpRateLimitConfig
|
|
49
50
|
});
|
|
50
51
|
if (rateLimitError) {
|
|
51
|
-
|
|
52
|
+
logger.warn("Rate-limited", {
|
|
52
53
|
endpoint: ENDPOINT_PATH,
|
|
53
54
|
ip: callerIp,
|
|
54
55
|
outcome: "rate_limited"
|
|
@@ -57,7 +58,7 @@ async function GET(req) {
|
|
|
57
58
|
}
|
|
58
59
|
const supplied = req.headers.get("x-domain-resolve-secret");
|
|
59
60
|
if (!secretEqual(supplied, expected)) {
|
|
60
|
-
|
|
61
|
+
logger.warn("Rejected request \u2014 invalid secret", {
|
|
61
62
|
endpoint: ENDPOINT_PATH,
|
|
62
63
|
ip: callerIp,
|
|
63
64
|
outcome: "forbidden"
|
|
@@ -67,7 +68,7 @@ async function GET(req) {
|
|
|
67
68
|
const container = await createRequestContainer();
|
|
68
69
|
const service = container.resolve("domainMappingService");
|
|
69
70
|
const records = await service.resolveAll();
|
|
70
|
-
|
|
71
|
+
logger.info("Authorized", {
|
|
71
72
|
endpoint: ENDPOINT_PATH,
|
|
72
73
|
ip: callerIp,
|
|
73
74
|
outcome: "ok",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/modules/customer_accounts/api/domain-resolve/all.ts"],
|
|
4
|
-
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { secretEqual } from '@open-mercato/core/modules/customer_accounts/lib/secretCompare'\nimport { DomainMappingService } from '@open-mercato/core/modules/customer_accounts/services/domainMappingService'\nimport { rateLimitErrorSchema } from '@open-mercato/shared/lib/ratelimit/helpers'\nimport {\n checkAuthRateLimit,\n domainResolveAllIpRateLimitConfig,\n} from '@open-mercato/core/modules/customer_accounts/lib/rateLimiter'\n\nconst ORIGIN_HEADER_NAME = process.env.CUSTOMER_DOMAIN_ORIGIN_HEADER ?? 'X-Open-Mercato-Origin'\nconst
|
|
5
|
-
"mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAElB,SAAS,8BAA8B;AACvC,SAAS,mBAAmB;AAE5B,SAAS,4BAA4B;AACrC;AAAA,EACE;AAAA,EACA;AAAA,OACK;
|
|
4
|
+
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { secretEqual } from '@open-mercato/core/modules/customer_accounts/lib/secretCompare'\nimport { DomainMappingService } from '@open-mercato/core/modules/customer_accounts/services/domainMappingService'\nimport { rateLimitErrorSchema } from '@open-mercato/shared/lib/ratelimit/helpers'\nimport {\n checkAuthRateLimit,\n domainResolveAllIpRateLimitConfig,\n} from '@open-mercato/core/modules/customer_accounts/lib/rateLimiter'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('customer_accounts').child({ component: 'domain-resolve-all' })\n\nconst ORIGIN_HEADER_NAME = process.env.CUSTOMER_DOMAIN_ORIGIN_HEADER ?? 'X-Open-Mercato-Origin'\nconst ENDPOINT_PATH = '/api/customer_accounts/domain-resolve/all'\n\nexport const metadata = {\n GET: { requireAuth: false },\n}\n\nfunction withOriginHeader(response: NextResponse): NextResponse {\n response.headers.set(ORIGIN_HEADER_NAME, '1')\n return response\n}\n\nfunction readCallerIp(req: Request): string {\n const forwardedFor = req.headers.get('x-forwarded-for')\n if (forwardedFor) {\n const firstHop = forwardedFor.split(',')[0]?.trim()\n if (firstHop) return firstHop\n }\n const realIp = req.headers.get('x-real-ip')\n if (realIp && realIp.trim().length > 0) return realIp.trim()\n return 'unknown'\n}\n\nexport async function GET(req: Request) {\n const callerIp = readCallerIp(req)\n const expected = process.env.DOMAIN_RESOLVE_SECRET\n if (!expected) {\n // Fail closed when the gating secret is not configured on the server.\n logger.warn('Rejected request \u2014 secret not configured', {\n endpoint: ENDPOINT_PATH,\n ip: callerIp,\n outcome: 'misconfigured',\n })\n return withOriginHeader(\n NextResponse.json(\n { ok: false, error: 'DOMAIN_RESOLVE_SECRET is not configured on the server' },\n { status: 503 },\n ),\n )\n }\n\n // Rate-limit by caller IP before the secret comparison to make leak-driven\n // enumeration noisy and bounded. Fails closed (returns the helper's 429\n // response) when the limit is exceeded.\n const { error: rateLimitError } = await checkAuthRateLimit({\n req,\n ipConfig: domainResolveAllIpRateLimitConfig,\n })\n if (rateLimitError) {\n logger.warn('Rate-limited', {\n endpoint: ENDPOINT_PATH,\n ip: callerIp,\n outcome: 'rate_limited',\n })\n return withOriginHeader(rateLimitError)\n }\n\n const supplied = req.headers.get('x-domain-resolve-secret')\n if (!secretEqual(supplied, expected)) {\n logger.warn('Rejected request \u2014 invalid secret', {\n endpoint: ENDPOINT_PATH,\n ip: callerIp,\n outcome: 'forbidden',\n })\n return withOriginHeader(NextResponse.json({ ok: false, error: 'Forbidden' }, { status: 403 }))\n }\n\n const container = await createRequestContainer()\n const service = container.resolve('domainMappingService') as DomainMappingService\n const records = await service.resolveAll()\n logger.info('Authorized', {\n endpoint: ENDPOINT_PATH,\n ip: callerIp,\n outcome: 'ok',\n domains: records.length,\n })\n return withOriginHeader(\n NextResponse.json({\n ok: true,\n domains: records.map((r) => ({\n hostname: r.hostname,\n tenantId: r.tenantId,\n organizationId: r.organizationId,\n orgSlug: r.orgSlug,\n status: r.status,\n })),\n }),\n )\n}\n\nconst errorSchema = z.object({ ok: z.literal(false), error: z.string() })\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'CustomerAccounts',\n summary: 'Batch resolve all active custom domains',\n methods: {\n GET: {\n summary: 'Batch warm-up for the Node middleware',\n description:\n 'Returns every active domain mapping in a single payload so the middleware can populate its cache on process start. Requires X-Domain-Resolve-Secret header.',\n responses: [\n {\n status: 200,\n description: 'OK',\n schema: z.object({\n ok: z.literal(true),\n domains: z.array(\n z.object({\n hostname: z.string(),\n tenantId: z.string().uuid(),\n organizationId: z.string().uuid(),\n orgSlug: z.string().nullable(),\n status: z.literal('active'),\n }),\n ),\n }),\n },\n ],\n errors: [\n { status: 403, description: 'Forbidden', schema: errorSchema },\n { status: 429, description: 'Too many requests', schema: rateLimitErrorSchema },\n { status: 503, description: 'Server misconfiguration', schema: errorSchema },\n ],\n },\n },\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -23,6 +23,8 @@ import {
|
|
|
23
23
|
TenantResolutionError
|
|
24
24
|
} from "@open-mercato/core/modules/customer_accounts/lib/resolveTenantContext";
|
|
25
25
|
import { urlForCustomerOrg } from "@open-mercato/core/modules/customer_accounts/lib/customerUrl";
|
|
26
|
+
import { createLogger } from "@open-mercato/shared/lib/logger";
|
|
27
|
+
const logger = createLogger("customer_accounts").child({ component: "signup" });
|
|
26
28
|
const metadata = { requireAuth: false };
|
|
27
29
|
const TIMING_EQUALIZATION_HASH = "$2b$10$.F2A6UHFzk.d8trNdfqt4OLz05Nf3IOuMmN6VJKflhD4.rz.prR8i";
|
|
28
30
|
function resolvePortalLoginUrl(baseUrl, organizationSlug) {
|
|
@@ -117,7 +119,7 @@ async function POST(req) {
|
|
|
117
119
|
subject: subject2,
|
|
118
120
|
react: CustomerExistingAccountEmail({ loginUrl, copy: copy2 })
|
|
119
121
|
}).catch((error) => {
|
|
120
|
-
|
|
122
|
+
logger.error("Existing-account email failed", { err: error });
|
|
121
123
|
});
|
|
122
124
|
return NextResponse.json({ ok: true }, { status: 202 });
|
|
123
125
|
}
|
|
@@ -163,7 +165,7 @@ async function POST(req) {
|
|
|
163
165
|
subject,
|
|
164
166
|
react: CustomerSignupVerificationEmail({ verifyUrl, copy })
|
|
165
167
|
}).catch((error) => {
|
|
166
|
-
|
|
168
|
+
logger.error("Verification email failed", { err: error });
|
|
167
169
|
});
|
|
168
170
|
void emitCustomerAccountsEvent("customer_accounts.user.created", {
|
|
169
171
|
id: user.id,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/customer_accounts/api/signup.ts"],
|
|
4
|
-
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { compare as bcryptCompare } from 'bcryptjs'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc, OpenApiMethodDoc } from '@open-mercato/shared/lib/openapi'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { sendEmail } from '@open-mercato/shared/lib/email/send'\nimport { signupSchema } from '@open-mercato/core/modules/customer_accounts/data/validators'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { CustomerUserService } from '@open-mercato/core/modules/customer_accounts/services/customerUserService'\nimport { CustomerTokenService } from '@open-mercato/core/modules/customer_accounts/services/customerTokenService'\nimport { CustomerRole, CustomerUserRole } from '@open-mercato/core/modules/customer_accounts/data/entities'\nimport { emitCustomerAccountsEvent } from '@open-mercato/core/modules/customer_accounts/events'\nimport CustomerSignupVerificationEmail from '@open-mercato/core/modules/customer_accounts/emails/CustomerSignupVerificationEmail'\nimport CustomerExistingAccountEmail from '@open-mercato/core/modules/customer_accounts/emails/CustomerExistingAccountEmail'\nimport { rateLimitErrorSchema } from '@open-mercato/shared/lib/ratelimit/helpers'\nimport {\n checkAuthRateLimit,\n customerSignupRateLimitConfig,\n customerSignupIpRateLimitConfig,\n} from '@open-mercato/core/modules/customer_accounts/lib/rateLimiter'\nimport { readNormalizedEmailFromJsonRequest } from '@open-mercato/core/modules/customer_accounts/lib/rateLimitIdentifier'\nimport { findOrganizationInTenant } from '@open-mercato/core/modules/customer_accounts/lib/organizationLookup'\nimport { getSecurityEmailBaseUrl, mapSecurityEmailUrlError } from '@open-mercato/shared/lib/url'\nimport {\n resolveTenantContext,\n TenantResolutionError,\n} from '@open-mercato/core/modules/customer_accounts/lib/resolveTenantContext'\nimport { urlForCustomerOrg } from '@open-mercato/core/modules/customer_accounts/lib/customerUrl'\n\nexport const metadata: { path?: string; requireAuth?: boolean } = { requireAuth: false }\n\n// Precomputed bcrypt cost-10 hash of an unknowable random 32-byte input; used to equalize\n// response latency between the existing-user and new-user signup branches so the endpoint's\n// 202-for-both contract is not undone by a timing side channel.\nconst TIMING_EQUALIZATION_HASH = '$2b$10$.F2A6UHFzk.d8trNdfqt4OLz05Nf3IOuMmN6VJKflhD4.rz.prR8i'\nfunction resolvePortalLoginUrl(baseUrl: string, organizationSlug?: string | null): string {\n return organizationSlug\n ? `${baseUrl}/${organizationSlug}/portal/login`\n : `${baseUrl}/portal/login`\n}\n\nfunction resolvePortalVerifyUrl(baseUrl: string, token: string, organizationSlug?: string | null): string {\n const route = organizationSlug\n ? `${baseUrl}/${organizationSlug}/portal/verify`\n : `${baseUrl}/portal/verify`\n return `${route}?token=${encodeURIComponent(token)}`\n}\n\nexport async function POST(req: Request) {\n const rateLimitEmail = await readNormalizedEmailFromJsonRequest(req)\n const { error: rateLimitError } = await checkAuthRateLimit({\n req,\n ipConfig: customerSignupIpRateLimitConfig,\n compoundConfig: customerSignupRateLimitConfig,\n compoundIdentifier: rateLimitEmail,\n })\n if (rateLimitError) return rateLimitError\n\n let body: unknown\n try {\n body = await req.json()\n } catch {\n return NextResponse.json({ ok: false, error: 'Invalid request body' }, { status: 400 })\n }\n\n const parsed = signupSchema.safeParse(body)\n if (!parsed.success) {\n return NextResponse.json({ ok: false, error: 'Validation failed', details: parsed.error.flatten().fieldErrors }, { status: 400 })\n }\n\n const { email, password, displayName } = parsed.data\n let tenantId: string\n let organizationId: string | null\n try {\n const context = await resolveTenantContext(req, parsed.data.tenantId, {\n organizationId: parsed.data.organizationId ?? null,\n })\n tenantId = context.tenantId\n organizationId = context.organizationId ?? parsed.data.organizationId ?? null\n } catch (err) {\n if (err instanceof TenantResolutionError) {\n return NextResponse.json({ ok: false, error: err.message }, { status: err.status })\n }\n throw err\n }\n if (!organizationId) {\n return NextResponse.json({ ok: false, error: 'organizationId is required' }, { status: 400 })\n }\n\n let baseUrl: string\n try {\n baseUrl = getSecurityEmailBaseUrl(req)\n } catch (error) {\n const mapped = mapSecurityEmailUrlError(error, {\n scope: 'customer_accounts.signup',\n configMessage: 'Customer signup is not configured',\n })\n if (mapped) return NextResponse.json(mapped.body, { status: mapped.status })\n throw error\n }\n\n const container = await createRequestContainer()\n const customerUserService = container.resolve('customerUserService') as CustomerUserService\n const customerTokenService = container.resolve('customerTokenService') as CustomerTokenService\n const em = container.resolve('em') as import('@mikro-orm/postgresql').EntityManager\n const { translate } = await resolveTranslations()\n\n const orgRow = await findOrganizationInTenant(em, organizationId, tenantId)\n if (!orgRow) {\n return NextResponse.json({ ok: false, error: 'Registration could not be completed' }, { status: 400 })\n }\n\n const existing = await customerUserService.findByEmail(email, tenantId)\n if (existing) {\n await bcryptCompare(password, TIMING_EQUALIZATION_HASH)\n const existingOrg = await findOrganizationInTenant(em, existing.organizationId, tenantId)\n // Prefer the org's active custom domain when available; fall back to the\n // platform login URL preserved by `resolvePortalLoginUrl`.\n let loginUrl = resolvePortalLoginUrl(baseUrl, existingOrg?.slug ?? null)\n try {\n loginUrl = await urlForCustomerOrg(existing.organizationId, '/login', { container })\n } catch {\n // Fall back to platform URL on any resolution issue.\n }\n const subject = translate('customer_accounts.signup.existing.subject', 'You already have a portal account')\n const copy = {\n preview: translate('customer_accounts.signup.existing.preview', 'A sign-up attempt was made for an email that already has a portal account.'),\n title: translate('customer_accounts.signup.existing.title', 'You already have a portal account'),\n body: translate(\n 'customer_accounts.signup.existing.body',\n 'A sign-up request was made for this email address. You can sign in with your existing account. If you forgot your password, use the password reset option on the sign-in page.',\n ),\n cta: translate('customer_accounts.signup.existing.cta', 'Open sign-in page'),\n hint: translate(\n 'customer_accounts.signup.existing.hint',\n 'If this was not you, you can ignore this message. No new portal account was created.',\n ),\n }\n\n void sendEmail({\n to: existing.email,\n subject,\n react: CustomerExistingAccountEmail({ loginUrl, copy }),\n }).catch((error) => {\n console.error('[customer_accounts.signup] existing-account email failed', error)\n })\n\n return NextResponse.json({ ok: true }, { status: 202 })\n }\n\n const user = await customerUserService.createUser(email, password, displayName, { tenantId, organizationId })\n\n const defaultRole = await em.findOne(CustomerRole, {\n tenantId,\n isDefault: true,\n deletedAt: null,\n })\n if (defaultRole) {\n const userRole = em.create(CustomerUserRole, {\n user,\n role: defaultRole,\n createdAt: new Date(),\n } as any)\n em.persist(userRole)\n }\n\n await em.persist(user).flush()\n\n const verificationToken = await customerTokenService.createEmailVerification(user.id, tenantId)\n let verifyUrl = resolvePortalVerifyUrl(baseUrl, verificationToken, orgRow.slug)\n try {\n verifyUrl = await urlForCustomerOrg(organizationId, `/verify?token=${encodeURIComponent(verificationToken)}`, {\n container,\n })\n } catch {\n // Fall back to the platform-derived URL on any resolution issue.\n }\n const subject = translate('customer_accounts.signup.created.subject', 'Verify your portal account')\n const copy = {\n preview: translate('customer_accounts.signup.created.preview', 'Verify your portal account to finish sign-up.'),\n title: translate('customer_accounts.signup.created.title', 'Verify your portal account'),\n body: translate(\n 'customer_accounts.signup.created.body',\n 'Your account request was accepted. Confirm your email address to finish setting up portal access.',\n ),\n cta: translate('customer_accounts.signup.created.cta', 'Verify email address'),\n hint: translate(\n 'customer_accounts.signup.created.hint',\n 'This verification link expires in 24 hours. If you did not request this, you can ignore this email.',\n ),\n }\n\n void sendEmail({\n to: user.email,\n subject,\n react: CustomerSignupVerificationEmail({ verifyUrl, copy }),\n }).catch((error) => {\n console.error('[customer_accounts.signup] verification email failed', error)\n })\n\n void emitCustomerAccountsEvent('customer_accounts.user.created', {\n id: user.id,\n email: user.email,\n tenantId,\n organizationId,\n }).catch(() => undefined)\n\n return NextResponse.json({ ok: true }, { status: 202 })\n}\n\nconst signupAcceptedSchema = z.object({ ok: z.literal(true) })\n\nconst errorSchema = z.object({\n ok: z.literal(false),\n error: z.string(),\n})\n\nconst methodDoc: OpenApiMethodDoc = {\n summary: 'Register a new customer account',\n description: 'Accepts a signup request and always returns 202 to prevent account enumeration.',\n tags: ['Customer Authentication'],\n requestBody: {\n schema: signupSchema,\n description: 'Signup payload with email, password, and display name.',\n },\n responses: [\n { status: 202, description: 'Signup accepted', schema: signupAcceptedSchema },\n ],\n errors: [\n { status: 400, description: 'Validation failed or invalid request origin', schema: errorSchema },\n { status: 429, description: 'Too many signup attempts', schema: rateLimitErrorSchema },\n { status: 500, description: 'Signup email origin is not configured', schema: errorSchema },\n ],\n}\n\nexport const openApi: OpenApiRouteDoc = {\n summary: 'Customer account registration',\n description: 'Handles customer self-registration without revealing whether the email already exists.',\n methods: { POST: methodDoc },\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,WAAW,qBAAqB;AACzC,SAAS,SAAS;AAElB,SAAS,2BAA2B;AACpC,SAAS,iBAAiB;AAC1B,SAAS,oBAAoB;AAC7B,SAAS,8BAA8B;AAGvC,SAAS,cAAc,wBAAwB;AAC/C,SAAS,iCAAiC;AAC1C,OAAO,qCAAqC;AAC5C,OAAO,kCAAkC;AACzC,SAAS,4BAA4B;AACrC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,0CAA0C;AACnD,SAAS,gCAAgC;AACzC,SAAS,yBAAyB,gCAAgC;AAClE;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,yBAAyB;
|
|
4
|
+
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { compare as bcryptCompare } from 'bcryptjs'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc, OpenApiMethodDoc } from '@open-mercato/shared/lib/openapi'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { sendEmail } from '@open-mercato/shared/lib/email/send'\nimport { signupSchema } from '@open-mercato/core/modules/customer_accounts/data/validators'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { CustomerUserService } from '@open-mercato/core/modules/customer_accounts/services/customerUserService'\nimport { CustomerTokenService } from '@open-mercato/core/modules/customer_accounts/services/customerTokenService'\nimport { CustomerRole, CustomerUserRole } from '@open-mercato/core/modules/customer_accounts/data/entities'\nimport { emitCustomerAccountsEvent } from '@open-mercato/core/modules/customer_accounts/events'\nimport CustomerSignupVerificationEmail from '@open-mercato/core/modules/customer_accounts/emails/CustomerSignupVerificationEmail'\nimport CustomerExistingAccountEmail from '@open-mercato/core/modules/customer_accounts/emails/CustomerExistingAccountEmail'\nimport { rateLimitErrorSchema } from '@open-mercato/shared/lib/ratelimit/helpers'\nimport {\n checkAuthRateLimit,\n customerSignupRateLimitConfig,\n customerSignupIpRateLimitConfig,\n} from '@open-mercato/core/modules/customer_accounts/lib/rateLimiter'\nimport { readNormalizedEmailFromJsonRequest } from '@open-mercato/core/modules/customer_accounts/lib/rateLimitIdentifier'\nimport { findOrganizationInTenant } from '@open-mercato/core/modules/customer_accounts/lib/organizationLookup'\nimport { getSecurityEmailBaseUrl, mapSecurityEmailUrlError } from '@open-mercato/shared/lib/url'\nimport {\n resolveTenantContext,\n TenantResolutionError,\n} from '@open-mercato/core/modules/customer_accounts/lib/resolveTenantContext'\nimport { urlForCustomerOrg } from '@open-mercato/core/modules/customer_accounts/lib/customerUrl'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('customer_accounts').child({ component: 'signup' })\n\nexport const metadata: { path?: string; requireAuth?: boolean } = { requireAuth: false }\n\n// Precomputed bcrypt cost-10 hash of an unknowable random 32-byte input; used to equalize\n// response latency between the existing-user and new-user signup branches so the endpoint's\n// 202-for-both contract is not undone by a timing side channel.\nconst TIMING_EQUALIZATION_HASH = '$2b$10$.F2A6UHFzk.d8trNdfqt4OLz05Nf3IOuMmN6VJKflhD4.rz.prR8i'\nfunction resolvePortalLoginUrl(baseUrl: string, organizationSlug?: string | null): string {\n return organizationSlug\n ? `${baseUrl}/${organizationSlug}/portal/login`\n : `${baseUrl}/portal/login`\n}\n\nfunction resolvePortalVerifyUrl(baseUrl: string, token: string, organizationSlug?: string | null): string {\n const route = organizationSlug\n ? `${baseUrl}/${organizationSlug}/portal/verify`\n : `${baseUrl}/portal/verify`\n return `${route}?token=${encodeURIComponent(token)}`\n}\n\nexport async function POST(req: Request) {\n const rateLimitEmail = await readNormalizedEmailFromJsonRequest(req)\n const { error: rateLimitError } = await checkAuthRateLimit({\n req,\n ipConfig: customerSignupIpRateLimitConfig,\n compoundConfig: customerSignupRateLimitConfig,\n compoundIdentifier: rateLimitEmail,\n })\n if (rateLimitError) return rateLimitError\n\n let body: unknown\n try {\n body = await req.json()\n } catch {\n return NextResponse.json({ ok: false, error: 'Invalid request body' }, { status: 400 })\n }\n\n const parsed = signupSchema.safeParse(body)\n if (!parsed.success) {\n return NextResponse.json({ ok: false, error: 'Validation failed', details: parsed.error.flatten().fieldErrors }, { status: 400 })\n }\n\n const { email, password, displayName } = parsed.data\n let tenantId: string\n let organizationId: string | null\n try {\n const context = await resolveTenantContext(req, parsed.data.tenantId, {\n organizationId: parsed.data.organizationId ?? null,\n })\n tenantId = context.tenantId\n organizationId = context.organizationId ?? parsed.data.organizationId ?? null\n } catch (err) {\n if (err instanceof TenantResolutionError) {\n return NextResponse.json({ ok: false, error: err.message }, { status: err.status })\n }\n throw err\n }\n if (!organizationId) {\n return NextResponse.json({ ok: false, error: 'organizationId is required' }, { status: 400 })\n }\n\n let baseUrl: string\n try {\n baseUrl = getSecurityEmailBaseUrl(req)\n } catch (error) {\n const mapped = mapSecurityEmailUrlError(error, {\n scope: 'customer_accounts.signup',\n configMessage: 'Customer signup is not configured',\n })\n if (mapped) return NextResponse.json(mapped.body, { status: mapped.status })\n throw error\n }\n\n const container = await createRequestContainer()\n const customerUserService = container.resolve('customerUserService') as CustomerUserService\n const customerTokenService = container.resolve('customerTokenService') as CustomerTokenService\n const em = container.resolve('em') as import('@mikro-orm/postgresql').EntityManager\n const { translate } = await resolveTranslations()\n\n const orgRow = await findOrganizationInTenant(em, organizationId, tenantId)\n if (!orgRow) {\n return NextResponse.json({ ok: false, error: 'Registration could not be completed' }, { status: 400 })\n }\n\n const existing = await customerUserService.findByEmail(email, tenantId)\n if (existing) {\n await bcryptCompare(password, TIMING_EQUALIZATION_HASH)\n const existingOrg = await findOrganizationInTenant(em, existing.organizationId, tenantId)\n // Prefer the org's active custom domain when available; fall back to the\n // platform login URL preserved by `resolvePortalLoginUrl`.\n let loginUrl = resolvePortalLoginUrl(baseUrl, existingOrg?.slug ?? null)\n try {\n loginUrl = await urlForCustomerOrg(existing.organizationId, '/login', { container })\n } catch {\n // Fall back to platform URL on any resolution issue.\n }\n const subject = translate('customer_accounts.signup.existing.subject', 'You already have a portal account')\n const copy = {\n preview: translate('customer_accounts.signup.existing.preview', 'A sign-up attempt was made for an email that already has a portal account.'),\n title: translate('customer_accounts.signup.existing.title', 'You already have a portal account'),\n body: translate(\n 'customer_accounts.signup.existing.body',\n 'A sign-up request was made for this email address. You can sign in with your existing account. If you forgot your password, use the password reset option on the sign-in page.',\n ),\n cta: translate('customer_accounts.signup.existing.cta', 'Open sign-in page'),\n hint: translate(\n 'customer_accounts.signup.existing.hint',\n 'If this was not you, you can ignore this message. No new portal account was created.',\n ),\n }\n\n void sendEmail({\n to: existing.email,\n subject,\n react: CustomerExistingAccountEmail({ loginUrl, copy }),\n }).catch((error) => {\n logger.error('Existing-account email failed', { err: error })\n })\n\n return NextResponse.json({ ok: true }, { status: 202 })\n }\n\n const user = await customerUserService.createUser(email, password, displayName, { tenantId, organizationId })\n\n const defaultRole = await em.findOne(CustomerRole, {\n tenantId,\n isDefault: true,\n deletedAt: null,\n })\n if (defaultRole) {\n const userRole = em.create(CustomerUserRole, {\n user,\n role: defaultRole,\n createdAt: new Date(),\n } as any)\n em.persist(userRole)\n }\n\n await em.persist(user).flush()\n\n const verificationToken = await customerTokenService.createEmailVerification(user.id, tenantId)\n let verifyUrl = resolvePortalVerifyUrl(baseUrl, verificationToken, orgRow.slug)\n try {\n verifyUrl = await urlForCustomerOrg(organizationId, `/verify?token=${encodeURIComponent(verificationToken)}`, {\n container,\n })\n } catch {\n // Fall back to the platform-derived URL on any resolution issue.\n }\n const subject = translate('customer_accounts.signup.created.subject', 'Verify your portal account')\n const copy = {\n preview: translate('customer_accounts.signup.created.preview', 'Verify your portal account to finish sign-up.'),\n title: translate('customer_accounts.signup.created.title', 'Verify your portal account'),\n body: translate(\n 'customer_accounts.signup.created.body',\n 'Your account request was accepted. Confirm your email address to finish setting up portal access.',\n ),\n cta: translate('customer_accounts.signup.created.cta', 'Verify email address'),\n hint: translate(\n 'customer_accounts.signup.created.hint',\n 'This verification link expires in 24 hours. If you did not request this, you can ignore this email.',\n ),\n }\n\n void sendEmail({\n to: user.email,\n subject,\n react: CustomerSignupVerificationEmail({ verifyUrl, copy }),\n }).catch((error) => {\n logger.error('Verification email failed', { err: error })\n })\n\n void emitCustomerAccountsEvent('customer_accounts.user.created', {\n id: user.id,\n email: user.email,\n tenantId,\n organizationId,\n }).catch(() => undefined)\n\n return NextResponse.json({ ok: true }, { status: 202 })\n}\n\nconst signupAcceptedSchema = z.object({ ok: z.literal(true) })\n\nconst errorSchema = z.object({\n ok: z.literal(false),\n error: z.string(),\n})\n\nconst methodDoc: OpenApiMethodDoc = {\n summary: 'Register a new customer account',\n description: 'Accepts a signup request and always returns 202 to prevent account enumeration.',\n tags: ['Customer Authentication'],\n requestBody: {\n schema: signupSchema,\n description: 'Signup payload with email, password, and display name.',\n },\n responses: [\n { status: 202, description: 'Signup accepted', schema: signupAcceptedSchema },\n ],\n errors: [\n { status: 400, description: 'Validation failed or invalid request origin', schema: errorSchema },\n { status: 429, description: 'Too many signup attempts', schema: rateLimitErrorSchema },\n { status: 500, description: 'Signup email origin is not configured', schema: errorSchema },\n ],\n}\n\nexport const openApi: OpenApiRouteDoc = {\n summary: 'Customer account registration',\n description: 'Handles customer self-registration without revealing whether the email already exists.',\n methods: { POST: methodDoc },\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["subject", "copy"]
|
|
7
7
|
}
|
|
@@ -5,6 +5,8 @@ import { CUSTOMER_JWT_AUDIENCE } from "@open-mercato/core/modules/customer_accou
|
|
|
5
5
|
import { tryNormalizeHostname } from "@open-mercato/core/modules/customer_accounts/lib/hostname";
|
|
6
6
|
import { platformDomains } from "@open-mercato/core/modules/customer_accounts/lib/platformDomains";
|
|
7
7
|
import { validateUserState } from "./customerAuth.js";
|
|
8
|
+
import { createLogger } from "@open-mercato/shared/lib/logger";
|
|
9
|
+
const logger = createLogger("customer_accounts").child({ component: "customer-auth-server" });
|
|
8
10
|
async function assertSessionStillActive(sessionId) {
|
|
9
11
|
try {
|
|
10
12
|
const container = await createRequestContainer();
|
|
@@ -66,7 +68,7 @@ async function getCustomerAuthForHost(host) {
|
|
|
66
68
|
if (!resolved || resolved.status !== "active") return null;
|
|
67
69
|
return getCustomerAuthFromCookies({ expectedTenantId: resolved.tenantId });
|
|
68
70
|
} catch (err) {
|
|
69
|
-
|
|
71
|
+
logger.warn("Domain resolve failed; falling back to platform cookie", { err });
|
|
70
72
|
return getCustomerAuthFromCookies();
|
|
71
73
|
}
|
|
72
74
|
}
|